diff --git a/DEPS b/DEPS
index ca8321f..dec3d3d 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': 'b284280be4cc15bd13bc8c53b9f486d027fcc939',
+  'skia_revision': '6668a514ac5d507359a885480cbaabd812ef92db',
   # 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': 'd729403cd1d7b25f51637aa900527903b8837ced',
+  'v8_revision': '4c27ac5c13df9499357e04985bd7de55dd61e062',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2160821e16dbc4f2715422940df914ed5e77bf92',
+  'angle_revision': '5188a2747b404b0aac332a3f866e94bdfcd8bb99',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '84d3394d88c42b798eedc938e6295ad1bf28ac66',
+  'pdfium_revision': '1f7db295b1deeecb562d6213b3ea17b9168405eb',
   # 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': 'd35e4d092bb2d9679134112afdf321ce447adfbe',
+  'catapult_revision': 'b76f0192a83adb19a2e97595bca2086186145eb2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -278,7 +278,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '89ba326620341ca7950621cf24da78864d6ee895',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '98397e899bd994fb1b42f1dc15ef8a6c7357ae2f',
       'condition': 'checkout_ios',
   },
 
@@ -539,7 +539,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'cb29fbd231d64bbc5d23bbf04fb47637111b71bb',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7dc67f1a80f0e43c1ef8004494da76ec53e8b612',
       'condition': 'checkout_linux',
   },
 
@@ -768,7 +768,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'd955c63ec7048d59dffd20af25eeec23da878d27',
 
   'src/third_party/libaom/source/libaom': {
-    'url': Var('aomedia_git') + '/aom.git' + '@' +  '88e4b0a4ee32d39371e15040fa0a1ee7c9d8a19d',
+    'url': Var('aomedia_git') + '/aom.git' + '@' +  '0415f2e501a2ef3282771d7500e9a325068436cb',
     'condition': 'checkout_libaom',
   },
 
@@ -912,7 +912,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'b1589ae6be41855308a22948da3967a381ef703a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'e0f20f1882cb7b47877ebda0d5dceb2174441745',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1034,7 +1034,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'e71d1bb7fc22c7a08f34391b69c722d07c2100f2',
+    Var('webrtc_git') + '/src.git' + '@' + 'a3df0f2d05c7b0973c31fe171507e97e588671a5',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1068,7 +1068,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@eade4f0eac2e7a0f73fdd436d8289dca03ab773b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@442a61600537d67a9631c60e370cf4556a66b130',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index e6173fc..206b318 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -658,6 +658,7 @@
               'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
               'src-internal', 'webrtc')
   ) | set('%s@appspot.gserviceaccount.com' % s for s in ('findit-for-me',)
+  ) | set('%s@developer.gserviceaccount.com' % s for s in ('3su6n15k.default',)
   ) | set('%s@chops-service-accounts.iam.gserviceaccount.com' % s
           for s in ('v8-ci-autoroll-builder',))
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 8203c67..19a7517 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1796,7 +1796,7 @@
     'blink_bluetooth': ['mattreynolds+watch@chromium.org',
                         'ortuno+watch@chromium.org'],
     'blink_canvas2d': ['dongseong.hwang@intel.com',
-                       'junov@chromium.org'],
+                       'fserb@chromium.org'],
     'blink_client_hints': ['yoav@yoav.ws'],
     'blink_clipboard': ['dcheng@chromium.org'],
     'blink_common': ['jbroman+watch@chromium.org',
@@ -1882,7 +1882,7 @@
                                 'drott+blinkwatch@chromium.org',
                                 'dschulze@chromium.org',
                                 'fmalita+watch@chromium.org',
-                                'junov@chromium.org',
+                                'fserb@chromium.org',
                                 'pdr+graphicswatchlist@chromium.org',
                                 'schenney@chromium.org'],
     'blink_preloadScanner': ['yoav@yoav.ws'],
diff --git a/android_webview/browser/aw_variations_service_client.cc b/android_webview/browser/aw_variations_service_client.cc
index ca60e71..d505bc8 100644
--- a/android_webview/browser/aw_variations_service_client.cc
+++ b/android_webview/browser/aw_variations_service_client.cc
@@ -11,6 +11,8 @@
 #include "components/version_info/version_info.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
+using version_info::Channel;
+
 namespace android_webview {
 namespace {
 
@@ -46,8 +48,18 @@
   return nullptr;
 }
 
-version_info::Channel AwVariationsServiceClient::GetChannel() {
-  return version_info::GetChannel();
+Channel AwVariationsServiceClient::GetChannel() {
+  Channel channel = version_info::GetChannel();
+  // There are separate Monochrome APKs built for each channel, but only one
+  // stand-alone WebView APK for all channels, so stand-alone WebView has
+  // channel "unknown". Pretend stand-alone WebView is always "stable" for the
+  // purpose of variations. This simplifies experiment design, since stand-alone
+  // WebView need not be considered separately when choosing channels.
+  return channel == Channel::UNKNOWN ? Channel::STABLE : channel;
+}
+
+bool AwVariationsServiceClient::GetSupportsPermanentConsistency() {
+  return false;
 }
 
 bool AwVariationsServiceClient::OverridesRestrictParameter(
diff --git a/android_webview/browser/aw_variations_service_client.h b/android_webview/browser/aw_variations_service_client.h
index afcac6b..0caf0fd 100644
--- a/android_webview/browser/aw_variations_service_client.h
+++ b/android_webview/browser/aw_variations_service_client.h
@@ -31,6 +31,7 @@
   scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
   network_time::NetworkTimeTracker* GetNetworkTimeTracker() override;
   version_info::Channel GetChannel() override;
+  bool GetSupportsPermanentConsistency() override;
   bool OverridesRestrictParameter(std::string* parameter) override;
 
   DISALLOW_COPY_AND_ASSIGN(AwVariationsServiceClient);
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc
index 5122f9dd..511987a7 100644
--- a/ash/host/ash_window_tree_host_platform.cc
+++ b/ash/host/ash_window_tree_host_platform.cc
@@ -54,10 +54,7 @@
   if (!allow_confine_cursor())
     return;
 
-  // We want to limit the cursor to what is visible, which is the size of the
-  // compositor. |GetBoundsInPixels()| may include pixels that are not used.
-  // See https://crbug.com/843354
-  gfx::Rect confined_bounds(GetCompositorSizeInPixels());
+  gfx::Rect confined_bounds(GetBoundsInPixels().size());
   confined_bounds.Inset(transformer_helper_.GetHostInsets());
   last_cursor_confine_bounds_in_pixels_ = confined_bounds;
   platform_window()->ConfineCursorToBounds(confined_bounds);
@@ -165,33 +162,6 @@
   ConfineCursorToRootWindow();
 }
 
-gfx::Size AshWindowTreeHostPlatform::GetCompositorSizeInPixels() const {
-  // For Chrome OS, the platform window size may be slightly different from the
-  // compositor pixel size. This is to prevent any trailing 1px line at the
-  // right or bottom edge due to rounding. This means we may not be using ALL
-  // the pixels on a display, however this is a temporary fix until we figure
-  // out a way to prevent these rounding artifacts.
-  // See https://crbug.com/843354 and https://crbug.com/862424 for more info.
-  if (device_scale_factor() == 1.f)
-    return GetBoundsInPixels().size();
-  return gfx::ScaleToRoundedSize(
-      gfx::ScaleToFlooredSize(GetBoundsInPixels().size(),
-                              1.f / device_scale_factor()),
-      device_scale_factor());
-}
-
-void AshWindowTreeHostPlatform::OnBoundsChanged(const gfx::Rect& new_bounds) {
-  // We need to recompute the bounds in pixels based on the DIP size. This is a
-  // temporary fix needed because the root layer has the bounds in DIP which
-  // when scaled by the compositor does not match the display bounds in pixels.
-  // So we need to change the display bounds to match the root layer's scaled
-  // size.
-  // See https://crbug.com/843354 for more info.
-  const float new_scale = ui::GetScaleFactorForNativeView(window());
-  WindowTreeHostPlatform::OnBoundsChanged(gfx::ScaleToRoundedRect(
-      gfx::ScaleToEnclosedRect(new_bounds, 1.f / new_scale), new_scale));
-}
-
 void AshWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
   TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
   if (event->IsLocatedEvent())
diff --git a/ash/host/ash_window_tree_host_platform.h b/ash/host/ash_window_tree_host_platform.h
index 5b25a482..339cabc 100644
--- a/ash/host/ash_window_tree_host_platform.h
+++ b/ash/host/ash_window_tree_host_platform.h
@@ -61,8 +61,6 @@
   void OnCursorVisibilityChangedNative(bool show) override;
   void SetBoundsInPixels(const gfx::Rect& bounds,
                          const viz::LocalSurfaceId& local_surface_id) override;
-  gfx::Size GetCompositorSizeInPixels() const override;
-  void OnBoundsChanged(const gfx::Rect& new_bounds) override;
   void DispatchEvent(ui::Event* event) override;
 
   // aura::InputMethodMusDelegate:
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 7f52f9a..44c719a 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -315,16 +315,11 @@
   }
 }
 
-void LoginScreenController::LoadUsers(
-    std::vector<mojom::LoginUserInfoPtr> users,
-    bool show_guest) {
+void LoginScreenController::SetUserList(
+    std::vector<mojom::LoginUserInfoPtr> users) {
   DCHECK(DataDispatcher());
 
   DataDispatcher()->NotifyUsers(users);
-  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
-      ->shelf_widget()
-      ->login_shelf_view()
-      ->SetAllowLoginAsGuest(show_guest);
 }
 
 void LoginScreenController::SetPinEnabledForUser(const AccountId& account_id,
@@ -414,11 +409,19 @@
       ->SetKioskApps(std::move(kiosk_apps));
 }
 
-void LoginScreenController::NotifyOobeDialogVisibility(bool visible) {
+void LoginScreenController::NotifyOobeDialogState(
+    mojom::OobeDialogState state) {
   Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
       ->shelf_widget()
       ->login_shelf_view()
-      ->SetLoginDialogVisible(visible);
+      ->SetLoginDialogState(state);
+}
+
+void LoginScreenController::SetAllowLoginAsGuest(bool allow_guest) {
+  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
+      ->shelf_widget()
+      ->login_shelf_view()
+      ->SetAllowLoginAsGuest(allow_guest);
 }
 
 void LoginScreenController::SetAddUserButtonEnabled(bool enable) {
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index 3aa7d02..dff21e0 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -111,8 +111,7 @@
   void SetAuthType(const AccountId& account_id,
                    proximity_auth::mojom::AuthType auth_type,
                    const base::string16& initial_value) override;
-  void LoadUsers(std::vector<mojom::LoginUserInfoPtr> users,
-                 bool show_guest) override;
+  void SetUserList(std::vector<mojom::LoginUserInfoPtr> users) override;
   void SetPinEnabledForUser(const AccountId& account_id,
                             bool is_enabled) override;
   void SetAvatarForUser(const AccountId& account_id,
@@ -139,8 +138,9 @@
   void SetFingerprintUnlockState(const AccountId& account_id,
                                  mojom::FingerprintUnlockState state) override;
   void SetKioskApps(std::vector<mojom::KioskAppInfoPtr> kiosk_apps) override;
-  void NotifyOobeDialogVisibility(bool is_visible) override;
+  void NotifyOobeDialogState(mojom::OobeDialogState state) override;
   void SetAddUserButtonEnabled(bool enable) override;
+  void SetAllowLoginAsGuest(bool allow_guest) override;
 
   // Flushes the mojo pipes - to be used in tests.
   void FlushForTesting();
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index 74ebd63b2..f7a9ed20 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -1722,4 +1722,22 @@
   EXPECT_TRUE(login_views_utils::HasFocusInAnyChildView(primary_password_view));
 }
 
+TEST_F(LockContentsViewUnitTest, PowerwashShortcutSendsMojoCall) {
+  auto* contents = new LockContentsView(
+      mojom::TrayActionState::kNotAvailable, LockScreen::ScreenType::kLock,
+      data_dispatcher(),
+      std::make_unique<FakeLoginDetachableBaseModel>(data_dispatcher()));
+  SetUserCount(1);
+  SetWidget(CreateWidgetWithContent(contents));
+
+  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  EXPECT_CALL(*client, ShowResetScreen());
+
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->PressKey(ui::KeyboardCode::VKEY_R, ui::EF_CONTROL_DOWN |
+                                                    ui::EF_ALT_DOWN |
+                                                    ui::EF_SHIFT_DOWN);
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace ash
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index 2b9c593..08df062 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -12,6 +12,33 @@
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/public/mojom/base/time.mojom";
 
+// State of the Oobe UI dialog.
+enum OobeDialogState {
+  // Oobe UI dialog is currently hidden.
+  HIDDEN,
+
+  // Showing gaia signin screen.
+  GAIA_SIGNIN,
+
+  // Showing wrong hardware identification screen.
+  WRONG_HWID_WARNING,
+
+  // Showing supervised user creation screen.
+  SUPERVISED_USER_CREATION_FLOW,
+
+  // Showing SAML password confirmation screen.
+  SAML_PASSWORD_CONFIRM,
+
+  // Showing password changed screen.
+  PASSWORD_CHANGED,
+
+  // Showing device enrollment screen.
+  ENROLLMENT,
+
+  // Showing error screen.
+  ERROR,
+};
+
 // Allows clients (e.g. Chrome browser) to control the ash login/lock/user-add
 // screens.
 interface LoginScreen {
@@ -59,10 +86,9 @@
               proximity_auth.mojom.AuthType auth_type,
               mojo_base.mojom.String16 initial_value);
 
-  // Requests to load users in the lock screen.
-  // |users|:      A list of users who can unlock the device.
-  // |show_guest|: Whether to show guest session button.
-  LoadUsers(array<LoginUserInfo> users, bool show_guest);
+  // Set the users who are displayed on the login UI. |users| is filtered
+  // and does not correspond to every user on the device.
+  SetUserList(array<LoginUserInfo> users);
 
   // Notification if pin is enabled or disabled for the given user.
   // |account_id|:   The account id of the user in the user pod.
@@ -130,13 +156,17 @@
   // Update the kiosk app data for the login screen.
   SetKioskApps(array<KioskAppInfo> kiosk_apps);
 
-  // Called when the dialog hosting oobe has changed visibility. The oobe dialog
+  // Called when the dialog hosting oobe has changed state. The oobe dialog
   // provides support for any part of login that is implemented in JS/HTML, such
   // as add user or powerwash.
-  NotifyOobeDialogVisibility(bool is_visible);
+  NotifyOobeDialogState(OobeDialogState state);
 
   // Sets whether users can be added from the login screen.
   SetAddUserButtonEnabled(bool enable);
+
+  // Sets if the guest button on the login shelf can be shown. Even if set to
+  // true the button may still not be visible.
+  SetAllowLoginAsGuest(bool allow_guest);
 };
 
 // Allows ash lock screen to control a client (e.g. Chrome browser). Requests
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 1cab347b..cfa2f6e 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -410,8 +410,8 @@
   UpdateUi();
 }
 
-void LoginShelfView::SetLoginDialogVisible(bool visible) {
-  dialog_visible_ = visible;
+void LoginShelfView::SetLoginDialogState(mojom::OobeDialogState state) {
+  dialog_state_ = state;
   UpdateUi();
 }
 
@@ -478,12 +478,33 @@
   // TODO(agawronska): Implement full list of conditions for buttons visibility,
   // when views based shelf if enabled during OOBE. https://crbug.com/798869
   bool is_login_primary = (session_state == SessionState::LOGIN_PRIMARY);
-  GetViewByID(kBrowseAsGuest)
-      ->SetVisible(allow_guest_ && !dialog_visible_ && is_login_primary);
-  GetViewByID(kAddUser)->SetVisible(!dialog_visible_ && is_login_primary);
-  kiosk_apps_button_->SetVisible(
-      !dialog_visible_ && kiosk_apps_button_->HasApps() && is_login_primary);
+  bool dialog_visible = dialog_state_ != mojom::OobeDialogState::HIDDEN;
 
+  // Show guest button if:
+  // 1. It's in login screen.
+  // 2. Guest login is allowed.
+  // 3. OOBE UI dialog is not currently showing wrong HWID warning screen or
+  // SAML password confirmation screen.
+  GetViewByID(kBrowseAsGuest)
+      ->SetVisible(
+          allow_guest_ &&
+          dialog_state_ != mojom::OobeDialogState::WRONG_HWID_WARNING &&
+          dialog_state_ != mojom::OobeDialogState::SAML_PASSWORD_CONFIRM &&
+          is_login_primary);
+
+  // Show add user button when it's in login screen and OobeUI dialog is not
+  // visible.
+  GetViewByID(kAddUser)->SetVisible(!dialog_visible && is_login_primary);
+
+  // Show kiosk apps button if:
+  // 1. It's in login screen.
+  // 2. There're Kiosk apps availble.
+  // 3. Oobe UI dialog is not visible or is currently showing gaia signin
+  // screen.
+  kiosk_apps_button_->SetVisible(
+      (!dialog_visible ||
+       dialog_state_ == mojom::OobeDialogState::GAIA_SIGNIN) &&
+      kiosk_apps_button_->HasApps() && is_login_primary);
   Layout();
 }
 
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 5e7ddbe..68e92bd 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "ash/lock_screen_action/lock_screen_action_background_observer.h"
 #include "ash/public/interfaces/kiosk_app_info.mojom.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/shutdown_controller.h"
 #include "ash/tray_action/tray_action_observer.h"
 #include "base/scoped_observer.h"
@@ -63,9 +64,8 @@
   // Sets the list of kiosk apps that can be launched from the login shelf.
   void SetKioskApps(std::vector<mojom::KioskAppInfoPtr> kiosk_apps);
 
-  // Sets if the login dialog is visible. This hides some of the buttons on the
-  // LoginShelf.
-  void SetLoginDialogVisible(bool visible);
+  // Sets the state of the login dialog.
+  void SetLoginDialogState(mojom::OobeDialogState state);
 
   // Sets if the guest button on the login shelf can be shown. Even if set to
   // true the button may still not be visible.
@@ -101,7 +101,7 @@
   // policy updates, session state changes etc.
   void UpdateUi();
 
-  bool dialog_visible_ = false;
+  mojom::OobeDialogState dialog_state_ = mojom::OobeDialogState::HIDDEN;
   bool allow_guest_ = true;
 
   LockScreenActionBackgroundController* lock_screen_action_background_;
diff --git a/ash/shelf/login_shelf_view_unittest.cc b/ash/shelf/login_shelf_view_unittest.cc
index a15cdea..0b71fd8e 100644
--- a/ash/shelf/login_shelf_view_unittest.cc
+++ b/ash/shelf/login_shelf_view_unittest.cc
@@ -291,23 +291,68 @@
 
   // However, SetAllowLoginAsGuest(true) does not mean that the guest button is
   // always visible.
-  login_shelf_view_->SetLoginDialogVisible(true);
+  login_shelf_view_->SetLoginDialogState(
+      mojom::OobeDialogState::SAML_PASSWORD_CONFIRM);
   EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
 }
 
-TEST_F(LoginShelfViewTest, ShouldUpdateUiAfterDialogVisibilityChange) {
+TEST_F(LoginShelfViewTest, ShouldUpdateUiAfterDialogStateChange) {
   NotifySessionStateChanged(SessionState::LOGIN_PRIMARY);
   EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown,
                                  LoginShelfView::kBrowseAsGuest,
                                  LoginShelfView::kAddUser}));
 
-  login_shelf_view_->SetLoginDialogVisible(true);
-  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
+  // Add user button is always hidden if dialog state !=
+  // OobeDialogState::HIDDEN.
+  login_shelf_view_->SetLoginDialogState(mojom::OobeDialogState::GAIA_SIGNIN);
+  EXPECT_TRUE(ShowsShelfButtons(
+      {LoginShelfView::kShutdown, LoginShelfView::kBrowseAsGuest}));
 
-  login_shelf_view_->SetLoginDialogVisible(false);
+  login_shelf_view_->SetLoginDialogState(mojom::OobeDialogState::HIDDEN);
   EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown,
                                  LoginShelfView::kBrowseAsGuest,
                                  LoginShelfView::kAddUser}));
+
+  // Guest button is hidden if dialog state ==
+  // OobeDialogState::WRONG_HWID_WARNING or SAML_PASSWORD_CONFIRM.
+  login_shelf_view_->SetLoginDialogState(
+      mojom::OobeDialogState::WRONG_HWID_WARNING);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
+
+  login_shelf_view_->SetLoginDialogState(
+      mojom::OobeDialogState::SAML_PASSWORD_CONFIRM);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
+
+  login_shelf_view_->SetLoginDialogState(mojom::OobeDialogState::GAIA_SIGNIN);
+  EXPECT_TRUE(ShowsShelfButtons(
+      {LoginShelfView::kShutdown, LoginShelfView::kBrowseAsGuest}));
+
+  // Guest button is hidden if SetAllowLoginAsGuest(false).
+  login_shelf_view_->SetAllowLoginAsGuest(false /*allow_guest*/);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
+
+  // Kiosk app button is visible when dialog state == OobeDialogState::HIDDEN
+  // or GAIA_SIGNIN.
+  login_shelf_view_->SetLoginDialogState(mojom::OobeDialogState::GAIA_SIGNIN);
+  std::vector<mojom::KioskAppInfoPtr> kiosk_apps;
+  kiosk_apps.push_back(mojom::KioskAppInfo::New());
+  login_shelf_view_->SetKioskApps(std::move(kiosk_apps));
+  EXPECT_TRUE(
+      ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kApps}));
+
+  login_shelf_view_->SetLoginDialogState(
+      mojom::OobeDialogState::SAML_PASSWORD_CONFIRM);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown}));
+
+  login_shelf_view_->SetLoginDialogState(mojom::OobeDialogState::HIDDEN);
+  EXPECT_TRUE(
+      ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kAddUser,
+                         LoginShelfView::kApps}));
+
+  // Kiosk app button is hidden when no app exists.
+  login_shelf_view_->SetKioskApps(std::vector<mojom::KioskAppInfoPtr>());
+  EXPECT_TRUE(
+      ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kAddUser}));
 }
 
 TEST_F(LoginShelfViewTest, ClickShutdownButton) {
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index ce990ffa6..9e5676a 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -62,6 +62,48 @@
 
 // ShelfView contains the shelf items visible within an active user session.
 // ShelfView and LoginShelfView should never be shown together.
+
+// In the following example, there are 12 apps to place on the shelf, plus
+// the app list and back buttons, which make 14 shelf items in total.
+//
+// If there is enough screen space, all icons can fit:
+//
+// -----------------------------------------------------------------
+// | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 |
+// -----------------------------------------------------------------
+//   ^                                               ^
+//   |                                               |
+// first_visible_index = 0                 last_visible_index = 13
+// (back button = 0 is hidden)             last_hidden_index = 13
+//
+// Where:
+//     0 = back button (only shown in tablet mode)
+//     1 = app list button
+//
+// If screen space is more constrained, some icons are placed in an overflow
+// menu (which holds its own instance of ShelfView):
+//
+//            first_visible_index = 10    last_hidden_index = 13
+//               (for the overflow)     last_visible_index = 13 (for overflow)
+//                                |               |
+//                                v               v
+//                              ---------------------
+//                              | 10 | 11 | 12 | 13 |
+//                              ---------------------
+//                                        ^
+// -------------------------------------------
+// | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |
+// -------------------------------------------
+//   ^                                    ^
+//   |                                    |
+// first_visible_index = 0       last_visible_index = 10
+//   (for the main shelf)         (the overflow button)
+//  (back button = 0
+//           is hidden)
+//
+// Note that last_visible_index is 10 (not 9) even though the overflow button
+// doesn't shift the array of indices.
+
 class ASH_EXPORT ShelfView : public views::View,
                              public ShelfModelObserver,
                              public InkDropButtonListener,
diff --git a/ash/strings/ash_strings_ar.xtb b/ash/strings/ash_strings_ar.xtb
index 1b9a11c..c62963d 100644
--- a/ash/strings/ash_strings_ar.xtb
+++ b/ash/strings/ash_strings_ar.xtb
@@ -191,6 +191,7 @@
 <translation id="4544944664594876241">لقد تغير اختصار قفل الشاشة. يُرجى استخدام <ph name="NEW_SHORTCUT" /> بدلاً من <ph name="OLD_SHORTCUT" />.</translation>
 <translation id="4564869809620998694">خدمة الخطوط</translation>
 <translation id="4570957409596482333">زر "سماع الاختيار"</translation>
+<translation id="4585337515783392668">إيقاف الإرسال إلى مستلم غير معروف</translation>
 <translation id="4628757576491864469">الأجهزة</translation>
 <translation id="4659419629803378708">‏تم تفعيل ChromeVox</translation>
 <translation id="4734965478015604180">أفقي</translation>
@@ -237,6 +238,7 @@
 <translation id="5805697420284793859">مدير النوافذ</translation>
 <translation id="5820394555380036790">‏نظام التشغيل Chromium</translation>
 <translation id="5832805196449965646">إضافة شخص</translation>
+<translation id="5837036133683224804">إيقاف <ph name="ROUTE_TITLE" /> في <ph name="RECEIVER_NAME" /></translation>
 <translation id="5860033963881614850">إيقاف</translation>
 <translation id="5895138241574237353">إعادة التشغيل</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
@@ -274,6 +276,7 @@
 <translation id="639644700271529076">‏مفتاح CAPS LOCK قيد الإيقاف</translation>
 <translation id="6406704438230478924">altgr</translation>
 <translation id="643147933154517414">ليس لديك أي إشعارات</translation>
+<translation id="6445835306623867477"><ph name="ROUTE_TITLE" /> في <ph name="RECEIVER_NAME" /></translation>
 <translation id="6452181791372256707">رفض</translation>
 <translation id="6453179446719226835">تم تغيير اللغة</translation>
 <translation id="6459472438155181876">تمديد الشاشة إلى <ph name="DISPLAY_NAME" /></translation>
@@ -370,6 +373,7 @@
 <translation id="8351131234907093545">إنشاء ملاحظة</translation>
 <translation id="8392451568018454956">قائمة الخيارات لـ <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="8406981827175133772">مُكبِّر بوضع ملء الشاشة</translation>
+<translation id="8427213022735114808">‏ترسل ميزة "الإملاء" صوتك إلى Google للسماح بالكتابة بالصوت في أي حقل نصي.</translation>
 <translation id="8428213095426709021">الإعدادات</translation>
 <translation id="8431190899827883166">عرض النقرات</translation>
 <translation id="8433186206711564395">إعدادات الشبكة</translation>
@@ -411,6 +415,7 @@
 <translation id="9111102763498581341">فتح القفل</translation>
 <translation id="9151726767154816831">‏إعادة التشغيل وإجراء Powerwash للتحديث</translation>
 <translation id="9179259655489829027">تسمح لك هذه الميزة بالوصول بسرعة إلى أي مستخدم سجّل دخوله بدون طلب كلمة مرور. لا تستخدم هذه الميزة إلا مع الحسابات التي تثق بها.</translation>
+<translation id="9193626018745640770">إرسال إلى مستلم غير معروف</translation>
 <translation id="9194617393863864469">تسجيل دخول مستخدم آخر...</translation>
 <translation id="9201131092683066720">اكتمل شحن <ph name="PERCENTAGE" />% من البطارية.</translation>
 <translation id="9210037371811586452">جارٍ الخروج من وضع سطح المكتب الموحد</translation>
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb
index e64f26b..390bf595 100644
--- a/ash/strings/ash_strings_bn.xtb
+++ b/ash/strings/ash_strings_bn.xtb
@@ -191,6 +191,7 @@
 <translation id="4544944664594876241">স্ক্রিন লক করার শর্টকাটটি পরিবর্তিত হয়েছে। <ph name="OLD_SHORTCUT" /> এর পরিবর্তে দয়া করে <ph name="NEW_SHORTCUT" /> ব্যবহার করুন।</translation>
 <translation id="4564869809620998694">ফন্ট পরিষেবা</translation>
 <translation id="4570957409596482333">বাছুন ও শুনুন বোতাম</translation>
+<translation id="4585337515783392668">অজানা ডিভাইসে কাস্ট করা বন্ধ করুন</translation>
 <translation id="4628757576491864469">ডিভাইস</translation>
 <translation id="4659419629803378708">ChromeVox সক্ষম করা আছে</translation>
 <translation id="4734965478015604180">অনুভূমিক</translation>
@@ -237,6 +238,7 @@
 <translation id="5805697420284793859">উইন্ডো ম্যানেজার</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5832805196449965646">একজন ব্যক্তিকে যোগ করুন</translation>
+<translation id="5837036133683224804"><ph name="RECEIVER_NAME" />-এ <ph name="ROUTE_TITLE" /> বন্ধ করুন</translation>
 <translation id="5860033963881614850">বন্ধ করুন</translation>
 <translation id="5895138241574237353">পুনর্সূচনা</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
@@ -274,6 +276,7 @@
 <translation id="639644700271529076">CAPS LOCK বন্ধ আছে</translation>
 <translation id="6406704438230478924">altgr</translation>
 <translation id="643147933154517414">সব সম্পন্ন!</translation>
+<translation id="6445835306623867477"><ph name="RECEIVER_NAME" />-এ <ph name="ROUTE_TITLE" /></translation>
 <translation id="6452181791372256707">প্রত্যাখ্যান</translation>
 <translation id="6453179446719226835">ভাষা পরিবর্তন করা হয়েছে</translation>
 <translation id="6459472438155181876">স্ক্রিন <ph name="DISPLAY_NAME" /> তে প্রসারিত হচ্ছে</translation>
@@ -370,6 +373,7 @@
 <translation id="8351131234907093545">নোট তৈরি করুন</translation>
 <translation id="8392451568018454956"><ph name="USER_EMAIL_ADDRESS" /> এর জন্য বিকল্পগুলির মেনু</translation>
 <translation id="8406981827175133772">ফুল-স্ক্রিন ম্যাগনিফায়ার</translation>
+<translation id="8427213022735114808">যেকোনও টেক্সট ক্ষেত্রে ভয়েস টাইপিং করার অনুমতি দেওয়ার জন্য ডিকটেশন Google-কে আপনার ভয়েস পাঠায়।</translation>
 <translation id="8428213095426709021">সেটিংস</translation>
 <translation id="8431190899827883166">ট্যাপগুলি দেখুন</translation>
 <translation id="8433186206711564395">নেটওয়ার্ক সেটিংস</translation>
@@ -411,6 +415,7 @@
 <translation id="9111102763498581341">আনলক</translation>
 <translation id="9151726767154816831">আপডেট করার জন্য আবার শুরু করুন এবং পাওয়ারওয়াশ করুন</translation>
 <translation id="9179259655489829027">এই বৈশিষ্ট্যের মাধ্যমে আপনি কোনও পাসওয়ার্ড ছাড়াই সাইন-ইন করা যেকোনও ব্যবহারকারীকে দ্রুত অ্যাক্সেস করতে পারেন। এটি শুধুমাত্র বিশ্বস্ত অ্যাকাউন্টেই ব্যবহার করুন।</translation>
+<translation id="9193626018745640770">অজানা ডিভাইসে কাস্ট করা হচ্ছে</translation>
 <translation id="9194617393863864469">অন্য ব্যবহারকারীকে প্রবেশ করান...</translation>
 <translation id="9201131092683066720">ব্যাটারি <ph name="PERCENTAGE" />% পূর্ণ৷</translation>
 <translation id="9210037371811586452">সমন্বিত ডেস্কটপ মোড থেকে প্রস্থান করছে</translation>
diff --git a/ash/strings/ash_strings_ru.xtb b/ash/strings/ash_strings_ru.xtb
index 932dfbf8c..1e3a8d5 100644
--- a/ash/strings/ash_strings_ru.xtb
+++ b/ash/strings/ash_strings_ru.xtb
@@ -96,7 +96,7 @@
 <translation id="2761704814324807722">Строка состояния, время <ph name="TIME" />, <ph name="BATTERY" /></translation>
 <translation id="277257480934873581">Повторное подключение к сети <ph name="NAME" />…</translation>
 <translation id="2792498699870441125">Alt + Search</translation>
-<translation id="2805756323405976993">Сервисы</translation>
+<translation id="2805756323405976993">Приложения</translation>
 <translation id="2808012452536866044">В режиме Better Together теперь используется другой телефон.</translation>
 <translation id="2819276065543622893">Сеанс завершен.</translation>
 <translation id="2825619548187458965">Полка</translation>
@@ -191,6 +191,7 @@
 <translation id="4544944664594876241">Изменились быстрые клавиши для блокировки экрана. Используйте <ph name="NEW_SHORTCUT" /> вместо <ph name="OLD_SHORTCUT" />.</translation>
 <translation id="4564869809620998694">Сервис шрифтов</translation>
 <translation id="4570957409596482333">Кнопка "Озвучивание при нажатии"</translation>
+<translation id="4585337515783392668">Остановить трансляцию на неизвестное устройство</translation>
 <translation id="4628757576491864469">Устройства</translation>
 <translation id="4659419629803378708">Функция ChromeVox включена</translation>
 <translation id="4734965478015604180">Горизонтальная ориентация</translation>
@@ -237,6 +238,7 @@
 <translation id="5805697420284793859">Менеджер окон</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5832805196449965646">Добавить пользователя</translation>
+<translation id="5837036133683224804">Остановить трансляцию <ph name="ROUTE_TITLE" /> на устройство "<ph name="RECEIVER_NAME" />"</translation>
 <translation id="5860033963881614850">Выкл.</translation>
 <translation id="5895138241574237353">Перезапустить</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
@@ -273,6 +275,7 @@
 <translation id="639644700271529076">CAPS LOCK отключен</translation>
 <translation id="6406704438230478924">altgr</translation>
 <translation id="643147933154517414">Уведомлений больше нет</translation>
+<translation id="6445835306623867477">Трансляция <ph name="ROUTE_TITLE" /> на устройство "<ph name="RECEIVER_NAME" />"</translation>
 <translation id="6452181791372256707">Отклонить</translation>
 <translation id="6453179446719226835">Язык изменен</translation>
 <translation id="6459472438155181876">Расширение экрана на <ph name="DISPLAY_NAME" /></translation>
@@ -369,6 +372,7 @@
 <translation id="8351131234907093545">Создать заметку</translation>
 <translation id="8392451568018454956">Меню параметров пользователя "<ph name="USER_EMAIL_ADDRESS" />"</translation>
 <translation id="8406981827175133772">Полноэкранная лупа</translation>
+<translation id="8427213022735114808">Запись вашего голоса отправляется в Google. Это позволяет использовать голосовой набор для любого текстового поля.</translation>
 <translation id="8428213095426709021">Настройки</translation>
 <translation id="8431190899827883166">Визуальный отклик</translation>
 <translation id="8433186206711564395">Настройки сети</translation>
@@ -410,6 +414,7 @@
 <translation id="9111102763498581341">Разблокировать</translation>
 <translation id="9151726767154816831">Чтобы обновить систему, перезапустите ее и выполните Powerwash</translation>
 <translation id="9179259655489829027">Эта функция позволяет быстро и без пароля получить доступ к любому аккаунту, в который выполнен вход. Используйте ее только для надежных аккаунтов.</translation>
+<translation id="9193626018745640770">Трансляция на неизвестное устройство</translation>
 <translation id="9194617393863864469">Войти в другой аккаунт...</translation>
 <translation id="9201131092683066720">Батарея заряжена на <ph name="PERCENTAGE" />%.</translation>
 <translation id="9210037371811586452">Выход из режима единого рабочего стола…</translation>
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc
index 031ea5c..d8661b6e 100644
--- a/ash/wm/overview/scoped_transform_overview_window.cc
+++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -254,7 +254,7 @@
     // ScopedOverviewAnimationSettings in order to monitor the complete of its
     // exiting animation.
     if (window == GetOverviewWindow() &&
-        selector_item_->ShouldBeObservedWhenExiting()) {
+        selector_item_->should_be_observed_when_exiting()) {
       auto window_animation_observer_weak_ptr =
           selector_item_->window_grid()->window_animation_observer();
       if (window_animation_observer_weak_ptr)
@@ -405,7 +405,7 @@
     // If current |window_| should not animate during exiting process, we defer
     // set transfrom on the window by adding the layer and transform information
     // to the |window_animation_observer|.
-    if (!selector_item_->ShouldAnimateWhenExiting() &&
+    if (!selector_item_->should_animate_when_exiting() &&
         window_animation_observer_weak_ptr) {
       window_animation_observer_weak_ptr->AddLayerTransformPair(window->layer(),
                                                                 new_transform);
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc
index 583e2d8..2381996 100644
--- a/ash/wm/overview/window_grid.cc
+++ b/ash/wm/overview/window_grid.cc
@@ -345,10 +345,13 @@
   prepared_for_overview_ = true;
 }
 
-void WindowGrid::PositionWindows(bool animate,
-                                 WindowSelectorItem* ignored_item) {
+void WindowGrid::PositionWindows(
+    bool animate,
+    WindowSelectorItem* ignored_item,
+    WindowSelector::OverviewTransition transition) {
   if (window_selector_->IsShuttingDown())
     return;
+  DCHECK_NE(transition, WindowSelector::OverviewTransition::kExit);
 
   DCHECK(shield_widget_.get());
   // Keep the background shield widget covering the whole screen. A grid without
@@ -368,15 +371,26 @@
   // position |ignored_item| if it is not nullptr and matches a item in
   // |window_list_|.
   for (size_t i = 0; i < window_list_.size(); ++i) {
-    if (window_list_[i]->animating_to_close() ||
-        (ignored_item != nullptr && window_list_[i].get() == ignored_item)) {
+    WindowSelectorItem* window_item = window_list_[i].get();
+    if (window_item->animating_to_close() ||
+        (ignored_item != nullptr && window_item == ignored_item)) {
       continue;
     }
 
-    const bool should_animate = window_list_[i]->ShouldAnimateWhenEntering();
-    window_list_[i]->SetBounds(
+    // Calculate if each window item needs animation.
+    bool should_animate_item = animate;
+    // If we're in entering overview process, not all window items in the grid
+    // might need animation even if the grid needs animation.
+    if (animate && transition == WindowSelector::OverviewTransition::kEnter)
+      should_animate_item = window_item->should_animate_when_entering();
+    // Do not do the bounds animation for the new selector item. We'll do the
+    // opacity animation by ourselves.
+    if (IsNewSelectorItemWindow(window_item->GetWindow()))
+      should_animate_item = false;
+
+    window_item->SetBounds(
         rects[i],
-        animate && should_animate
+        should_animate_item
             ? OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS
             : OverviewAnimationType::OVERVIEW_ANIMATION_NONE);
   }
@@ -471,13 +485,6 @@
       std::make_unique<WindowSelectorItem>(window, window_selector_, this));
   window_list_.back()->PrepareForOverview();
 
-  if (IsNewSelectorItemWindow(window)) {
-    // If we're adding the new selector item, don't do the layout animation.
-    // We'll do opacity animation by ourselves.
-    window_list_.back()->set_should_animate_when_entering(false);
-    window_list_.back()->set_should_animate_when_exiting(false);
-  }
-
   if (reposition)
     PositionWindows(/*animate=*/true);
 }
@@ -835,11 +842,6 @@
   }
 }
 
-void WindowGrid::ResetWindowListAnimationStates() {
-  for (const auto& selector_item : window_list_)
-    selector_item->ResetAnimationStates();
-}
-
 void WindowGrid::StartNudge(WindowSelectorItem* item) {
   // When there is one window left, there is no need to nudge.
   if (window_list_.size() <= 1) {
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h
index 3e543ae3..bd3bac1 100644
--- a/ash/wm/overview/window_grid.h
+++ b/ash/wm/overview/window_grid.h
@@ -70,8 +70,11 @@
   // fit that height. Optionally animates the windows to their targets when
   // |animate| is true. If |ignored_item| is not null and is an item in
   // |window_list_|, that item is not positioned. This is for split screen.
+  // |transition| specifies the overview state when this function is called.
   void PositionWindows(bool animate,
-                       WindowSelectorItem* ignored_item = nullptr);
+                       WindowSelectorItem* ignored_item = nullptr,
+                       WindowSelector::OverviewTransition transition =
+                           WindowSelector::OverviewTransition::kInOverview);
 
   // Updates |selected_index_| according to the specified |direction| and calls
   // MoveSelectionWidget(). Returns |true| if the new selection index is out of
@@ -206,10 +209,6 @@
   // directly when the animation is completed.
   void SetWindowListNotAnimatedWhenExiting();
 
-  // Reset |selector_item|'s |should_animate_when_entering_|,
-  // |should_animate_when_exiting_| and |should_be_observed_when_exiting_|.
-  void ResetWindowListAnimationStates();
-
   // Starts a nudge, with |item| being the item that may be deleted. This method
   // calculates which items in |window_list_| are to be updated, and their
   // destination bounds and fills |nudge_data_| accordingly.
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index dc10f08..680b5720 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -290,13 +290,11 @@
     // as we don't want to cause any window updates until all windows in
     // overview are observed. See http://crbug.com/384495.
     for (std::unique_ptr<WindowGrid>& window_grid : grid_list_) {
-        window_grid->SetWindowListAnimationStates(/*selected_item=*/nullptr,
-                                                  OverviewTransition::kEnter);
+      window_grid->SetWindowListAnimationStates(/*selected_item=*/nullptr,
+                                                OverviewTransition::kEnter);
       window_grid->PrepareForOverview();
-      window_grid->PositionWindows(/*animate=*/true);
-      // Reset |should_animate_when_entering_| in order to animate during
-      // overview mode, such as dragging animations.
-      window_grid->ResetWindowListAnimationStates();
+      window_grid->PositionWindows(/*animate=*/true, /*ignore_item=*/nullptr,
+                                   OverviewTransition::kEnter);
     }
 
     // Image used for text filter textfield.
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h
index 15a676c8..fc84beb 100644
--- a/ash/wm/overview/window_selector.h
+++ b/ash/wm/overview/window_selector.h
@@ -57,8 +57,9 @@
   enum Direction { LEFT, UP, RIGHT, DOWN };
 
   enum class OverviewTransition {
-    kEnter,  // In the entering process of overview.
-    kExit    // In the exiting process of overview.
+    kEnter,       // In the entering process of overview.
+    kInOverview,  // Already in overview.
+    kExit         // In the exiting process of overview.
   };
 
   using WindowList = std::vector<aura::Window*>;
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
index 6679ec377..3650e478e 100644
--- a/ash/wm/overview/window_selector_item.cc
+++ b/ash/wm/overview/window_selector_item.cc
@@ -1139,32 +1139,14 @@
   return item_widget_->GetNativeWindow()->layer()->opacity();
 }
 
-bool WindowSelectorItem::ShouldAnimateWhenEntering() const {
-  return should_animate_when_entering_;
-}
-
-bool WindowSelectorItem::ShouldAnimateWhenExiting() const {
-  return should_animate_when_exiting_;
-}
-
-bool WindowSelectorItem::ShouldBeObservedWhenExiting() const {
-  return should_be_observed_when_exiting_;
-}
-
-void WindowSelectorItem::ResetAnimationStates() {
-  should_animate_when_entering_ = true;
-  should_animate_when_exiting_ = true;
-  should_be_observed_when_exiting_ = false;
-}
-
 OverviewAnimationType WindowSelectorItem::GetExitOverviewAnimationType() {
-  return ShouldAnimateWhenExiting()
+  return should_animate_when_exiting_
              ? OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS
              : OverviewAnimationType::OVERVIEW_ANIMATION_NONE;
 }
 
 OverviewAnimationType WindowSelectorItem::GetExitTransformAnimationType() {
-  return ShouldAnimateWhenExiting()
+  return should_animate_when_exiting_
              ? OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW
              : OverviewAnimationType::OVERVIEW_ANIMATION_NONE;
 }
diff --git a/ash/wm/overview/window_selector_item.h b/ash/wm/overview/window_selector_item.h
index d7ccc6d..60933ff30 100644
--- a/ash/wm/overview/window_selector_item.h
+++ b/ash/wm/overview/window_selector_item.h
@@ -223,19 +223,23 @@
   void set_should_animate_when_entering(bool should_animate) {
     should_animate_when_entering_ = should_animate;
   }
-  bool ShouldAnimateWhenEntering() const;
+  bool should_animate_when_entering() const {
+    return should_animate_when_entering_;
+  }
 
   void set_should_animate_when_exiting(bool should_animate) {
     should_animate_when_exiting_ = should_animate;
   }
-  bool ShouldAnimateWhenExiting() const;
+  bool should_animate_when_exiting() const {
+    return should_animate_when_exiting_;
+  }
 
   void set_should_be_observed_when_exiting(bool should_be_observed) {
     should_be_observed_when_exiting_ = should_be_observed;
   }
-  bool ShouldBeObservedWhenExiting() const;
-
-  void ResetAnimationStates();
+  bool should_be_observed_when_exiting() const {
+    return should_be_observed_when_exiting_;
+  }
 
   OverviewAnimationType GetExitOverviewAnimationType();
   OverviewAnimationType GetExitTransformAnimationType();
diff --git a/base/BUILD.gn b/base/BUILD.gn
index a9cb716..94e90b1 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -319,6 +319,8 @@
     "debug/dump_without_crashing.h",
     "debug/gdi_debug_util_win.cc",
     "debug/gdi_debug_util_win.h",
+    "debug/invalid_access_win.cc",
+    "debug/invalid_access_win.h",
     "debug/leak_annotations.h",
     "debug/leak_tracker.h",
     "debug/proc_maps_linux.cc",
diff --git a/base/debug/invalid_access_win.cc b/base/debug/invalid_access_win.cc
new file mode 100644
index 0000000..d6a96de
--- /dev/null
+++ b/base/debug/invalid_access_win.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/invalid_access_win.h"
+
+#include <stdlib.h>
+#include <windows.h>
+
+#include "base/logging.h"
+#include "base/win/windows_version.h"
+
+namespace base {
+namespace debug {
+namespace win {
+
+namespace {
+
+void CreateSyntheticHeapCorruption() {
+  EXCEPTION_RECORD record = {};
+  record.ExceptionCode = STATUS_HEAP_CORRUPTION;
+  RaiseFailFastException(&record, nullptr,
+                         FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
+}
+
+}  // namespace
+
+void TerminateWithHeapCorruption() {
+  __try {
+    // Pre-Windows 10, it's hard to trigger a heap corruption fast fail, so
+    // artificially create one instead.
+    if (base::win::GetVersion() < base::win::VERSION_WIN10)
+      CreateSyntheticHeapCorruption();
+    HANDLE heap = ::HeapCreate(0, 0, 0);
+    CHECK(heap);
+    CHECK(HeapSetInformation(heap, HeapEnableTerminationOnCorruption, nullptr,
+                             0));
+    void* addr = ::HeapAlloc(heap, 0, 0x1000);
+    CHECK(addr);
+    // Corrupt heap header.
+    char* addr_mutable = reinterpret_cast<char*>(addr);
+    memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
+
+    HeapFree(heap, 0, addr);
+    HeapDestroy(heap);
+  } __except (EXCEPTION_EXECUTE_HANDLER) {
+    // Heap corruption exception should never be caught.
+    CHECK(false);
+  }
+  // Should never reach here.
+  abort();
+}
+
+}  // namespace win
+}  // namespace debug
+}  // namespace base
diff --git a/base/debug/invalid_access_win.h b/base/debug/invalid_access_win.h
new file mode 100644
index 0000000..37d8eb39
--- /dev/null
+++ b/base/debug/invalid_access_win.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_DEBUG_INVALID_ACCESS_WIN_H_
+#define BASE_DEBUG_INVALID_ACCESS_WIN_H_
+
+#include "base/base_export.h"
+
+namespace base {
+namespace debug {
+namespace win {
+
+// Creates a synthetic heap corruption that causes the current process to
+// terminate immediately with a fast fail exception.
+[[noreturn]] BASE_EXPORT void TerminateWithHeapCorruption();
+
+}  // namespace win
+}  // namespace debug
+}  // namespace base
+
+#endif  // BASE_DEBUG_INVALID_ACCESS_WIN_H_
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index ff37880..b0e7a1d 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -13,6 +13,7 @@
 #include "base/debug/activity_tracker.h"
 #include "base/logging.h"
 #include "base/metrics/field_trial_param_associator.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/process/memory.h"
 #include "base/process/process_handle.h"
 #include "base/process/process_info.h"
@@ -833,6 +834,8 @@
     std::string switch_value =
         cmd_line.GetSwitchValueASCII(field_trial_handle_switch);
     bool result = CreateTrialsFromSwitchValue(switch_value);
+    UMA_HISTOGRAM_BOOLEAN("ChildProcess.FieldTrials.CreateFromShmemSuccess",
+                          result);
     DCHECK(result);
   }
 #elif defined(OS_POSIX) && !defined(OS_NACL)
@@ -843,6 +846,8 @@
     std::string switch_value =
         cmd_line.GetSwitchValueASCII(field_trial_handle_switch);
     bool result = CreateTrialsFromDescriptor(fd_key, switch_value);
+    UMA_HISTOGRAM_BOOLEAN("ChildProcess.FieldTrials.CreateFromShmemSuccess",
+                          result);
     DCHECK(result);
   }
 #endif
@@ -851,6 +856,8 @@
     bool result = FieldTrialList::CreateTrialsFromString(
         cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials),
         std::set<std::string>());
+    UMA_HISTOGRAM_BOOLEAN("ChildProcess.FieldTrials.CreateFromSwitchSuccess",
+                          result);
     DCHECK(result);
   }
 }
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
index 82af410..1129092a 100644
--- a/base/process/process_unittest.cc
+++ b/base/process/process_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/at_exit.h"
+#include "base/debug/invalid_access_win.h"
 #include "base/process/kill.h"
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_timeouts.h"
@@ -299,6 +300,13 @@
 }
 #endif
 
+#if defined(OS_WIN)
+TEST_F(ProcessTest, HeapCorruption) {
+  EXPECT_EXIT(base::debug::win::TerminateWithHeapCorruption(),
+              ::testing::ExitedWithCode(STATUS_HEAP_CORRUPTION), "");
+}
+#endif
+
 TEST_F(ProcessTest, ChildProcessIsRunning) {
   Process process(SpawnChild("SleepyChildProcess"));
   EXPECT_FALSE(process.WaitForExitWithTimeout(
diff --git a/base/third_party/libevent/README.chromium b/base/third_party/libevent/README.chromium
index 1462e88..85132a48 100644
--- a/base/third_party/libevent/README.chromium
+++ b/base/third_party/libevent/README.chromium
@@ -37,3 +37,4 @@
    by sandbox in nacl_helper_nonsfi.
 8) Remove an unnecessary workaround for OS X 10.4 from kqueue.c. It was causing
    problems on macOS Sierra.
+9) Change buffer.c to not redefine _GNU_SOURCE.
diff --git a/base/third_party/libevent/buffer.c b/base/third_party/libevent/buffer.c
index ebf35c9..3cbbaba 100644
--- a/base/third_party/libevent/buffer.c
+++ b/base/third_party/libevent/buffer.c
@@ -34,7 +34,7 @@
 #include <windows.h>
 #endif
 
-#ifdef HAVE_VASPRINTF
+#if defined(HAVE_VASPRINTF) && !defined(_GNU_SOURCE)
 /* If we have vasprintf, we need to define this before we include stdio.h. */
 #define _GNU_SOURCE
 #endif
diff --git a/build/chromeos/PRESUBMIT.py b/build/chromeos/PRESUBMIT.py
new file mode 100644
index 0000000..5700f54
--- /dev/null
+++ b/build/chromeos/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for build/chromeos/.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into depot_tools.
+"""
+
+
+def CommonChecks(input_api, output_api):
+  return input_api.canned_checks.RunPylint(
+      input_api,
+      output_api,
+      pylintrc='pylintrc')
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return CommonChecks(input_api, output_api)
diff --git a/build/chromeos/create_vm_test_script.py b/build/chromeos/create_vm_test_script.py
index f14b8181..67e2ec3 100755
--- a/build/chromeos/create_vm_test_script.py
+++ b/build/chromeos/create_vm_test_script.py
@@ -10,7 +10,6 @@
 
 import argparse
 import os
-import re
 import sys
 
 
diff --git a/build/chromeos/pylintrc b/build/chromeos/pylintrc
new file mode 100644
index 0000000..2a721bf2
--- /dev/null
+++ b/build/chromeos/pylintrc
@@ -0,0 +1,15 @@
+[FORMAT]
+
+max-line-length=80
+
+[MESSAGES CONTROL]
+
+disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,wrong-import-position
+
+[REPORTS]
+
+reports=no
+
+[VARIABLES]
+
+dummy-variables-rgx=^_.*$|dummy
diff --git a/build/chromeos/run_vm_test.py b/build/chromeos/run_vm_test.py
index bbc2089c..4cedbd2 100755
--- a/build/chromeos/run_vm_test.py
+++ b/build/chromeos/run_vm_test.py
@@ -5,16 +5,14 @@
 # found in the LICENSE file.
 
 import argparse
-import contextlib
 import json
 import logging
 import os
 import re
 import signal
-import stat
 import sys
 
-import psutil
+import psutil  # pylint: disable=import-error
 
 CHROMIUM_SRC_PATH = os.path.abspath(os.path.join(
     os.path.dirname(__file__), '..', '..'))
@@ -22,13 +20,13 @@
 # Use the android test-runner's gtest results support library for generating
 # output json ourselves.
 sys.path.insert(0, os.path.join(CHROMIUM_SRC_PATH, 'build', 'android'))
-from pylib.base import base_test_result
-from pylib.results import json_results
+from pylib.base import base_test_result  # pylint: disable=import-error
+from pylib.results import json_results  # pylint: disable=import-error
 
 # Use luci-py's subprocess42.py
 sys.path.insert(
     0, os.path.join(CHROMIUM_SRC_PATH, 'tools', 'swarming_client', 'utils'))
-import subprocess42
+import subprocess42  # pylint: disable=import-error
 
 CHROMITE_PATH = os.path.abspath(os.path.join(
     CHROMIUM_SRC_PATH, 'third_party', 'chromite'))
@@ -36,30 +34,275 @@
     CHROMITE_PATH, 'bin', 'cros_run_vm_test'))
 
 
-_FILE_BLACKLIST = [
-  re.compile(r'.*build/chromeos.*'),
-  re.compile(r'.*build/cros_cache.*'),
-  re.compile(r'.*third_party/chromite.*'),
-]
+class TestFormatError(Exception):
+  pass
 
 
-def read_runtime_files(runtime_deps_path, outdir):
-  if not runtime_deps_path:
-    return []
+class RemoteTest(object):
 
-  abs_runtime_deps_path = os.path.abspath(
-      os.path.join(outdir, runtime_deps_path))
-  with open(abs_runtime_deps_path) as runtime_deps_file:
-    files = [l.strip() for l in runtime_deps_file if l]
-  rel_file_paths = []
-  for f in files:
-    rel_file_path = os.path.relpath(
-        os.path.abspath(os.path.join(outdir, f)),
-        os.getcwd())
-    if not any(regex.match(rel_file_path) for regex in _FILE_BLACKLIST):
-      rel_file_paths.append(rel_file_path)
+  def __init__(self, args, unknown_args):
+    self._additional_args = unknown_args
+    self._path_to_outdir = args.path_to_outdir
+    self._test_exe = args.test_exe
+    self._test_launcher_summary_output = args.test_launcher_summary_output
+    self._vm_logs_dir = args.vm_logs_dir
 
-  return rel_file_paths
+    self._test_env = os.environ.copy()
+    self._retries = 0
+    self._timeout = None
+
+    self._vm_test_cmd = [
+        CROS_RUN_VM_TEST_PATH,
+        '--start',
+        '--board', args.board,
+        '--cache-dir', args.cros_cache,
+    ]
+    if args.vm_logs_dir:
+      self._vm_test_cmd += [
+          '--results-src', '/var/log/',
+          '--results-dest-dir', args.vm_logs_dir,
+      ]
+
+  @property
+  def vm_test_cmd(self):
+    return self._vm_test_cmd
+
+  def run_test(self):
+    # Traps SIGTERM and kills all child processes of cros_run_vm_test when it's
+    # caught. This will allow us to capture logs from the VM if a test hangs
+    # and gets timeout-killed by swarming. See also:
+    # https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance
+    test_proc = None
+    def _kill_child_procs(trapped_signal, _):
+      logging.warning(
+          'Received signal %d. Killing child processes of test.',
+          trapped_signal)
+      if not test_proc or not test_proc.pid:
+        # This shouldn't happen?
+        logging.error('Test process not running.')
+        return
+      for child in psutil.Process(test_proc.pid).children():
+        logging.warning('Killing process %s', child)
+        child.kill()
+
+    signal.signal(signal.SIGTERM, _kill_child_procs)
+
+    for i in xrange(self._retries+1):
+      logging.info('########################################')
+      logging.info('Test attempt #%d', i)
+      logging.info('########################################')
+      test_proc = subprocess42.Popen(
+          self._vm_test_cmd, stdout=sys.stdout, stderr=sys.stderr,
+          env=self._test_env)
+      try:
+        test_proc.wait(timeout=self._timeout)
+      except subprocess42.TimeoutExpired:
+        logging.error('Test timed out. Sending SIGTERM.')
+        # SIGTERM the proc and wait 10s for it to close.
+        test_proc.terminate()
+        try:
+          test_proc.wait(timeout=10)
+        except subprocess42.TimeoutExpired:
+          # If it hasn't closed in 10s, SIGKILL it.
+          logging.error('Test did not exit in time. Sending SIGKILL.')
+          test_proc.kill()
+          test_proc.wait()
+      logging.info('Test exitted with %d.', test_proc.returncode)
+      if test_proc.returncode == 0:
+        break
+
+    self.handle_results(test_proc.returncode)
+    return test_proc.returncode
+
+  def handle_results(self, return_code):
+    pass
+
+
+class GTestTest(RemoteTest):
+
+  _FILE_BLACKLIST = [
+      re.compile(r'.*build/chromeos.*'),
+      re.compile(r'.*build/cros_cache.*'),
+      re.compile(r'.*third_party/chromite.*'),
+  ]
+
+  def __init__(self, args, unknown_args):
+    super(GTestTest, self).__init__(args, unknown_args)
+
+    self._runtime_deps_path = args.runtime_deps_path
+    self._vpython_dir = args.vpython_dir
+
+    self._test_launcher_shard_index = args.test_launcher_shard_index
+    self._test_launcher_total_shards = args.test_launcher_total_shards
+
+  def build_test_command(self):
+    # To keep things easy for us, ensure both types of output locations are
+    # the same.
+    if self._test_launcher_summary_output and self._vm_logs_dir:
+      json_out_dir = os.path.dirname(self._test_launcher_summary_output) or '.'
+      if os.path.abspath(json_out_dir) != os.path.abspath(self._vm_logs_dir):
+        raise TestFormatError(
+            '--test-launcher-summary-output and --vm-logs-dir must point to '
+            'the same directory.')
+
+    runtime_files = self._read_runtime_files()
+    if self._vpython_dir:
+      # --vpython-dir is relative to the out dir, but --files expects paths
+      # relative to src dir, so fix the path up a bit.
+      runtime_files.append(
+          os.path.relpath(
+              os.path.abspath(os.path.join(self._path_to_outdir,
+                                           self._vpython_dir)),
+              CHROMIUM_SRC_PATH))
+      # TODO(bpastene): Add the vpython spec to the test's runtime deps instead
+      # of handling it here.
+      runtime_files.append('.vpython')
+
+    # If we're pushing files, we need to set the cwd.
+    if runtime_files:
+        self._vm_test_cmd.extend(
+            ['--cwd', os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH)])
+    for f in runtime_files:
+      self._vm_test_cmd.extend(['--files', f])
+
+    if self._test_launcher_summary_output:
+      result_dir, result_file = os.path.split(
+          self._test_launcher_summary_output)
+      # If args.test_launcher_summary_output is a file in cwd, result_dir will
+      # be an empty string, so replace it with '.' when this is the case so
+      # cros_run_vm_test can correctly handle it.
+      if not result_dir:
+        result_dir = '.'
+      vm_result_file = '/tmp/%s' % result_file
+      self._vm_test_cmd += [
+          '--results-src', vm_result_file,
+          '--results-dest-dir', result_dir,
+      ]
+
+    pre_test_cmds = [
+        # /home is mounted with "noexec" in the VM, but some of our tools
+        # and tests use the home dir as a workspace (eg: vpython downloads
+        # python binaries to ~/.vpython-root). /tmp doesn't have this
+        # restriction, so change the location of the home dir for the
+        # duration of the test.
+        'export HOME=/tmp', '\\;',
+    ]
+    if self._vpython_dir:
+      vpython_spec_path = os.path.relpath(
+          os.path.join(CHROMIUM_SRC_PATH, '.vpython'),
+          self._path_to_outdir)
+      pre_test_cmds += [
+          # Backslash is needed to prevent $PATH from getting prematurely
+          # executed on the host.
+          'export PATH=\\$PATH:\\$PWD/%s' % self._vpython_dir, '\\;',
+          # Initialize the vpython cache. This can take 10-20s, and some tests
+          # can't afford to wait that long on the first invocation.
+          'vpython', '-vpython-spec', vpython_spec_path, '-vpython-tool',
+          'install', '\\;',
+      ]
+
+    self._vm_test_cmd += [
+        # Some tests fail as root, so run as the less privileged user 'chronos'.
+        '--as-chronos',
+        '--cmd',
+        '--',
+        # Wrap the cmd to run in the VM around quotes (") so that the
+        # interpreter on the host doesn't stop at any ";" or "&&" tokens in the
+        # cmd.
+        '"',
+    ] + pre_test_cmds + [
+        './' + self._test_exe,
+        '--test-launcher-shard-index=%d' % self._test_launcher_shard_index,
+        '--test-launcher-total-shards=%d' % self._test_launcher_total_shards,
+    ] + self._additional_args + [
+        '"',
+    ]
+
+    if self._test_launcher_summary_output:
+      self._vm_test_cmd += [
+        '--test-launcher-summary-output=%s' % vm_result_file,
+      ]
+
+  def _read_runtime_files(self):
+    if not self._runtime_deps_path:
+      return []
+
+    abs_runtime_deps_path = os.path.abspath(
+        os.path.join(self._path_to_outdir, self._runtime_deps_path))
+    with open(abs_runtime_deps_path) as runtime_deps_file:
+      files = [l.strip() for l in runtime_deps_file if l]
+    rel_file_paths = []
+    for f in files:
+      rel_file_path = os.path.relpath(
+          os.path.abspath(os.path.join(self._path_to_outdir, f)),
+          os.getcwd())
+      if not any(regex.match(rel_file_path) for regex in self._FILE_BLACKLIST):
+        rel_file_paths.append(rel_file_path)
+
+    return rel_file_paths
+
+
+class BrowserSanityTest(RemoteTest):
+
+  def __init__(self, args, unknown_args):
+    super(BrowserSanityTest, self).__init__(args, unknown_args)
+
+    # 5 min should be enough time for the sanity test to pass.
+    self._retries = 2
+    self._timeout = 300
+
+  def build_test_command(self):
+    if self._additional_args:
+      raise TestFormatError('Sanity test should not have additional args.')
+
+    # run_cros_vm_test's default behavior when no cmd is specified is the sanity
+    # test that's baked into the VM image. This test smoke-checks the system
+    # browser, so deploy our locally-built chrome to the VM before testing.
+    self._vm_test_cmd += [
+        '--deploy',
+        '--build-dir', os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH),
+    ]
+
+    # deploy_chrome needs a set of GN args used to build chrome to determine if
+    # certain libraries need to be pushed to the VM. It looks for the args via
+    # an env var. To trigger the default deploying behavior, give it a dummy set
+    # of args.
+    # TODO(crbug.com/823996): Make the GN-dependent deps controllable via cmd
+    # line args.
+    if not self._test_env.get('GN_ARGS'):
+      self._test_env['GN_ARGS'] = 'is_chromeos = true'
+    self._test_env['PATH'] = (
+        self._test_env['PATH'] + ':' + os.path.join(CHROMITE_PATH, 'bin'))
+
+  def handle_results(self, return_code):
+    # Create a simple json results file for the sanity test if needed. The
+    # results will contain only one test ('cros_vm_sanity_test'), and will
+    # either be a PASS or FAIL depending on the return code of cros_run_vm_test.
+    if self._test_launcher_summary_output:
+      result = (base_test_result.ResultType.FAIL if return_code else
+                    base_test_result.ResultType.PASS)
+      sanity_test_result = base_test_result.BaseTestResult(
+          'cros_vm_sanity_test', result)
+      run_results = base_test_result.TestRunResults()
+      run_results.AddResult(sanity_test_result)
+      with open(self._test_launcher_summary_output, 'w') as f:
+        json.dump(json_results.GenerateResultsDict([run_results]), f)
+
+
+def vm_test(args, unknown_args):
+  # pylint: disable=redefined-variable-type
+  # TODO: Remove the above when depot_tool's pylint is updated to include the
+  # fix to https://github.com/PyCQA/pylint/issues/710.
+  if args.test_exe == 'cros_vm_sanity_test':
+    test = BrowserSanityTest(args, unknown_args)
+  else:
+    test = GTestTest(args, unknown_args)
+
+  test.build_test_command()
+  logging.info('Running the following command:')
+  logging.info(' '.join(test.vm_test_cmd))
+
+  return test.run_test()
 
 
 def host_cmd(args, unknown_args):
@@ -93,199 +336,6 @@
       cros_run_vm_test_cmd, stdout=sys.stdout, stderr=sys.stderr)
 
 
-def vm_test(args, unknown_args):
-  is_sanity_test = args.test_exe == 'cros_vm_sanity_test'
-
-  # To keep things easy for us, ensure both types of output locations are
-  # the same.
-  if args.test_launcher_summary_output and args.vm_logs_dir:
-    json_output_dir = os.path.dirname(args.test_launcher_summary_output) or '.'
-    if os.path.abspath(json_output_dir) != os.path.abspath(args.vm_logs_dir):
-      logging.error(
-          '--test-launcher-summary-output and --vm-logs-dir must point to '
-          'the same directory.')
-      return 1
-
-  cros_run_vm_test_cmd = [
-      CROS_RUN_VM_TEST_PATH,
-      '--start',
-      '--board', args.board,
-      '--cache-dir', args.cros_cache,
-  ]
-
-  # cros_run_vm_test has trouble with relative paths that go up directories, so
-  # cd to src/, which should be the root of all data deps.
-  os.chdir(CHROMIUM_SRC_PATH)
-
-  runtime_files = read_runtime_files(
-      args.runtime_deps_path, args.path_to_outdir)
-  if args.vpython_dir:
-    # --vpython-dir is relative to the out dir, but --files expects paths
-    # relative to src dir, so fix the path up a bit.
-    runtime_files.append(
-        os.path.relpath(
-            os.path.abspath(os.path.join(args.path_to_outdir,
-                                         args.vpython_dir)),
-            CHROMIUM_SRC_PATH))
-    runtime_files.append('.vpython')
-
-  # If we're pushing files, we need to set the cwd.
-  if runtime_files:
-      cros_run_vm_test_cmd.extend(
-          ['--cwd', os.path.relpath(args.path_to_outdir, CHROMIUM_SRC_PATH)])
-  for f in runtime_files:
-    cros_run_vm_test_cmd.extend(['--files', f])
-
-  if args.vm_logs_dir:
-    cros_run_vm_test_cmd += [
-        '--results-src', '/var/log/',
-        '--results-dest-dir', args.vm_logs_dir,
-    ]
-
-  if args.test_launcher_summary_output and not is_sanity_test:
-    result_dir, result_file = os.path.split(args.test_launcher_summary_output)
-    # If args.test_launcher_summary_output is a file in cwd, result_dir will be
-    # an empty string, so replace it with '.' when this is the case so
-    # cros_run_vm_test can correctly handle it.
-    if not result_dir:
-      result_dir = '.'
-    vm_result_file = '/tmp/%s' % result_file
-    cros_run_vm_test_cmd += [
-      '--results-src', vm_result_file,
-      '--results-dest-dir', result_dir,
-    ]
-
-  if is_sanity_test:
-    # run_cros_vm_test's default behavior when no cmd is specified is the sanity
-    # test that's baked into the VM image. This test smoke-checks the system
-    # browser, so deploy our locally-built chrome to the VM before testing.
-    cros_run_vm_test_cmd += [
-        '--deploy',
-        '--build-dir', os.path.relpath(args.path_to_outdir, CHROMIUM_SRC_PATH),
-    ]
-  else:
-    pre_test_cmds = [
-        # /home is mounted with "noexec" in the VM, but some of our tools
-        # and tests use the home dir as a workspace (eg: vpython downloads
-        # python binaries to ~/.vpython-root). /tmp doesn't have this
-        # restriction, so change the location of the home dir for the
-        # duration of the test.
-        'export HOME=/tmp', '\;',
-    ]
-    if args.vpython_dir:
-      vpython_spec_path = os.path.relpath(
-          os.path.join(CHROMIUM_SRC_PATH, '.vpython'),
-          args.path_to_outdir)
-      pre_test_cmds += [
-          # Backslash is needed to prevent $PATH from getting prematurely
-          # executed on the host.
-          'export PATH=\$PATH:\$PWD/%s' % args.vpython_dir, '\;',
-          # Initialize the vpython cache. This can take 10-20s, and some tests
-          # can't afford to wait that long on the first invocation.
-          'vpython', '-vpython-spec', vpython_spec_path, '-vpython-tool',
-          'install', '\;',
-      ]
-    cros_run_vm_test_cmd += [
-        # Some tests fail as root, so run as the less privileged user 'chronos'.
-        '--as-chronos',
-        '--cmd',
-        '--',
-        # Wrap the cmd to run in the VM around quotes (") so that the
-        # interpreter on the host doesn't stop at any ";" or "&&" tokens in the
-        # cmd.
-        '"',
-    ] + pre_test_cmds + [
-        './' + args.test_exe,
-        '--test-launcher-shard-index=%d' % args.test_launcher_shard_index,
-        '--test-launcher-total-shards=%d' % args.test_launcher_total_shards,
-    ] + unknown_args + [
-        '"',
-    ]
-
-  if args.test_launcher_summary_output and not is_sanity_test:
-    cros_run_vm_test_cmd += [
-      '--test-launcher-summary-output=%s' % vm_result_file,
-    ]
-
-  logging.info('Running the following command:')
-  logging.info(' '.join(cros_run_vm_test_cmd))
-
-  # deploy_chrome needs a set of GN args used to build chrome to determine if
-  # certain libraries need to be pushed to the VM. It looks for the args via an
-  # env var. To trigger the default deploying behavior, give it a dummy set of
-  # args.
-  # TODO(crbug.com/823996): Make the GN-dependent deps controllable via cmd-line
-  # args.
-  env_copy = os.environ.copy()
-  if not env_copy.get('GN_ARGS'):
-    env_copy['GN_ARGS'] = 'is_chromeos = true'
-  env_copy['PATH'] = env_copy['PATH'] + ':' + os.path.join(CHROMITE_PATH, 'bin')
-
-  # Traps SIGTERM and kills all child processes of cros_run_vm_test when it's
-  # caught. This will allow us to capture logs from the VM if a test hangs
-  # and gets timeout-killed by swarming. See also:
-  # https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance
-  test_proc = None
-  def _kill_child_procs(trapped_signal, _):
-    logging.warning(
-        'Received signal %d. Killing child processes of test.', trapped_signal)
-    if not test_proc or not test_proc.pid:
-      # This shouldn't happen?
-      logging.error('Test process not running.')
-      return
-    for child in psutil.Process(test_proc.pid).children():
-      logging.warning('Killing process %s', child)
-      child.kill()
-
-  # Standard GTests should handle retries and timeouts themselves.
-  retries, timeout = 0, None
-  if is_sanity_test:
-    # 5 min should be enough time for the sanity test to pass.
-    retries, timeout = 2, 300
-  signal.signal(signal.SIGTERM, _kill_child_procs)
-
-  for i in xrange(retries+1):
-    logging.info('########################################')
-    logging.info('Test attempt #%d', i)
-    logging.info('########################################')
-    test_proc = subprocess42.Popen(
-        cros_run_vm_test_cmd, stdout=sys.stdout, stderr=sys.stderr,
-        env=env_copy)
-    try:
-      test_proc.wait(timeout=timeout)
-    except subprocess42.TimeoutExpired:
-      logging.error('Test timed out. Sending SIGTERM.')
-      # SIGTERM the proc and wait 10s for it to close.
-      test_proc.terminate()
-      try:
-        test_proc.wait(timeout=10)
-      except subprocess42.TimeoutExpired:
-        # If it hasn't closed in 10s, SIGKILL it.
-        logging.error('Test did not exit in time. Sending SIGKILL.')
-        test_proc.kill()
-        test_proc.wait()
-    logging.info('Test exitted with %d.', test_proc.returncode)
-    if test_proc.returncode == 0:
-      break
-
-  rc = test_proc.returncode
-
-  # Create a simple json results file for the sanity test if needed. The results
-  # will contain only one test ('cros_vm_sanity_test'), and will either be a
-  # PASS or FAIL depending on the return code of cros_run_vm_test above.
-  if args.test_launcher_summary_output and is_sanity_test:
-    result = (base_test_result.ResultType.FAIL if rc else
-                  base_test_result.ResultType.PASS)
-    sanity_test_result = base_test_result.BaseTestResult(
-        'cros_vm_sanity_test', result)
-    run_results = base_test_result.TestRunResults()
-    run_results.AddResult(sanity_test_result)
-    with open(args.test_launcher_summary_output, 'w') as f:
-      json.dump(json_results.GenerateResultsDict([run_results]), f)
-
-  return rc
-
-
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--verbose', '-v', action='store_true')
@@ -365,6 +415,10 @@
         '/dev/kvm is not writable as current user. Perhaps you should be root?')
     return 1
 
+  # cros_run_vm_test has trouble with relative paths that go up directories, so
+  # cd to src/, which should be the root of all data deps.
+  os.chdir(CHROMIUM_SRC_PATH)
+
   args.cros_cache = os.path.abspath(args.cros_cache)
   return args.func(args, unknown_args)
 
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index fcc00ee0..0c1b861f 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -522,7 +522,6 @@
   "//build/config/compiler:afdo",
   "//build/config/compiler:afdo_optimize_size",
   "//build/config/compiler:compiler",
-  "//build/config/compiler:clang_stackrealign",
   "//build/config/compiler:compiler_arm_fpu",
   "//build/config/compiler:compiler_arm_thumb",
   "//build/config/compiler:chromium_code",
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index a703551..71f8f18 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1079,20 +1079,6 @@
   asmflags = cflags
 }
 
-# This is separate from :compiler_codegen (and not even a sub-config there)
-# so that some targets can remove it from the list with:
-#   configs -= [ "//build/config/compiler:clang_stackrealign" ]
-# See https://crbug.com/556393 for details of where it must be avoided.
-config("clang_stackrealign") {
-  if (is_clang && current_cpu == "x86" && is_linux) {
-    cflags = [
-      # Align the stack on 16-byte boundaries, http://crbug.com/418554.
-      "-mstack-alignment=16",
-      "-mstackrealign",
-    ]
-  }
-}
-
 config("clang_revision") {
   if (is_clang && clang_base_path == default_clang_base_path) {
     update_args = [
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 56bca37..ec9a79d 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -677,7 +677,8 @@
   gfx::Rect viewport_rect_for_tile_priority =
       layer_tree_impl()->ViewportRectForTilePriority();
   if (visible_rect_in_content_space.IsEmpty() ||
-      layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority) {
+      layer_tree_impl()->GetDeviceViewport() !=
+          viewport_rect_for_tile_priority) {
     gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
     if (ScreenSpaceTransform().GetInverse(&view_to_layer)) {
       // Transform from view space to content space.
@@ -1318,7 +1319,7 @@
       int64_t maximum_area =
           static_cast<int64_t>(bounds_at_maximum_scale.width()) *
           static_cast<int64_t>(bounds_at_maximum_scale.height());
-      gfx::Size viewport = layer_tree_impl()->device_viewport_size();
+      gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
 
       // Use the square of the maximum viewport dimension direction, to
       // compensate for viewports with different aspect ratios.
@@ -1337,7 +1338,7 @@
       int64_t start_area =
           static_cast<int64_t>(bounds_at_starting_scale.width()) *
           static_cast<int64_t>(bounds_at_starting_scale.height());
-      gfx::Size viewport = layer_tree_impl()->device_viewport_size();
+      gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
       int64_t viewport_area = static_cast<int64_t>(viewport.width()) *
                               static_cast<int64_t>(viewport.height());
       if (start_area <= viewport_area)
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index fa1a8571..36425eb 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -77,7 +77,7 @@
   void RunRasterQueueConstructAndIterateTest(const std::string& test_name,
                                              int num_tiles,
                                              const gfx::Size& viewport_size) {
-    host_impl_.SetViewportSize(viewport_size);
+    host_impl_.active_tree()->SetDeviceViewportSize(viewport_size);
     host_impl_.pending_tree()->UpdateDrawProperties();
 
     timer_.Reset();
@@ -100,7 +100,7 @@
 
   void RunRasterQueueConstructTest(const std::string& test_name,
                                    const gfx::Rect& viewport) {
-    host_impl_.SetViewportSize(viewport.size());
+    host_impl_.active_tree()->SetDeviceViewportSize(viewport.size());
     host_impl_.pending_tree()
         ->property_trees()
         ->scroll_tree.UpdateScrollOffsetBaseForTesting(
@@ -124,7 +124,7 @@
       const std::string& test_name,
       int num_tiles,
       const gfx::Size& viewport_size) {
-    host_impl_.SetViewportSize(viewport_size);
+    host_impl_.active_tree()->SetDeviceViewportSize(viewport_size);
     host_impl_.pending_tree()->UpdateDrawProperties();
 
     timer_.Reset();
@@ -148,7 +148,7 @@
 
   void RunEvictionQueueConstructTest(const std::string& test_name,
                                      const gfx::Rect& viewport) {
-    host_impl_.SetViewportSize(viewport.size());
+    host_impl_.active_tree()->SetDeviceViewportSize(viewport.size());
     host_impl_.pending_tree()
         ->property_trees()
         ->scroll_tree.UpdateScrollOffsetBaseForTesting(
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 05de466..ae7ae9ed 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -74,7 +74,7 @@
  public:
   void SetUp() override {
     TestLayerTreeHostBase::SetUp();
-    host_impl()->SetViewportSize(gfx::Size(10000, 10000));
+    host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(10000, 10000));
   }
 
   LayerTreeSettings CreateSettings() override {
@@ -715,7 +715,7 @@
 TEST_F(PictureLayerImplTest, ScaledBoundsOverflowInt) {
   // Limit visible size.
   gfx::Size viewport_size(1, 1);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(600000, 60);
 
@@ -2039,7 +2039,7 @@
   gfx::Size layer_bounds(200, 200);
   gfx::Size viewport_size(400, 400);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetInitialDeviceScaleFactor(2.f);
 
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());
@@ -2596,7 +2596,7 @@
   host_impl()->CommitComplete();
 
   gfx::Size viewport_size(1000, 1000);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(4000, 4000);
   SetupDefaultTrees(layer_bounds);
@@ -2622,7 +2622,7 @@
   host_impl()->CommitComplete();
 
   gfx::Size viewport_size(1502, 2560);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   float dsf = 3.5f;
   gfx::Size layer_bounds = gfx::ScaleToCeiledSize(viewport_size, 1.0f / dsf);
@@ -2719,7 +2719,7 @@
 
 TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) {
   gfx::Size viewport_size(1000, 1000);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(100, 100);
   SetupDefaultTrees(layer_bounds);
@@ -2777,7 +2777,7 @@
 
 TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) {
   gfx::Size viewport_size(1000, 1000);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(100, 100);
   SetupDefaultTrees(layer_bounds);
@@ -2922,7 +2922,7 @@
 
 TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationAspectRatio) {
   gfx::Size viewport_size(2000, 1000);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(100, 100);
   SetupDefaultTrees(layer_bounds);
@@ -2950,7 +2950,7 @@
 
 TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationAspectRatioTooLarge) {
   gfx::Size viewport_size(2000, 1000);
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   gfx::Size layer_bounds(100, 100);
   SetupDefaultTrees(layer_bounds);
@@ -2980,7 +2980,7 @@
 TEST_F(PictureLayerImplTest, TilingSetRasterQueue) {
   host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
 
-  host_impl()->SetViewportSize(gfx::Size(500, 500));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(500, 500));
 
   gfx::Size layer_bounds(1000, 1000);
 
@@ -3112,7 +3112,7 @@
 TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree) {
   host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
 
-  host_impl()->SetViewportSize(gfx::Size(500, 500));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(500, 500));
 
   gfx::Size layer_bounds(1000, 1000);
 
@@ -3161,7 +3161,7 @@
   gfx::Size layer_bounds(1000, 1000);
   float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
 
-  host_impl()->SetViewportSize(gfx::Size(500, 500));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(500, 500));
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
@@ -3310,7 +3310,7 @@
   gfx::Size viewport_size(1000, 1000);
 
   LayerTestCommon::LayerImplTest impl;
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
@@ -3359,7 +3359,7 @@
   gfx::Size viewport_size(1000, 1000);
 
   LayerTestCommon::LayerImplTest impl;
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilledSolidColor(layer_bounds);
@@ -3392,7 +3392,7 @@
   gfx::Size viewport_size(1000, 1000);
 
   LayerTestCommon::LayerImplTest impl;
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilledSolidColor(layer_bounds);
@@ -3868,7 +3868,7 @@
   std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
 
   gfx::Size layer_bounds(1000, 2000);
-  host_impl()->SetViewportSize(gfx::Size(10000, 20000));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(10000, 20000));
   SetupDefaultTrees(layer_bounds);
 
   ResetTilingsAndRasterScales();
@@ -4021,7 +4021,7 @@
   gfx::Size viewport_size(500, 500);
   gfx::PointF occluding_layer_position(310.f, 0.f);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
@@ -4113,7 +4113,7 @@
   gfx::Size viewport_size(500, 500);
   gfx::PointF occluding_layer_position(310.f, 0.f);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
@@ -4236,7 +4236,7 @@
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
 
   SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
   ASSERT_TRUE(pending_layer()->CanHaveTilings());
@@ -4322,7 +4322,7 @@
   scoped_refptr<FakeRasterSource> active_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetupPendingTree(active_raster_source);
 
   // Partially occlude the active layer.
@@ -4410,7 +4410,7 @@
   gfx::PointF active_occluding_layer_position(0.f, 310.f);
   gfx::Rect invalidation_rect(230, 230, 152, 152);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetInitialDeviceScaleFactor(2.f);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
@@ -4874,7 +4874,7 @@
   gfx::Size layer_bounds(100, 100);
   gfx::Size viewport_size(100, 100);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetInitialDeviceScaleFactor(1.f);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
@@ -4918,7 +4918,7 @@
   gfx::Size layer_bounds(1000, 1000);
   gfx::Size viewport_size(100, 100);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetInitialDeviceScaleFactor(1.f);
 
   SetupDefaultTrees(layer_bounds);
@@ -4948,7 +4948,7 @@
   gfx::Size layer_bounds(100, 100);
   gfx::Size viewport_size(100, 100);
 
-  host_impl()->SetViewportSize(viewport_size);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   SetInitialDeviceScaleFactor(1.f);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
@@ -5033,7 +5033,7 @@
   std::unique_ptr<FakePictureLayerImpl> layer =
       FakePictureLayerImpl::Create(pending_tree, layer_id());
 
-  host_impl()->SetViewportSize(gfx::Size(1000, 1000));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(1000, 1000));
   gfx::Size result;
 
   host_impl()->SetHasGpuRasterizationTrigger(false);
@@ -5063,10 +5063,11 @@
   host_impl()->CommitComplete();
   EXPECT_EQ(host_impl()->gpu_rasterization_status(),
             GpuRasterizationStatus::ON);
-  host_impl()->SetViewportSize(gfx::Size(2000, 2000));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(2000, 2000));
   host_impl()->NotifyReadyToActivate();
 
-  layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
+  layer->set_gpu_raster_max_texture_size(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   result = layer->CalculateTileSize(gfx::Size(10000, 10000));
   EXPECT_EQ(result.width(),
             MathUtil::UncheckedRoundUp(
@@ -5075,8 +5076,9 @@
 
   // Clamp and round-up, when smaller than viewport.
   // Tile-height doubles to 50% when width shrinks to <= 50%.
-  host_impl()->SetViewportSize(gfx::Size(1000, 1000));
-  layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(1000, 1000));
+  layer->set_gpu_raster_max_texture_size(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   result = layer->CalculateTileSize(gfx::Size(447, 10000));
   EXPECT_EQ(result.width(), 448);
   EXPECT_EQ(result.height(), 512);  // 500 + 2, 32-byte aliged.
@@ -5106,11 +5108,12 @@
   host_impl()->CommitComplete();
   EXPECT_EQ(host_impl()->gpu_rasterization_status(),
             GpuRasterizationStatus::ON);
-  host_impl()->SetViewportSize(gfx::Size(2000, 2000));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(2000, 2000));
   host_impl()->NotifyReadyToActivate();
 
   // Basic test.
-  layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
+  layer->set_gpu_raster_max_texture_size(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   result = layer->CalculateTileSize(gfx::Size(10000, 10000));
   EXPECT_EQ(result.width(),
             MathUtil::UncheckedRoundUp(
@@ -5118,16 +5121,18 @@
   EXPECT_EQ(result.height(), 512);
 
   // When using odd sized viewport bounds, we should round up.
-  host_impl()->SetViewportSize(gfx::Size(509, 1000));
-  layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(509, 1000));
+  layer->set_gpu_raster_max_texture_size(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   result = layer->CalculateTileSize(gfx::Size(10000, 10000));
   EXPECT_EQ(result.width(), 288);
   EXPECT_EQ(result.height(), 256);
 
   // If content would fit in a single tile after rounding, we shouldn't halve
   // the tile width.
-  host_impl()->SetViewportSize(gfx::Size(511, 1000));
-  layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(511, 1000));
+  layer->set_gpu_raster_max_texture_size(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   result = layer->CalculateTileSize(gfx::Size(530, 10000));
   EXPECT_EQ(result.width(), 544);
   EXPECT_EQ(result.height(), 256);
@@ -5248,7 +5253,7 @@
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
 
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   host_impl()->CreatePendingTree();
   LayerTreeImpl* pending_tree = host_impl()->pending_tree();
 
@@ -5259,6 +5264,7 @@
   pending_layer->SetDrawsContent(true);
   FakePictureLayerImpl* pending_layer_ptr = pending_layer.get();
   pending_tree->SetRootLayerForTesting(std::move(pending_layer));
+  pending_tree->SetDeviceViewportSize(layer_bounds);
   pending_tree->BuildLayerListAndPropertyTreesForTesting();
 
   // Set PictureLayerImpl::ideal_contents_scale_ to 2.f.
diff --git a/cc/layers/render_surface_impl_unittest.cc b/cc/layers/render_surface_impl_unittest.cc
index 8fb231d..89c6177 100644
--- a/cc/layers/render_surface_impl_unittest.cc
+++ b/cc/layers/render_surface_impl_unittest.cc
@@ -107,7 +107,7 @@
   impl.host_impl()->active_tree()->SetRootLayerForTesting(std::move(root));
 
   impl.host_impl()->active_tree()->SetDeviceScaleFactor(device_scale_factor);
-  impl.host_impl()->SetViewportSize(viewport_size);
+  impl.host_impl()->active_tree()->SetDeviceViewportSize(viewport_size);
   impl.host_impl()->active_tree()->BuildLayerListAndPropertyTreesForTesting();
   impl.host_impl()->active_tree()->UpdateDrawProperties();
 
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index 2217573..2176380 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -246,7 +246,7 @@
       FakeLayerTreeFrameSink::Create3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
   // Set a big enough viewport to show the entire render pass.
-  host_impl.SetViewportSize(gfx::Size(1000, 1000));
+  host_impl.active_tree()->SetDeviceViewportSize(gfx::Size(1000, 1000));
 
   std::unique_ptr<LayerImpl> root_layer =
       LayerImpl::Create(host_impl.active_tree(), 1);
@@ -315,7 +315,7 @@
       FakeLayerTreeFrameSink::Create3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
   // Set a big enough viewport to show the entire render pass.
-  host_impl.SetViewportSize(gfx::Size(1000, 1000));
+  host_impl.active_tree()->SetDeviceViewportSize(gfx::Size(1000, 1000));
 
   std::unique_ptr<LayerImpl> root_layer =
       LayerImpl::Create(host_impl.active_tree(), 1);
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc
index 56d9170..0dbc5e0 100644
--- a/cc/layers/video_layer_impl_unittest.cc
+++ b/cc/layers/video_layer_impl_unittest.cc
@@ -92,7 +92,7 @@
   gfx::Rect visible(layer_size);
 
   LayerTestCommon::LayerImplTest impl;
-  impl.host_impl()->SetViewportSize(layer_size);
+  impl.host_impl()->active_tree()->SetDeviceViewportSize(layer_size);
   DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
   auto* active_tree = impl.host_impl()->active_tree();
 
diff --git a/cc/test/fake_layer_tree_host_impl.cc b/cc/test/fake_layer_tree_host_impl.cc
index 5ae1dc5f..d032695 100644
--- a/cc/test/fake_layer_tree_host_impl.cc
+++ b/cc/test/fake_layer_tree_host_impl.cc
@@ -45,7 +45,7 @@
       notify_tile_state_changed_called_(false) {
   // Explicitly clear all debug settings.
   SetDebugState(LayerTreeDebugState());
-  SetViewportSize(gfx::Size(100, 100));
+  active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   // Start an impl frame so tests have a valid frame_time to work with.
   base::TimeTicks time_ticks =
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc
index 7a683eb0..38ed760 100644
--- a/cc/test/fake_picture_layer_impl.cc
+++ b/cc/test/fake_picture_layer_impl.cc
@@ -100,7 +100,8 @@
   DCHECK(layer_tree_impl()->IsPendingTree());
   Region invalidation_temp = invalidation;
   const PictureLayerTilingSet* pending_set = nullptr;
-  set_gpu_raster_max_texture_size(layer_tree_impl()->device_viewport_size());
+  set_gpu_raster_max_texture_size(
+      layer_tree_impl()->GetDeviceViewport().size());
   UpdateRasterSource(raster_source, &invalidation_temp, pending_set);
 }
 
diff --git a/cc/test/test_layer_tree_host_base.cc b/cc/test/test_layer_tree_host_base.cc
index 8645068..2ab007ed 100644
--- a/cc/test/test_layer_tree_host_base.cc
+++ b/cc/test/test_layer_tree_host_base.cc
@@ -102,6 +102,8 @@
   host_impl()->pending_tree()->PushPageScaleFromMainThread(1.f, 0.00001f,
                                                            100000.f);
   LayerTreeImpl* pending_tree = host_impl()->pending_tree();
+  pending_tree->SetDeviceViewportSize(
+      host_impl()->active_tree()->GetDeviceViewport().size());
   pending_tree->SetDeviceScaleFactor(
       host_impl()->active_tree()->device_scale_factor());
 
diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc
index 8b30a30..8842bc3 100644
--- a/cc/tiles/tile_manager_perftest.cc
+++ b/cc/tiles/tile_manager_perftest.cc
@@ -219,7 +219,7 @@
 
     gfx::Size layer_bounds(width, height);
     gfx::Size viewport(width / 5, height / 5);
-    host_impl()->SetViewportSize(viewport);
+    host_impl()->active_tree()->SetDeviceViewportSize(viewport);
     SetupDefaultTreesWithFixedTileSize(layer_bounds,
                                        settings.default_tile_size);
 
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 87eb976..b9cbd76f 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -96,7 +96,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   std::unique_ptr<RasterTilePriorityQueue> queue(host_impl()->BuildRasterQueue(
@@ -353,7 +353,7 @@
        RasterTilePriorityQueueHighNonIdealTilings) {
   const gfx::Size layer_bounds(1000, 1000);
   const gfx::Size viewport(800, 800);
-  host_impl()->SetViewportSize(viewport);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport);
   SetupDefaultTrees(layer_bounds);
 
   pending_layer()->tilings()->AddTiling(
@@ -428,7 +428,7 @@
        RasterTilePriorityQueueHighLowTilings) {
   const gfx::Size layer_bounds(1000, 1000);
   const gfx::Size viewport(800, 800);
-  host_impl()->SetViewportSize(viewport);
+  host_impl()->active_tree()->SetDeviceViewportSize(viewport);
   SetupDefaultTrees(layer_bounds);
 
   pending_layer()->tilings()->AddTiling(
@@ -501,7 +501,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueInvalidation) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(gfx::Size(500, 500));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(500, 500));
   SetupDefaultTrees(layer_bounds);
 
   // Use a tile's content rect as an invalidation. We should inset it a bit to
@@ -622,7 +622,7 @@
   pending_layer()->test_properties()->AddChild(std::move(pending_child));
 
   // Set a small viewport, so we have soon and eventually tiles.
-  host_impl()->SetViewportSize(gfx::Size(200, 200));
+  host_impl()->active_tree()->SetDeviceViewportSize(gfx::Size(200, 200));
   host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
   host_impl()->pending_tree()->property_trees()->needs_rebuild = true;
   host_impl()->pending_tree()->BuildLayerListAndPropertyTreesForTesting();
@@ -653,7 +653,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
   ASSERT_TRUE(active_layer()->HighResTiling());
   ASSERT_TRUE(active_layer()->LowResTiling());
@@ -828,7 +828,7 @@
 
   gfx::Size layer_bounds(1000, 1000);
 
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
 
   scoped_refptr<FakeRasterSource> pending_raster_source =
       FakeRasterSource::CreateFilled(layer_bounds);
@@ -1030,7 +1030,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueEmptyLayers) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   std::unique_ptr<RasterTilePriorityQueue> queue(host_impl()->BuildRasterQueue(
@@ -1077,7 +1077,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueEmptyLayers) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   std::unique_ptr<RasterTilePriorityQueue> raster_queue(
@@ -1318,7 +1318,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, SetIsLikelyToRequireADraw) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   // Verify that the queue has a required for draw tile at Top.
@@ -1335,7 +1335,7 @@
 TEST_F(TileManagerTilePriorityQueueTest,
        SetIsLikelyToRequireADrawOnZeroMemoryBudget) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   // Verify that the queue has a required for draw tile at Top.
@@ -1356,7 +1356,7 @@
 TEST_F(TileManagerTilePriorityQueueTest,
        SetIsLikelyToRequireADrawOnLimitedMemoryBudget) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   // Verify that the queue has a required for draw tile at Top.
@@ -1388,7 +1388,7 @@
 
 TEST_F(TileManagerTilePriorityQueueTest, DefaultMemoryPolicy) {
   const gfx::Size layer_bounds(1000, 1000);
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
 
   host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
@@ -1922,6 +1922,8 @@
       FakeRasterSource::CreateFilled(kTileSize);
   host_impl()->CreatePendingTree();
   LayerTreeImpl* pending_tree = host_impl()->pending_tree();
+  pending_tree->SetDeviceViewportSize(
+      host_impl()->active_tree()->GetDeviceViewport().size());
 
   // Steal from the recycled tree.
   std::unique_ptr<FakePictureLayerImpl> pending_layer =
@@ -2019,6 +2021,8 @@
       FakeRasterSource::CreateFilled(kTileSize);
   host_impl->CreatePendingTree();
   LayerTreeImpl* pending_tree = host_impl->pending_tree();
+  pending_tree->SetDeviceViewportSize(
+      host_impl->active_tree()->GetDeviceViewport().size());
 
   std::unique_ptr<FakePictureLayerImpl> pending_layer =
       FakePictureLayerImpl::CreateWithRasterSource(pending_tree, kLayerId,
@@ -2101,6 +2105,8 @@
 
   host_impl->CreatePendingTree();
   LayerTreeImpl* pending_tree = host_impl->pending_tree();
+  pending_tree->SetDeviceViewportSize(
+      host_impl->active_tree()->GetDeviceViewport().size());
 
   // Steal from the recycled tree.
   std::unique_ptr<FakePictureLayerImpl> pending_layer =
@@ -2420,7 +2426,7 @@
   // ready instead of marking them ready immediately.
   host_impl()->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY);
   gfx::Size very_small(1, 1);
-  host_impl()->SetViewportSize(very_small);
+  host_impl()->active_tree()->SetDeviceViewportSize(very_small);
 
   gfx::Size layer_bounds(1000, 1000);
   SetupDefaultTrees(layer_bounds);
@@ -2463,7 +2469,7 @@
   EXPECT_GT(orig_num_prepaint, 0u);
   EXPECT_GT(orig_num_required, 0u);
 
-  host_impl()->SetViewportSize(layer_bounds);
+  host_impl()->active_tree()->SetDeviceViewportSize(layer_bounds);
   host_impl()->active_tree()->UpdateDrawProperties();
   host_impl()->pending_tree()->UpdateDrawProperties();
 
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 814f025..8a0c802 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1421,8 +1421,8 @@
 
   tree_impl->set_browser_controls_shrink_blink_size(
       browser_controls_shrink_blink_size_);
-  tree_impl->set_top_controls_height(top_controls_height_);
-  tree_impl->set_bottom_controls_height(bottom_controls_height_);
+  tree_impl->SetTopControlsHeight(top_controls_height_);
+  tree_impl->SetBottomControlsHeight(bottom_controls_height_);
   tree_impl->set_overscroll_behavior(overscroll_behavior_);
   tree_impl->PushBrowserControlsFromMainThread(top_controls_shown_ratio_);
   tree_impl->elastic_overscroll()->PushMainToPending(elastic_overscroll_);
@@ -1440,14 +1440,13 @@
 
   tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_);
   has_pushed_local_surface_id_from_parent_ = true;
+  tree_impl->SetDeviceViewportSize(device_viewport_size_);
 
   if (pending_page_scale_animation_) {
     tree_impl->SetPendingPageScaleAnimation(
         std::move(pending_page_scale_animation_));
   }
 
-  DCHECK(!tree_impl->ViewportSizeInvalid());
-
   tree_impl->set_has_ever_been_drawn(false);
 }
 
@@ -1467,7 +1466,6 @@
   host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_);
   RecordGpuRasterizationHistogram(host_impl);
 
-  host_impl->SetViewportSize(device_viewport_size_);
   host_impl->SetViewportVisibleRect(viewport_visible_rect_);
   host_impl->SetDebugState(debug_state_);
 }
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc
index ab5d5e6..bf611ae 100644
--- a/cc/trees/layer_tree_host_common_perftest.cc
+++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -103,7 +103,7 @@
     RenderSurfaceList update_list;
     LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
         active_tree->root_layer_for_testing(),
-        active_tree->DeviceViewport().size(), host_impl->DrawTransform(),
+        active_tree->GetDeviceViewport().size(), host_impl->DrawTransform(),
         active_tree->device_scale_factor(),
         active_tree->current_page_scale_factor(),
         active_tree->InnerViewportContainerLayer(),
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index f63d1a2..f1531396 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -3051,7 +3051,7 @@
   LayerImpl* surface_child_ptr = surface_child.get();
   LayerImpl* surface_child_mask_ptr = surface_child_mask.get();
 
-  host_impl.SetViewportSize(root->bounds());
+  host_impl.active_tree()->SetDeviceViewportSize(root->bounds());
 
   surface_child->test_properties()->SetMaskLayer(std::move(surface_child_mask));
   surface->test_properties()->AddChild(std::move(surface_child));
@@ -3101,7 +3101,7 @@
   fractional_translate.Translate(10.5f, 20.3f);
   child->test_properties()->transform = fractional_translate;
 
-  host_impl.SetViewportSize(root->bounds());
+  host_impl.active_tree()->SetDeviceViewportSize(root->bounds());
 
   root->test_properties()->AddChild(std::move(child));
   host_impl.active_tree()->SetRootLayerForTesting(std::move(root));
@@ -3161,7 +3161,7 @@
   occluding_child->SetDrawsContent(true);
   occluding_child->SetContentsOpaque(true);
 
-  host_impl.SetViewportSize(root->bounds());
+  host_impl.active_tree()->SetDeviceViewportSize(root->bounds());
 
   child->test_properties()->AddChild(std::move(grand_child));
   root->test_properties()->AddChild(std::move(child));
@@ -8068,7 +8068,7 @@
   // Device viewport accomidated the root and the browser controls.
   gfx::Size device_viewport_size = gfx::Size(300, 600);
 
-  host_impl.SetViewportSize(device_viewport_size);
+  host_impl.active_tree()->SetDeviceViewportSize(device_viewport_size);
   host_impl.active_tree()->SetRootLayerForTesting(
       LayerImpl::Create(host_impl.active_tree(), 1));
 
@@ -10522,7 +10522,7 @@
   gfx::Size device_viewport_size = gfx::Size(300, 600);
   gfx::Rect viewport_visible_rect = gfx::Rect(100, 100, 200, 200);
 
-  host_impl.SetViewportSize(device_viewport_size);
+  host_impl.active_tree()->SetDeviceViewportSize(device_viewport_size);
   host_impl.SetViewportVisibleRect(viewport_visible_rect);
   host_impl.active_tree()->SetRootLayerForTesting(
       LayerImpl::Create(host_impl.active_tree(), 1));
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index cffc4df..69bae67 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -336,8 +336,6 @@
   DCHECK(task_runner_provider_->IsImplThread());
   DidVisibilityChange(this, visible_);
 
-  SetDebugState(settings.initial_debug_state);
-
   // LTHI always has an active tree.
   active_tree_ = std::make_unique<LayerTreeImpl>(
       this, new SyncedProperty<ScaleGroup>, new SyncedBrowserControls,
@@ -357,6 +355,8 @@
   memory_pressure_listener_.reset(
       new base::MemoryPressureListener(base::BindRepeating(
           &LayerTreeHostImpl::OnMemoryPressure, base::Unretained(this))));
+
+  SetDebugState(settings.initial_debug_state);
 }
 
 LayerTreeHostImpl::~LayerTreeHostImpl() {
@@ -543,17 +543,11 @@
   if (resourceless_software_draw_)
     return true;
 
-  if (DeviceViewport().IsEmpty()) {
+  if (active_tree_->GetDeviceViewport().IsEmpty()) {
     TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport",
                          TRACE_EVENT_SCOPE_THREAD);
     return false;
   }
-  if (active_tree_->ViewportSizeInvalid()) {
-    TRACE_EVENT_INSTANT0(
-        "cc", "LayerTreeHostImpl::CanDraw viewport size recently changed",
-        TRACE_EVENT_SCOPE_THREAD);
-    return false;
-  }
   if (EvictedUIResourcesExist()) {
     TRACE_EVENT_INSTANT0(
         "cc", "LayerTreeHostImpl::CanDraw UI resources evicted not recreated",
@@ -1968,7 +1962,7 @@
                                  active_tree_->device_scale_factor();
   active_tree_->GetViewportSelection(&metadata.selection);
   metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get());
-  metadata.viewport_size_in_pixels = device_viewport_size();
+  metadata.viewport_size_in_pixels = active_tree_->GetDeviceViewport().size();
 
 #if defined(OS_ANDROID)
   metadata.top_controls_height =
@@ -2546,7 +2540,7 @@
   hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine |
                                 viz::HitTestRegionFlags::kHitTestMouse |
                                 viz::HitTestRegionFlags::kHitTestTouch;
-  hit_test_region_list->bounds = DeviceViewport();
+  hit_test_region_list->bounds = active_tree_->GetDeviceViewport();
   hit_test_region_list->transform = DrawTransform();
 
   float device_scale_factor = active_tree()->device_scale_factor();
@@ -3222,32 +3216,6 @@
   client_->SetBeginFrameSource(source);
 }
 
-void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
-  if (device_viewport_size == device_viewport_size_)
-    return;
-  TRACE_EVENT_INSTANT2("cc", "LayerTreeHostImpl::SetViewportSize",
-                       TRACE_EVENT_SCOPE_THREAD, "width",
-                       device_viewport_size.width(), "height",
-                       device_viewport_size.height());
-
-  if (pending_tree_)
-    active_tree_->SetViewportSizeInvalid();
-
-  device_viewport_size_ = device_viewport_size;
-
-  UpdateViewportContainerSizes();
-  client_->OnCanDrawStateChanged(CanDraw());
-  SetFullViewportDamage();
-  active_tree_->set_needs_update_draw_properties();
-}
-
-gfx::Rect LayerTreeHostImpl::DeviceViewport() const {
-  if (external_viewport_.IsEmpty())
-    return gfx::Rect(device_viewport_size_);
-
-  return external_viewport_;
-}
-
 void LayerTreeHostImpl::SetViewportVisibleRect(const gfx::Rect& visible_rect) {
   if (visible_rect == viewport_visible_rect_)
     return;
@@ -3257,13 +3225,6 @@
   active_tree_->set_needs_update_draw_properties();
 }
 
-const gfx::Rect LayerTreeHostImpl::ViewportRectForTilePriority() const {
-  if (viewport_rect_for_tile_priority_.IsEmpty())
-    return DeviceViewport();
-
-  return viewport_rect_for_tile_priority_;
-}
-
 const gfx::Transform& LayerTreeHostImpl::DrawTransform() const {
   return external_transform_;
 }
@@ -4606,7 +4567,7 @@
 }
 
 void LayerTreeHostImpl::SetFullViewportDamage() {
-  SetViewportDamage(gfx::Rect(DeviceViewport().size()));
+  SetViewportDamage(active_tree_->GetDeviceViewport());
 }
 
 bool LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) {
@@ -4867,8 +4828,8 @@
     ActivationStateAsValueInto(state);
     state->EndDictionary();
   }
-  MathUtil::AddToTracedValue("device_viewport_size", device_viewport_size_,
-                             state);
+  MathUtil::AddToTracedValue("device_viewport_size",
+                             active_tree_->GetDeviceViewport().size(), state);
 
   std::vector<PrioritizedTile> prioritized_tiles;
   active_tree_->GetAllPrioritizedTilesForTracing(&prioritized_tiles);
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index a4b2e504..ebf00deb 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -442,7 +442,8 @@
   void ReclaimResources(
       const std::vector<viz::ReturnedResource>& resources) override;
   void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override;
-  void SetTreeActivationCallback(const base::Closure& callback) override;
+  void SetTreeActivationCallback(
+      const base::RepeatingClosure& callback) override;
   void OnDraw(const gfx::Transform& transform,
               const gfx::Rect& viewport,
               bool resourceless_software_draw,
@@ -544,11 +545,6 @@
 
   ManagedMemoryPolicy ActualManagedMemoryPolicy() const;
 
-  void SetViewportSize(const gfx::Size& device_viewport_size);
-  const gfx::Size& device_viewport_size() const {
-    return device_viewport_size_;
-  }
-
   void SetViewportVisibleRect(const gfx::Rect& visible_rect);
   gfx::Rect viewport_visible_rect() const { return viewport_visible_rect_; }
 
@@ -630,12 +626,13 @@
   viz::CompositorFrameMetadata MakeCompositorFrameMetadata();
   RenderFrameMetadata MakeRenderFrameMetadata(FrameData* frame);
 
-  // Viewport rectangle and clip in device space.  These rects are used to
-  // prioritize raster and determine what is submitted in a CompositorFrame.
-  gfx::Rect DeviceViewport() const;
+  const gfx::Rect& external_viewport() const { return external_viewport_; }
+
   // Viewport rect to be used for tiling prioritization instead of the
   // DeviceViewport().
-  const gfx::Rect ViewportRectForTilePriority() const;
+  const gfx::Rect& viewport_rect_for_tile_priority() const {
+    return viewport_rect_for_tile_priority_;
+  }
 
   // When a SwapPromiseMonitor is created on the impl thread, it calls
   // InsertSwapPromiseMonitor() to register itself with LayerTreeHostImpl.
@@ -991,12 +988,6 @@
   // manager, if there were no limit on memory usage.
   size_t max_memory_needed_bytes_ = 0;
 
-  // Viewport size passed in from the main thread, in physical pixels.  This
-  // value is the default size for all concepts of physical viewport (draw
-  // viewport, scrolling viewport and device viewport), but it can be
-  // overridden.
-  gfx::Size device_viewport_size_;
-
   // Viewport clip rect passed in from the main thrad, in physical pixels.
   // This is used for out-of-process iframes whose size exceeds the window
   // in order to prevent full raster.
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 6cbf102..e68c5b7 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -147,6 +147,15 @@
     CreateHostImpl(DefaultSettings(), CreateLayerTreeFrameSink());
   }
 
+  void CreatePendingTree() {
+    host_impl_->CreatePendingTree();
+    LayerTreeImpl* pending_tree = host_impl_->pending_tree();
+    pending_tree->SetDeviceViewportSize(
+        host_impl_->active_tree()->GetDeviceViewport().size());
+    pending_tree->SetDeviceScaleFactor(
+        host_impl_->active_tree()->device_scale_factor());
+  }
+
   void TearDown() override {
     if (host_impl_)
       host_impl_->ReleaseLayerTreeFrameSink();
@@ -243,7 +252,7 @@
     layer_tree_frame_sink_ = std::move(layer_tree_frame_sink);
     host_impl_->SetVisible(true);
     bool init = host_impl_->InitializeFrameSink(layer_tree_frame_sink_.get());
-    host_impl_->SetViewportSize(gfx::Size(10, 10));
+    host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 10));
     host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
     host_impl_->active_tree()->SetLocalSurfaceIdFromParent(
         viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u)));
@@ -429,7 +438,7 @@
     gfx::Size scroll_content_size = gfx::Size(345, 3800);
     gfx::Size scrollbar_size = gfx::Size(15, 600);
 
-    host_impl_->SetViewportSize(content_size);
+    host_impl_->active_tree()->SetDeviceViewportSize(content_size);
     std::unique_ptr<LayerImpl> root = LayerImpl::Create(layer_tree_impl, 1);
     root->SetBounds(content_size);
     root->SetPosition(gfx::PointF());
@@ -527,7 +536,7 @@
 
     host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-    host_impl_->SetViewportSize(viewport_size);
+    host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
     host_impl_->active_tree()->DidBecomeActive();
 
     return content_layer;
@@ -597,7 +606,7 @@
     // Create the pending tree.
     host_impl_->BeginCommit();
     LayerTreeImpl* pending_tree = host_impl_->pending_tree();
-    host_impl_->SetViewportSize(layer_size);
+    pending_tree->SetDeviceViewportSize(layer_size);
     pending_tree->SetRootLayerForTesting(
         FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 1,
                                                      raster_source));
@@ -622,7 +631,7 @@
   void WhiteListedTouchActionTestHelper(float device_scale_factor,
                                         float page_scale_factor) {
     LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(200, 200));
-    host_impl_->SetViewportSize(gfx::Size(100, 100));
+    host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
     DrawFrame();
     LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
 
@@ -675,7 +684,7 @@
 
   LayerImpl* CreateLayerForSnapping() {
     LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
-    host_impl_->SetViewportSize(gfx::Size(100, 100));
+    host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
     gfx::Size overflow_size(400, 400);
     EXPECT_EQ(1u, scroll_layer->test_properties()->children.size());
@@ -871,12 +880,12 @@
   on_can_draw_state_changed_called_ = false;
 
   // Toggle the device viewport size to make sure it toggles can_draw.
-  host_impl_->SetViewportSize(gfx::Size());
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size());
   EXPECT_FALSE(host_impl_->CanDraw());
   EXPECT_TRUE(on_can_draw_state_changed_called_);
   on_can_draw_state_changed_called_ = false;
 
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
   EXPECT_TRUE(host_impl_->CanDraw());
   EXPECT_TRUE(on_can_draw_state_changed_called_);
   on_can_draw_state_changed_called_ = false;
@@ -888,7 +897,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   EXPECT_TRUE(host_impl_->CanDraw());
-  host_impl_->SetViewportSize(gfx::Size());
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size());
   EXPECT_FALSE(host_impl_->CanDraw());
 
   auto* fake_layer_tree_frame_sink =
@@ -1015,7 +1024,7 @@
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
@@ -1040,7 +1049,7 @@
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
@@ -1088,7 +1097,7 @@
 
 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   // We should not crash if the tree is replaced while we are scrolling.
@@ -1114,7 +1123,7 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
   LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   scroll->SetWheelEventHandlerRegion(Region(gfx::Rect(20, 20)));
   DrawFrame();
 
@@ -1141,7 +1150,7 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
   LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
 
@@ -1195,7 +1204,7 @@
 
 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
 
   root->set_main_thread_scrolling_reasons(
@@ -1231,7 +1240,7 @@
   gfx::Size scroll_content_size = gfx::Size(345, 3800);
   gfx::Size scrollbar_size = gfx::Size(15, 600);
 
-  host_impl_->SetViewportSize(content_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(content_size);
   std::unique_ptr<LayerImpl> root = LayerImpl::Create(layer_tree_impl, 1);
   root->SetBounds(content_size);
   root->SetPosition(gfx::PointF());
@@ -1283,7 +1292,7 @@
 
 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
   root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
@@ -1339,7 +1348,7 @@
 
 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   LayerImpl* root = *host_impl_->active_tree()->begin();
   root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
@@ -1373,7 +1382,7 @@
 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
   EXPECT_FALSE(host_impl_->active_tree()->have_scroll_event_handlers());
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1387,7 +1396,7 @@
 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
   host_impl_->active_tree()->set_have_scroll_event_handlers(true);
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1400,7 +1409,7 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   DrawFrame();
 
@@ -1673,7 +1682,7 @@
 
 TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   gfx::Size overflow_size(400, 400);
   ASSERT_EQ(1u, scroll_layer->test_properties()->children.size());
@@ -1842,7 +1851,7 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
   gfx::Size overflow_size(400, 400);
   ASSERT_EQ(1u, scroll_layer->test_properties()->children.size());
@@ -1914,9 +1923,9 @@
        AnimationSchedulingPendingTree) {
   EXPECT_FALSE(host_impl_->CommitToActiveTree());
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   auto root_owned = LayerImpl::Create(host_impl_->pending_tree(), 1);
   auto* root = root_owned.get();
   host_impl_->pending_tree()->SetRootLayerForTesting(std::move(root_owned));
@@ -1972,7 +1981,7 @@
        AnimationSchedulingActiveTree) {
   EXPECT_FALSE(host_impl_->CommitToActiveTree());
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
 
   host_impl_->active_tree()->SetRootLayerForTesting(
       LayerImpl::Create(host_impl_->active_tree(), 1));
@@ -2039,7 +2048,7 @@
                                        CreateLayerTreeFrameSink(), &provider);
   EXPECT_TRUE(host_impl_->CommitToActiveTree());
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
 
   auto root_owned = LayerImpl::Create(host_impl_->active_tree(), 1);
   auto* root = root_owned.get();
@@ -2083,7 +2092,7 @@
 }
 
 TEST_F(LayerTreeHostImplTest, AnimationSchedulingOnLayerDestruction) {
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
 
   host_impl_->active_tree()->SetRootLayerForTesting(
       LayerImpl::Create(host_impl_->active_tree(), 1));
@@ -2162,7 +2171,7 @@
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
@@ -2634,7 +2643,7 @@
 TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) {
   LayerImpl* viewport_scroll =
       SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
 
   // Set up two scrolling children of the root, one of which is a scroll parent
   // to the other. Scrolls shouldn't bubbling from the child.
@@ -2715,7 +2724,7 @@
 
 TEST_F(LayerTreeHostImplTest, PinchGesture) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -2889,7 +2898,7 @@
 
 TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollDelta) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -2936,7 +2945,7 @@
 
 TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollFromFractionalActiveBase) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -2972,7 +2981,7 @@
 
 TEST_F(LayerTreeHostImplTest, PinchZoomTriggersPageScaleAnimation) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   float min_page_scale = 1.f;
@@ -3095,7 +3104,7 @@
 
 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -3225,7 +3234,7 @@
 
 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -3284,7 +3293,7 @@
 }
 
 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
   CreateScrollAndContentsLayers(host_impl_->pending_tree(),
                                 gfx::Size(100, 100));
@@ -3410,7 +3419,7 @@
 
 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
@@ -3460,7 +3469,7 @@
 
 TEST_F(LayerTreeHostImplTest, MaxScrollOffsetAffectedByViewportBoundsDelta) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
   DrawFrame();
@@ -3534,7 +3543,7 @@
 
     SetupScrollAndContentsLayers(content_size);
     host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
-    host_impl_->SetViewportSize(
+    host_impl_->active_tree()->SetDeviceViewportSize(
         gfx::Size(content_size.width() / 2, content_size.height() / 2));
 
     std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar =
@@ -3749,7 +3758,7 @@
     bool expecting_animations = animator != LayerTreeSettings::NO_ANIMATOR;
 
     CreateHostImpl(settings, CreateLayerTreeFrameSink());
-    host_impl_->CreatePendingTree();
+    CreatePendingTree();
     CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size);
     std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar =
         SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400,
@@ -3786,7 +3795,7 @@
                             InputHandler::WHEEL);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 5)).get());
     host_impl_->ScrollEnd(EndState().get());
-    host_impl_->CreatePendingTree();
+    CreatePendingTree();
     // To test the case where the effect tree index of scrollbar layer changes,
     // we force the container layer to create a render surface.
     container = host_impl_->pending_tree()->InnerViewportContainerLayer();
@@ -3851,7 +3860,7 @@
 
     CreateHostImpl(settings, CreateLayerTreeFrameSink());
     host_impl_->active_tree()->SetDeviceScaleFactor(1);
-    host_impl_->SetViewportSize(viewport_size);
+    host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
     CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
     host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
         viewport_size);
@@ -3994,7 +4003,7 @@
   gfx::Size content_size(100, 100);
 
   CreateHostImpl(settings, CreateLayerTreeFrameSink());
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size);
   std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar =
       SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400,
@@ -4303,7 +4312,7 @@
 
   CreateHostImpl(settings, CreateLayerTreeFrameSink());
   host_impl_->active_tree()->SetDeviceScaleFactor(device_scale_factor);
-  host_impl_->SetViewportSize(device_viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(device_viewport_size);
 
   CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
   host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
@@ -4386,7 +4395,7 @@
 // |activation_dependencies|.
 TEST_F(LayerTreeHostImplTest, ActivationDependenciesInMetadata) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
 
   std::vector<viz::SurfaceId> primary_surfaces = {
@@ -4469,7 +4478,7 @@
 // damage.
 TEST_F(LayerTreeHostImplTest, SurfaceReferencesChangeCausesDamage) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   auto* fake_layer_tree_frame_sink =
       static_cast<FakeLayerTreeFrameSink*>(host_impl_->layer_tree_frame_sink());
 
@@ -4504,7 +4513,7 @@
 
 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
   DrawFrame();
   {
@@ -4694,7 +4703,7 @@
 };
 
 TEST_F(LayerTreeHostImplTest, DamageShouldNotCareAboutContributingLayers) {
-  host_impl_->SetViewportSize(gfx::Size(10, 10));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 10));
   host_impl_->active_tree()->SetRootLayerForTesting(
       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   auto* root =
@@ -4863,7 +4872,7 @@
 
 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
   gfx::Size big_size(1000, 1000);
-  host_impl_->SetViewportSize(big_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(big_size);
 
   host_impl_->active_tree()->SetRootLayerForTesting(
       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
@@ -5210,14 +5219,14 @@
 }
 
 TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
   CreateScrollAndContentsLayers(host_impl_->pending_tree(),
                                 gfx::Size(100, 100));
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
   host_impl_->ActivateSyncTree();
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   const gfx::ScrollOffset pending_scroll = gfx::ScrollOffset(-100, -100);
   LayerImpl* active_outer_layer =
       host_impl_->active_tree()->OuterViewportScrollLayer();
@@ -5251,7 +5260,7 @@
     bool init = LayerTreeHostImplTest::CreateHostImpl(
         settings, std::move(layer_tree_frame_sink));
     if (init) {
-      host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
+      host_impl_->active_tree()->SetTopControlsHeight(top_controls_height_);
       host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(1.f);
       host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
     }
@@ -5275,7 +5284,7 @@
       const gfx::Size& outer_viewport_size,
       const gfx::Size& scroll_layer_size) {
     tree_impl->set_browser_controls_shrink_blink_size(true);
-    tree_impl->set_top_controls_height(top_controls_height_);
+    tree_impl->SetTopControlsHeight(top_controls_height_);
     tree_impl->SetCurrentBrowserControlsShownRatio(1.f);
     tree_impl->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
     host_impl_->DidChangeBrowserControlsPosition();
@@ -5326,7 +5335,7 @@
     tree_impl->SetViewportLayersFromIds(viewport_ids);
     tree_impl->BuildPropertyTreesForTesting();
 
-    host_impl_->SetViewportSize(inner_viewport_size);
+    host_impl_->active_tree()->SetDeviceViewportSize(inner_viewport_size);
     LayerImpl* root_clip_ptr = tree_impl->root_layer_for_testing();
     EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
   }
@@ -6187,7 +6196,7 @@
     host_impl_->active_tree()->set_browser_controls_shrink_blink_size(false);
     host_impl_->active_tree()->PushBrowserControlsFromMainThread(0);
 
-    host_impl_->CreatePendingTree();
+    CreatePendingTree();
     SetupBrowserControlsAndScrollLayerWithVirtualViewport(
         host_impl_->pending_tree(), inner_viewport_size, outer_viewport_size,
         content_size);
@@ -6302,7 +6311,7 @@
   scroll_container_layer->test_properties()->force_render_surface = true;
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   EXPECT_EQ(
@@ -6327,7 +6336,7 @@
   root->test_properties()->force_render_surface = true;
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   EXPECT_EQ(
@@ -6350,7 +6359,7 @@
   host_impl_->active_tree()->SetRootLayerForTesting(std::move(root));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   // Scroll event is ignored because the input coordinate is outside the layer
@@ -6381,7 +6390,7 @@
   host_impl_->active_tree()->SetRootLayerForTesting(std::move(root));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   // Scroll event is ignored because the scrollable layer is not facing the
@@ -6411,7 +6420,7 @@
   host_impl_->active_tree()->SetRootLayerForTesting(std::move(scroll_layer));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   // Scrolling fails because the content layer is asking to be scrolled on the
@@ -6653,7 +6662,7 @@
       ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(),
                                                      gfx::ScrollOffset(3, 0));
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
   {
     gfx::Vector2d scroll_delta(-8, -7);
@@ -6715,7 +6724,7 @@
       ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(),
                                                      gfx::ScrollOffset(0, 50));
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   base::TimeTicks start_time =
@@ -6817,7 +6826,7 @@
   viewport_ids.inner_viewport_scroll = kViewportScrollLayerId;
   host_impl_->active_tree()->SetViewportLayersFromIds(viewport_ids);
   host_impl_->active_tree()->DidBecomeActive();
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
 
   grand_child_layer->layer_tree_impl()
       ->property_trees()
@@ -6966,7 +6975,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
   host_impl_->active_tree()->DidBecomeActive();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
   {
     gfx::Vector2d scroll_delta(0, 4);
@@ -7025,7 +7034,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
   host_impl_->active_tree()->DidBecomeActive();
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
 
   // Draw one frame and then immediately rebuild the layer tree to mimic a tree
   // synchronization.
@@ -7089,7 +7098,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   gfx::Size surface_size(50, 50);
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   // Scroll to the right in screen coordinates with a gesture.
@@ -7161,7 +7170,7 @@
   ElementId child_scroll_id = LayerIdToElementIdForTesting(child_layer_id);
 
   gfx::Size surface_size(50, 50);
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
   {
     // Scroll down in screen coordinates with a gesture.
@@ -7247,7 +7256,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   gfx::Size surface_size(50, 50);
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
 
   std::unique_ptr<ScrollAndScaleSet> scroll_info;
 
@@ -7308,7 +7317,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   gfx::Size surface_size(50, 50);
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
 
   // Scroll down in screen coordinates with a gesture.
@@ -7368,7 +7377,7 @@
 
 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
   TestInputHandlerClient scroll_watcher;
-  host_impl_->SetViewportSize(gfx::Size(10, 20));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 20));
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   LayerImpl* clip_layer =
       scroll_layer->test_properties()->parent->test_properties()->parent;
@@ -7457,7 +7466,7 @@
   // Forces a full tree synchronization and ensures that the scroll delegate
   // sees the correct size of the new tree.
   gfx::Size new_size(42, 24);
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
   CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
@@ -7481,7 +7490,7 @@
 
 TEST_F(LayerTreeHostImplTest,
        ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
-  host_impl_->SetViewportSize(gfx::Size(10, 20));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 20));
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   LayerImpl* clip_layer =
       scroll_layer->test_properties()->parent->test_properties()->parent;
@@ -7513,7 +7522,7 @@
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
   DrawFrame();
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
@@ -7680,7 +7689,7 @@
       ->scroll_tree.UpdateScrollOffsetBaseForTesting(
           grand_child_layer->element_id(), gfx::ScrollOffset(0, 2));
 
-  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(surface_size);
   DrawFrame();
   {
     gfx::Vector2d scroll_delta(0, -10);
@@ -7791,7 +7800,7 @@
   scroll_layer->SetScrollable(gfx::Size(50, 50));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
   DrawFrame();
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
@@ -8000,7 +8009,7 @@
   LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
 
   CreateBasicVirtualViewportLayers(viewport_size, viewport_size);
-  host_impl_->active_tree()->set_top_controls_height(10);
+  host_impl_->active_tree()->SetTopControlsHeight(10);
   host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(1.f);
 
   LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
@@ -8757,7 +8766,7 @@
 
 TEST_F(LayerTreeHostImplTest, MayContainVideo) {
   gfx::Size big_size(1000, 1000);
-  host_impl_->SetViewportSize(big_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(big_size);
 
   int layer_id = 1;
   host_impl_->active_tree()->SetRootLayerForTesting(
@@ -9029,7 +9038,8 @@
   bool software = false;
   CreateHostImpl(DefaultSettings(), CreateFakeLayerTreeFrameSink(software));
 
-  host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
+  host_impl_->active_tree()->SetDeviceViewportSize(
+      DipSizeToPixelSize(viewport_size_));
   SetupActiveTreeLayers();
   EXPECT_SCOPED(TestLayerCoversFullViewport());
   EXPECT_SCOPED(TestEmptyLayer());
@@ -9044,7 +9054,8 @@
   CreateHostImpl(DefaultSettings(), CreateFakeLayerTreeFrameSink(software));
 
   host_impl_->active_tree()->SetDeviceScaleFactor(2.f);
-  host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
+  host_impl_->active_tree()->SetDeviceViewportSize(
+      DipSizeToPixelSize(viewport_size_));
   SetupActiveTreeLayers();
   EXPECT_SCOPED(TestLayerCoversFullViewport());
   EXPECT_SCOPED(TestEmptyLayer());
@@ -9059,9 +9070,9 @@
   CreateHostImpl(DefaultSettings(), CreateFakeLayerTreeFrameSink(software));
 
   // Pending tree to force active_tree size invalid. Not used otherwise.
-  host_impl_->CreatePendingTree();
-  host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
-  EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+  CreatePendingTree();
+  host_impl_->active_tree()->SetDeviceViewportSize(
+      DipSizeToPixelSize(viewport_size_));
 
   SetupActiveTreeLayers();
   EXPECT_SCOPED(TestEmptyLayerWithOnDraw());
@@ -9076,19 +9087,18 @@
   CreateHostImpl(DefaultSettings(), CreateFakeLayerTreeFrameSink(software));
 
   // Set larger viewport and activate it to active tree.
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   gfx::Size larger_viewport(viewport_size_.width() + 100,
                             viewport_size_.height() + 100);
-  host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
-  EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+  host_impl_->active_tree()->SetDeviceViewportSize(
+      DipSizeToPixelSize(larger_viewport));
   host_impl_->ActivateSyncTree();
   EXPECT_TRUE(did_activate_pending_tree_);
-  EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
 
   // Shrink pending tree viewport without activating.
-  host_impl_->CreatePendingTree();
-  host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
-  EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+  CreatePendingTree();
+  host_impl_->active_tree()->SetDeviceViewportSize(
+      DipSizeToPixelSize(viewport_size_));
 
   SetupActiveTreeLayers();
   EXPECT_SCOPED(TestEmptyLayerWithOnDraw());
@@ -9134,7 +9144,8 @@
   layer_tree_host_impl->InitializeFrameSink(layer_tree_frame_sink.get());
   layer_tree_host_impl->WillBeginImplFrame(
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2));
-  layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
+  layer_tree_host_impl->active_tree()->SetDeviceViewportSize(
+      gfx::Size(500, 500));
 
   std::unique_ptr<LayerImpl> root =
       FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
@@ -9183,7 +9194,7 @@
   EXPECT_EQ(expected_swap_rect.ToString(),
             fake_layer_tree_frame_sink->last_swap_rect().ToString());
 
-  layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
+  layer_tree_host_impl->active_tree()->SetDeviceViewportSize(gfx::Size(10, 10));
   // This will damage everything.
   layer_tree_host_impl->active_tree()
       ->root_layer_for_testing()
@@ -9404,7 +9415,8 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   // Draw a frame. In the first frame, the entire viewport should be damaged.
-  gfx::Rect full_frame_damage(host_impl_->DeviceViewport().size());
+  gfx::Rect full_frame_damage(
+      host_impl_->active_tree()->GetDeviceViewport().size());
   DrawFrameAndTestDamage(full_frame_damage);
 
   // The second frame has damage that doesn't touch the child layer. Its quads
@@ -9431,9 +9443,9 @@
   gfx::Size root_size(2000, 1000);
   gfx::Size device_viewport_size =
       gfx::ScaleToCeiledSize(root_size, device_scale_factor);
-  host_impl_->SetViewportSize(device_viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(device_viewport_size);
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->SetDeviceScaleFactor(device_scale_factor);
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
                                                           16.f);
@@ -9659,7 +9671,8 @@
 
 namespace {
 void ExpectFullDamageAndDraw(LayerTreeHostImpl* host_impl) {
-  gfx::Rect full_frame_damage(host_impl->DeviceViewport().size());
+  gfx::Rect full_frame_damage(
+      host_impl->active_tree()->GetDeviceViewport().size());
   TestFrameData frame;
   EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame));
   ASSERT_EQ(1u, frame.render_passes.size());
@@ -9748,7 +9761,7 @@
     layer_tree_frame_sink_ = CreateLayerTreeFrameSink();
     host_impl_->SetVisible(true);
     host_impl_->InitializeFrameSink(layer_tree_frame_sink_.get());
-    host_impl_->SetViewportSize(gfx::Size(10, 10));
+    host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 10));
   }
 
   FakeLayerTreeHostImpl* fake_host_impl_;
@@ -10218,7 +10231,8 @@
   // Trigger a draw-swap sequence.
   host_impl_->SetNeedsRedraw();
 
-  gfx::Rect full_frame_damage(host_impl_->DeviceViewport().size());
+  gfx::Rect full_frame_damage(
+      host_impl_->active_tree()->GetDeviceViewport().size());
   TestFrameData frame;
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   EXPECT_TRUE(host_impl_->DrawLayers(&frame));
@@ -10269,7 +10283,8 @@
   // Trigger a draw-swap sequence.
   host_impl_->SetNeedsRedraw();
 
-  gfx::Rect full_frame_damage(host_impl_->DeviceViewport().size());
+  gfx::Rect full_frame_damage(
+      host_impl_->active_tree()->GetDeviceViewport().size());
   TestFrameData frame;
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   EXPECT_TRUE(host_impl_->DrawLayers(&frame));
@@ -10418,7 +10433,7 @@
     LayerTreeSettings settings = DefaultSettings();
     settings.commit_to_active_tree = false;
     CreateHostImpl(settings, CreateLayerTreeFrameSink());
-    host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
+    host_impl_->active_tree()->SetTopControlsHeight(top_controls_height_);
     host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(1.f);
   }
 
@@ -10446,8 +10461,8 @@
        BrowserControlsHeightIsCommitted) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   EXPECT_FALSE(did_request_redraw_);
-  host_impl_->CreatePendingTree();
-  host_impl_->sync_tree()->set_top_controls_height(100);
+  CreatePendingTree();
+  host_impl_->sync_tree()->SetTopControlsHeight(100);
   host_impl_->ActivateSyncTree();
   EXPECT_EQ(100, host_impl_->browser_controls_manager()->TopControlsHeight());
 }
@@ -10457,13 +10472,13 @@
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   EXPECT_EQ(0.f, host_impl_->browser_controls_manager()->ControlsTopOffset());
 
-  host_impl_->CreatePendingTree();
-  host_impl_->sync_tree()->set_top_controls_height(0);
+  CreatePendingTree();
+  host_impl_->sync_tree()->SetTopControlsHeight(0);
   host_impl_->ActivateSyncTree();
   EXPECT_EQ(0.f, host_impl_->browser_controls_manager()->ControlsTopOffset());
 
-  host_impl_->CreatePendingTree();
-  host_impl_->sync_tree()->set_top_controls_height(50);
+  CreatePendingTree();
+  host_impl_->sync_tree()->SetTopControlsHeight(50);
   host_impl_->ActivateSyncTree();
   EXPECT_EQ(0.f, host_impl_->browser_controls_manager()->ControlsTopOffset());
 }
@@ -10486,7 +10501,7 @@
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
       BrowserControlsState::kBoth, BrowserControlsState::kShown, false);
   DrawFrame();
@@ -10560,7 +10575,7 @@
 TEST_F(LayerTreeHostImplWithBrowserControlsTest,
        WheelUnhandledByBrowserControls) {
   SetupScrollAndContentsLayers(gfx::Size(100, 200));
-  host_impl_->SetViewportSize(gfx::Size(50, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 100));
   host_impl_->active_tree()->set_browser_controls_shrink_blink_size(true);
   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
       BrowserControlsState::kBoth, BrowserControlsState::kShown, false);
@@ -10603,7 +10618,7 @@
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(100, 200));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 200));
   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
       BrowserControlsState::kBoth, BrowserControlsState::kShown, false);
   DrawFrame();
@@ -10683,7 +10698,7 @@
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
       BrowserControlsState::kBoth, BrowserControlsState::kShown, false);
   float initial_scroll_offset = 50;
@@ -10763,7 +10778,7 @@
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
       BrowserControlsState::kBoth, BrowserControlsState::kShown, false);
   DrawFrame();
@@ -11188,7 +11203,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   const gfx::Size viewport_size(100, 100);
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
 
   const gfx::Transform transform_for_tile_priority;
   const gfx::Transform draw_transform;
@@ -11219,7 +11234,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   const gfx::Size viewport_size(100, 100);
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
 
   const gfx::Transform draw_transform;
   const gfx::Rect draw_viewport1(viewport_size);
@@ -11247,31 +11262,6 @@
   EXPECT_FALSE(last_on_draw_frame_->has_no_damage);
 }
 
-TEST_F(LayerTreeHostImplTest, OnMemoryPressure) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableLowEndDeviceMode);
-
-  gfx::Size size(200, 200);
-  viz::ResourceFormat format = viz::RGBA_8888;
-  gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
-  ResourcePool::InUsePoolResource resource =
-      host_impl_->resource_pool()->AcquireResource(size, format, color_space);
-  host_impl_->resource_pool()->ReleaseResource(std::move(resource));
-
-  size_t current_memory_usage =
-      host_impl_->resource_pool()->GetTotalMemoryUsageForTesting();
-
-  base::MemoryPressureListener::SimulatePressureNotification(
-      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
-  base::RunLoop().RunUntilIdle();
-
-  size_t memory_usage_after_memory_pressure =
-      host_impl_->resource_pool()->GetTotalMemoryUsageForTesting();
-
-  // Memory usage after the memory pressure should be less than previous one.
-  EXPECT_LT(memory_usage_after_memory_pressure, current_memory_usage);
-}
-
 class ResourcelessSoftwareLayerTreeHostImplTest : public LayerTreeHostImplTest {
  protected:
   std::unique_ptr<LayerTreeFrameSink> CreateLayerTreeFrameSink() override {
@@ -11285,7 +11275,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   const gfx::Size viewport_size(100, 100);
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
 
   const gfx::Transform draw_transform;
   const gfx::Rect draw_viewport(viewport_size);
@@ -11313,9 +11303,9 @@
 TEST_F(ResourcelessSoftwareLayerTreeHostImplTest,
        ResourcelessSoftwareDrawSkipsUpdateTiles) {
   const gfx::Size viewport_size(100, 100);
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   scoped_refptr<FakeRasterSource> raster_source(
       FakeRasterSource::CreateFilled(viewport_size));
   std::unique_ptr<FakePictureLayerImpl> layer(
@@ -11352,10 +11342,10 @@
        ExternalTileConstraintReflectedInPendingTree) {
   EXPECT_FALSE(host_impl_->CommitToActiveTree());
   const gfx::Size layer_size(100, 100);
-  host_impl_->SetViewportSize(layer_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(layer_size);
 
   // Set up active and pending tree.
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->SetRootLayerForTesting(
       LayerImpl::Create(host_impl_->pending_tree(), 1));
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
@@ -11365,7 +11355,7 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
   host_impl_->active_tree()->UpdateDrawProperties();
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->UpdateDrawProperties();
   host_impl_->active_tree()->UpdateDrawProperties();
 
@@ -11390,7 +11380,7 @@
                                  ->test_properties()
                                  ->children[0];
 
-  host_impl_->SetViewportSize(gfx::Size(90, 90));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(90, 90));
   host_impl_->active_tree()->UpdateDrawProperties();
   EXPECT_EQ(gfx::Rect(90, 90), content_layer->visible_layer_rect());
 
@@ -11421,7 +11411,7 @@
                                  ->test_properties()
                                  ->children[0];
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->UpdateDrawProperties();
   EXPECT_EQ(gfx::Rect(50, 50), content_layer->visible_layer_rect());
 
@@ -11467,7 +11457,7 @@
   test_layer->test_properties()->transform = perspective_transform;
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   host_impl_->active_tree()->UpdateDrawProperties();
   EffectNode* node =
       host_impl_->active_tree()->property_trees()->effect_tree.Node(
@@ -12211,7 +12201,7 @@
 }
 
 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
 
   Region empty_invalidation;
   scoped_refptr<RasterSource> raster_source_with_tiles(
@@ -12220,7 +12210,8 @@
   std::unique_ptr<FakePictureLayerImpl> layer =
       FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
   layer->SetBounds(gfx::Size(10, 10));
-  layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
+  layer->set_gpu_raster_max_texture_size(
+      host_impl_->active_tree()->GetDeviceViewport().size());
   layer->SetDrawsContent(true);
   layer->tilings()->AddTiling(gfx::AxisTransform2d(), raster_source_with_tiles);
   layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation,
@@ -12249,9 +12240,9 @@
 }
 
 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->ActivateSyncTree();
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
 
   LayerTreeImpl* pending_tree = host_impl_->pending_tree();
 
@@ -12289,7 +12280,7 @@
 
 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
-  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50));
   DrawFrame();
 
   EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
@@ -12815,15 +12806,17 @@
 TEST_F(LayerTreeHostImplTest, UpdatePageScaleFactorOnActiveTree) {
   // Check page scale factor update in property trees when an update is made
   // on the active tree.
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 3.f);
   CreateScrollAndContentsLayers(host_impl_->pending_tree(),
                                 gfx::Size(100, 100));
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
+  LOG(ERROR) << "ACTIVATE SYNC TREE";
   host_impl_->ActivateSyncTree();
+  LOG(ERROR) << "DONE ACTIVATE SYNC TREE";
   DrawFrame();
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   host_impl_->active_tree()->SetPageScaleOnActiveTree(2.f);
   LayerImpl* page_scale_layer = host_impl_->active_tree()->PageScaleLayer();
 
@@ -12846,7 +12839,9 @@
           page_scale_layer->transform_tree_index());
   EXPECT_EQ(pending_tree_node->post_local_scale_factor, 2.f);
 
+  LOG(ERROR) << "2 ACTIVATE SYNC TREE";
   host_impl_->ActivateSyncTree();
+  LOG(ERROR) << "DONE 2 ACTIVATE SYNC TREE";
   host_impl_->active_tree()->UpdateDrawProperties();
   active_tree_node =
       host_impl_->active_tree()->property_trees()->transform_tree.Node(
@@ -12887,9 +12882,9 @@
 }
 
 TEST_F(LayerTreeHostImplTest, JitterTest) {
-  host_impl_->SetViewportSize(gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100));
 
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
   CreateScrollAndContentsLayers(host_impl_->pending_tree(),
                                 gfx::Size(100, 100));
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
@@ -12908,7 +12903,7 @@
     host_impl_->ScrollEnd(EndState().get());
     host_impl_->active_tree()->UpdateDrawProperties();
 
-    host_impl_->CreatePendingTree();
+    CreatePendingTree();
     host_impl_->pending_tree()->set_source_frame_number(i + 1);
     LayerImpl* content_layer = host_impl_->pending_tree()
                                    ->OuterViewportScrollLayer()
@@ -13000,7 +12995,7 @@
 
   CreateHostImpl(settings, CreateLayerTreeFrameSink());
   host_impl_->active_tree()->SetDeviceScaleFactor(1);
-  host_impl_->SetViewportSize(viewport_size);
+  host_impl_->active_tree()->SetDeviceViewportSize(viewport_size);
   CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
   host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
       viewport_size);
@@ -13273,7 +13268,7 @@
   // Create the pending tree.
   host_impl_->BeginCommit();
   LayerTreeImpl* pending_tree = host_impl_->pending_tree();
-  host_impl_->SetViewportSize(layer_size);
+  pending_tree->SetDeviceViewportSize(layer_size);
   pending_tree->SetRootLayerForTesting(
       FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 1,
                                                    raster_source));
@@ -13353,8 +13348,8 @@
 TEST_F(LayerTreeHostImplTest, UpdatedTilingsForNonDrawingLayers) {
   gfx::Size layer_bounds(500, 500);
 
-  host_impl_->SetViewportSize(layer_bounds);
-  host_impl_->CreatePendingTree();
+  host_impl_->active_tree()->SetDeviceViewportSize(layer_bounds);
+  CreatePendingTree();
   std::unique_ptr<LayerImpl> scoped_root =
       LayerImpl::Create(host_impl_->pending_tree(), 1);
   scoped_root->SetBounds(layer_bounds);
@@ -13412,8 +13407,8 @@
 TEST_F(LayerTreeHostImplTest, RasterTilePrioritizationForNonDrawingLayers) {
   gfx::Size layer_bounds(500, 500);
 
-  host_impl_->SetViewportSize(layer_bounds);
-  host_impl_->CreatePendingTree();
+  host_impl_->active_tree()->SetDeviceViewportSize(layer_bounds);
+  CreatePendingTree();
   std::unique_ptr<LayerImpl> scoped_root =
       LayerImpl::Create(host_impl_->pending_tree(), 1);
   scoped_root->SetBounds(layer_bounds);
@@ -13484,7 +13479,7 @@
   LayerTreeSettings settings = DefaultSettings();
   settings.using_synchronous_renderer_compositor = true;
   CreateHostImpl(settings, CreateLayerTreeFrameSink());
-  host_impl_->CreatePendingTree();
+  CreatePendingTree();
 
   gfx::Size bounds(100, 100);
   scoped_refptr<FakeRasterSource> raster_source(
@@ -13717,7 +13712,7 @@
   // Setup surface layers in LayerTreeHostImpl.
   host_impl_->CreatePendingTree();
   host_impl_->ActivateSyncTree();
-  host_impl_->SetViewportSize(gfx::Size(1024, 768));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768));
 
   std::unique_ptr<LayerImpl> root =
       LayerImpl::Create(host_impl_->active_tree(), 1);
@@ -13761,7 +13756,7 @@
   std::unique_ptr<LayerImpl> overlapping_layer =
       LayerImpl::Create(host_impl_->active_tree(), 5);
 
-  host_impl_->SetViewportSize(gfx::Size(1024, 768));
+  host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768));
 
   intermediate_layer->SetPosition(gfx::PointF(200, 300));
   intermediate_layer->SetBounds(gfx::Size(200, 200));
@@ -13891,7 +13886,7 @@
   host_impl_->OnDraw(transform, viewport, resourceless_software_draw,
                      skip_draw);
   EXPECT_EQ(transform, host_impl_->DrawTransform());
-  EXPECT_EQ(viewport, host_impl_->DeviceViewport());
+  EXPECT_EQ(viewport, host_impl_->active_tree()->GetDeviceViewport());
 
   skip_draw = true;
   gfx::Transform new_transform;
@@ -13899,7 +13894,7 @@
   host_impl_->OnDraw(new_transform, new_viewport, resourceless_software_draw,
                      skip_draw);
   EXPECT_EQ(transform, host_impl_->DrawTransform());
-  EXPECT_EQ(viewport, host_impl_->DeviceViewport());
+  EXPECT_EQ(viewport, host_impl_->active_tree()->GetDeviceViewport());
 }
 
 }  // namespace
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 54ef932..934c9d7f 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2917,7 +2917,7 @@
   }
 
   void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
-    EXPECT_EQ(gfx::Rect(20, 20), impl->DeviceViewport());
+    EXPECT_EQ(gfx::Rect(20, 20), impl->active_tree()->GetDeviceViewport());
     EXPECT_EQ(SK_ColorGRAY, impl->active_tree()->background_color());
     EXPECT_EQ(EventListenerProperties::kPassive,
               impl->active_tree()->event_listener_properties(
@@ -3250,7 +3250,7 @@
     EXPECT_NEAR(impl->active_tree()->device_scale_factor(), 1.5f, 0.00001f);
 
     // Device viewport is scaled.
-    EXPECT_EQ(gfx::Rect(60, 60), impl->DeviceViewport());
+    EXPECT_EQ(gfx::Rect(60, 60), impl->active_tree()->GetDeviceViewport());
 
     FakePictureLayerImpl* root = static_cast<FakePictureLayerImpl*>(
         impl->active_tree()->root_layer_for_testing());
@@ -7936,7 +7936,7 @@
                                    DrawResult draw_result) override {
     EXPECT_EQ(DRAW_SUCCESS, draw_result);
     EXPECT_EQ(0, num_swaps_);
-    drawn_viewport_ = host_impl->DeviceViewport();
+    drawn_viewport_ = host_impl->active_tree()->GetDeviceViewport();
     return draw_result;
   }
 
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 47ee02de..46a495e 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -86,7 +86,6 @@
       content_source_id_(0),
       elastic_overscroll_(elastic_overscroll),
       layers_(new OwnedLayerImplList),
-      viewport_size_invalid_(false),
       needs_update_draw_properties_(true),
       scrollbar_geometries_need_update_(false),
       needs_full_tree_sync_(true),
@@ -452,8 +451,8 @@
 
   target_tree->set_browser_controls_shrink_blink_size(
       browser_controls_shrink_blink_size_);
-  target_tree->set_top_controls_height(top_controls_height_);
-  target_tree->set_bottom_controls_height(bottom_controls_height_);
+  target_tree->SetTopControlsHeight(top_controls_height_);
+  target_tree->SetBottomControlsHeight(bottom_controls_height_);
   target_tree->PushBrowserControls(nullptr);
 
   target_tree->set_overscroll_behavior(overscroll_behavior_);
@@ -476,6 +475,7 @@
   if (TakeNewLocalSurfaceIdRequest())
     target_tree->RequestNewLocalSurfaceId();
   target_tree->SetLocalSurfaceIdFromParent(local_surface_id_from_parent());
+  target_tree->SetDeviceViewportSize(device_viewport_size_);
 
   target_tree->pending_page_scale_animation_ =
       std::move(pending_page_scale_animation_);
@@ -497,11 +497,6 @@
       EventListenerClass::kTouchEndOrCancel,
       event_listener_properties(EventListenerClass::kTouchEndOrCancel));
 
-  if (ViewportSizeInvalid())
-    target_tree->SetViewportSizeInvalid();
-  else
-    target_tree->ResetViewportSizeInvalid();
-
   if (hud_layer())
     target_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(
         target_tree->LayerById(hud_layer()->id())));
@@ -897,7 +892,7 @@
     host_impl_->UpdateViewportContainerSizes();
 }
 
-void LayerTreeImpl::set_top_controls_height(float top_controls_height) {
+void LayerTreeImpl::SetTopControlsHeight(float top_controls_height) {
   if (top_controls_height_ == top_controls_height)
     return;
 
@@ -906,7 +901,7 @@
     host_impl_->UpdateViewportContainerSizes();
 }
 
-void LayerTreeImpl::set_bottom_controls_height(float bottom_controls_height) {
+void LayerTreeImpl::SetBottomControlsHeight(float bottom_controls_height) {
   if (bottom_controls_height_ == bottom_controls_height)
     return;
 
@@ -996,7 +991,7 @@
 
   set_needs_update_draw_properties();
   if (IsActiveTree())
-    host_impl_->SetFullViewportDamage();
+    host_impl_->SetViewportDamage(GetDeviceViewport());
   host_impl_->SetNeedUpdateGpuRasterizationStatus();
 }
 
@@ -1015,6 +1010,30 @@
   return new_local_surface_id_request;
 }
 
+void LayerTreeImpl::SetDeviceViewportSize(
+    const gfx::Size& device_viewport_size) {
+  if (device_viewport_size == device_viewport_size_)
+    return;
+  device_viewport_size_ = device_viewport_size;
+
+  set_needs_update_draw_properties();
+  if (!IsActiveTree())
+    return;
+
+  host_impl_->UpdateViewportContainerSizes();
+  host_impl_->OnCanDrawStateChangedForTree();
+  host_impl_->SetViewportDamage(GetDeviceViewport());
+}
+
+gfx::Rect LayerTreeImpl::GetDeviceViewport() const {
+  // TODO(fsamuel): We should plumb |external_viewport| similar to the
+  // way we plumb |device_viewport_size_|.
+  const gfx::Rect& external_viewport = host_impl_->external_viewport();
+  if (external_viewport.IsEmpty())
+    return gfx::Rect(device_viewport_size_);
+  return external_viewport;
+}
+
 void LayerTreeImpl::SetRasterColorSpace(
     int raster_color_space_id,
     const gfx::ColorSpace& raster_color_space) {
@@ -1149,7 +1168,7 @@
     // calculations except when this function is explicitly passed a flag asking
     // us to skip it.
     LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
-        layer_list_[0], DeviceViewport().size(), host_impl_->DrawTransform(),
+        layer_list_[0], GetDeviceViewport().size(), host_impl_->DrawTransform(),
         device_scale_factor(), current_page_scale_factor(), PageScaleLayer(),
         InnerViewportScrollLayer(), OuterViewportScrollLayer(),
         elastic_overscroll()->Current(IsActiveTree()),
@@ -1285,7 +1304,7 @@
       OuterViewportScrollLayer(), OverscrollElasticityLayer(),
       elastic_overscroll()->Current(IsActiveTree()),
       current_page_scale_factor(), device_scale_factor(),
-      gfx::Rect(DeviceViewport().size()), host_impl_->DrawTransform(),
+      gfx::Rect(GetDeviceViewport().size()), host_impl_->DrawTransform(),
       &property_trees_);
   property_trees_.transform_tree.set_source_to_parent_updates_allowed(false);
 }
@@ -1399,7 +1418,7 @@
 
 void LayerTreeImpl::DidBecomeActive() {
   if (next_activation_forces_redraw_) {
-    host_impl_->SetFullViewportDamage();
+    host_impl_->SetViewportDamage(GetDeviceViewport());
     next_activation_forces_redraw_ = false;
   }
 
@@ -1422,20 +1441,6 @@
   return host_impl_->RequiresHighResToDraw();
 }
 
-bool LayerTreeImpl::ViewportSizeInvalid() const {
-  return viewport_size_invalid_;
-}
-
-void LayerTreeImpl::SetViewportSizeInvalid() {
-  viewport_size_invalid_ = true;
-  host_impl_->OnCanDrawStateChangedForTree();
-}
-
-void LayerTreeImpl::ResetViewportSizeInvalid() {
-  viewport_size_invalid_ = false;
-  host_impl_->OnCanDrawStateChangedForTree();
-}
-
 TaskRunnerProvider* LayerTreeImpl::task_runner_provider() const {
   return host_impl_->task_runner_provider();
 }
@@ -1484,10 +1489,6 @@
   return host_impl_->memory_history();
 }
 
-gfx::Size LayerTreeImpl::device_viewport_size() const {
-  return host_impl_->device_viewport_size();
-}
-
 gfx::Rect LayerTreeImpl::viewport_visible_rect() const {
   return host_impl_->viewport_visible_rect();
 }
@@ -1538,12 +1539,12 @@
   return host_impl_->CurrentBeginFrameInterval();
 }
 
-gfx::Rect LayerTreeImpl::DeviceViewport() const {
-  return host_impl_->DeviceViewport();
-}
-
 const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const {
-  return host_impl_->ViewportRectForTilePriority();
+  const gfx::Rect& viewport_rect_for_tile_priority =
+      host_impl_->viewport_rect_for_tile_priority();
+  return viewport_rect_for_tile_priority.IsEmpty()
+             ? GetDeviceViewport()
+             : viewport_rect_for_tile_priority;
 }
 
 std::unique_ptr<ScrollbarAnimationController>
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 6f54954..877b0a7 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -117,7 +117,6 @@
   ImageAnimationController* image_animation_controller() const;
   FrameRateCounter* frame_rate_counter() const;
   MemoryHistory* memory_history() const;
-  gfx::Size device_viewport_size() const;
   gfx::Rect viewport_visible_rect() const;
   DebugRectHistory* debug_rect_history() const;
   bool IsActiveTree() const;
@@ -129,7 +128,6 @@
   bool PinchGestureActive() const;
   viz::BeginFrameArgs CurrentBeginFrameArgs() const;
   base::TimeDelta CurrentBeginFrameInterval() const;
-  gfx::Rect DeviceViewport() const;
   const gfx::Rect ViewportRectForTilePriority() const;
   std::unique_ptr<ScrollbarAnimationController>
   CreateScrollbarAnimationController(ElementId scroll_element_id,
@@ -330,6 +328,14 @@
     return new_local_surface_id_request_;
   }
 
+  void SetDeviceViewportSize(const gfx::Size& device_viewport_size);
+
+  // TODO(fsamuel): The reason this is not a trivial accessor is because it
+  // may return an external viewport specified in LayerTreeHostImpl. In the
+  // future, all properties should flow through the pending and active layer
+  // trees and we shouldn't need to reach out to LayerTreeHostImpl.
+  gfx::Rect GetDeviceViewport() const;
+
   void SetRasterColorSpace(int raster_color_space_id,
                            const gfx::ColorSpace& raster_color_space);
   const gfx::ColorSpace& raster_color_space() const {
@@ -426,12 +432,6 @@
 
   void DidBecomeActive();
 
-  // Set on the active tree when the viewport size recently changed
-  // and the active tree's size is now out of date.
-  bool ViewportSizeInvalid() const;
-  void SetViewportSizeInvalid();
-  void ResetViewportSizeInvalid();
-
   // Used for accessing the task runner and debug assertions.
   TaskRunnerProvider* task_runner_provider() const;
 
@@ -520,10 +520,10 @@
   float CurrentBrowserControlsShownRatio() const {
     return top_controls_shown_ratio_->Current(IsActiveTree());
   }
-  void set_top_controls_height(float top_controls_height);
+  void SetTopControlsHeight(float top_controls_height);
   float top_controls_height() const { return top_controls_height_; }
   void PushBrowserControlsFromMainThread(float top_controls_shown_ratio);
-  void set_bottom_controls_height(float bottom_controls_height);
+  void SetBottomControlsHeight(float bottom_controls_height);
   float bottom_controls_height() const { return bottom_controls_height_; }
 
   void set_overscroll_behavior(const OverscrollBehavior& behavior);
@@ -635,6 +635,7 @@
   uint32_t content_source_id_;
   viz::LocalSurfaceId local_surface_id_from_parent_;
   bool new_local_surface_id_request_ = false;
+  gfx::Size device_viewport_size_;
 
   scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
 
@@ -673,7 +674,6 @@
   // would not be fully covered by opaque content.
   Region unoccluded_screen_space_region_;
 
-  bool viewport_size_invalid_;
   bool needs_update_draw_properties_;
 
   // True if a scrollbar geometry value has changed. For example, if the scroll
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index f4c3368..9cd9d6c 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -100,7 +100,7 @@
     root->test_properties()->AddChild(std::move(left_child));
     root->test_properties()->AddChild(std::move(right_child));
 
-    host_impl().SetViewportSize(root->bounds());
+    host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
     host_impl().active_tree()->SetRootLayerForTesting(std::move(root));
     host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
     CHECK_EQ(1u, GetRenderSurfaceList().size());
@@ -124,7 +124,7 @@
   root->SetBounds(bounds);
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -163,7 +163,7 @@
   root->SetBounds(bounds);
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
   EXPECT_EQ(
       gfx::RectF(gfx::SizeF(bounds)),
@@ -171,7 +171,7 @@
   EXPECT_EQ(gfx::Rect(bounds), root->visible_layer_rect());
 
   gfx::Size new_bounds(50, 50);
-  host_impl().SetViewportSize(new_bounds);
+  host_impl().active_tree()->SetDeviceViewportSize(new_bounds);
   gfx::PointF test_point(51.f, 51.f);
   host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
   EXPECT_EQ(
@@ -191,7 +191,7 @@
   hud->SetBounds(gfx::Size(200, 200));
   hud->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(hud->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(hud->bounds());
   host_impl().active_tree()->set_hud_layer(hud.get());
   root->test_properties()->AddChild(std::move(hud));
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
@@ -239,7 +239,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
   // Sanity check the scenario we just created.
   ASSERT_EQ(1u, GetRenderSurfaceList().size());
@@ -293,7 +293,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -338,7 +338,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -414,7 +414,7 @@
   render_surface->test_properties()->AddChild(std::move(scale));
   root->test_properties()->AddChild(std::move(render_surface));
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   gfx::PointF test_point(160.f, 160.f);
@@ -449,7 +449,7 @@
   root->test_properties()->AddChild(std::move(child1));
   root->test_properties()->AddChild(std::move(child2));
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   gfx::PointF test_point(50.f, 50.f);
@@ -475,7 +475,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -533,7 +533,7 @@
     root->test_properties()->AddChild(std::move(clipping_layer));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -631,7 +631,7 @@
     ExecuteCalculateDrawProperties(root);
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
   // (11, 89) is close to the the bottom left corner within the clip, but it is
   // not inside the layer.
@@ -709,7 +709,7 @@
     root->test_properties()->AddChild(std::move(intermediate_layer));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -787,7 +787,7 @@
   LayerImpl* child2 = root->test_properties()->children[1];
   LayerImpl* grand_child1 = child1->test_properties()->children[0];
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -939,7 +939,7 @@
   LayerImpl* child2 = root->test_properties()->children[1];
   LayerImpl* grand_child1 = child1->test_properties()->children[0];
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1028,7 +1028,7 @@
     root->test_properties()->AddChild(std::move(child));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   gfx::PointF test_point(12.f, 52.f);
@@ -1071,7 +1071,7 @@
     root->test_properties()->AddChild(std::move(child));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   gfx::PointF test_point(12.f, 52.f);
@@ -1133,7 +1133,7 @@
   LayerImpl* child2 = root->test_properties()->children[1];
   LayerImpl* grand_child1 = child1->test_properties()->children[0];
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1212,7 +1212,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1290,7 +1290,7 @@
   root->SetDrawsContent(true);
   root->SetTouchActionRegion(touch_action_region);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1358,7 +1358,7 @@
   root->SetDrawsContent(true);
   root->SetTouchActionRegion(touch_action_region);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1431,7 +1431,7 @@
   float max_page_scale_factor = 10.f;
   gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
       root->bounds(), device_scale_factor * page_scale_factor);
-  host_impl().SetViewportSize(scaled_bounds_for_root);
+  host_impl().active_tree()->SetDeviceViewportSize(scaled_bounds_for_root);
 
   host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
   LayerTreeImpl::ViewportLayerIds viewport_ids;
@@ -1572,7 +1572,7 @@
     root->test_properties()->AddChild(std::move(clipping_layer));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1662,7 +1662,7 @@
   float max_page_scale_factor = 1.f;
   gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
       root->bounds(), device_scale_factor * page_scale_factor);
-  host_impl().SetViewportSize(scaled_bounds_for_root);
+  host_impl().active_tree()->SetDeviceViewportSize(scaled_bounds_for_root);
 
   host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
   LayerTreeImpl::ViewportLayerIds viewport_ids;
@@ -1728,7 +1728,7 @@
     root->test_properties()->AddChild(std::move(notouch_layer));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1787,7 +1787,7 @@
     test_layer->SetTouchActionRegion(touch_action_region);
     root->test_properties()->AddChild(std::move(test_layer));
   }
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   LayerImpl* test_layer = root->test_properties()->children[0];
@@ -1847,7 +1847,7 @@
   root->SetBounds(gfx::Size(100, 100));
   root->SetDrawsContent(true);
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1928,7 +1928,7 @@
     root->test_properties()->AddChild(std::move(clipping_layer));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -2011,7 +2011,7 @@
   float page_scale_factor = 5.f;
   gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
       root->bounds(), device_scale_factor * page_scale_factor);
-  host_impl().SetViewportSize(scaled_bounds_for_root);
+  host_impl().active_tree()->SetDeviceViewportSize(scaled_bounds_for_root);
 
   LayerTreeImpl::ViewportLayerIds viewport_ids;
   viewport_ids.page_scale = root->id();
@@ -2068,6 +2068,7 @@
   LayerImpl* root = root_layer();
   root->SetDrawsContent(true);
   root->SetBounds(gfx::Size(100, 100));
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
 
   int root_layer_id = root->id();
   int sub_layer_id = 2;
@@ -2162,7 +2163,7 @@
     root->test_properties()->AddChild(std::move(child));
   }
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   LayerSelection input;
@@ -2263,7 +2264,7 @@
   root->test_properties()->AddChild(std::move(left_child));
   root->test_properties()->AddChild(std::move(right_child));
 
-  host_impl().SetViewportSize(root->bounds());
+  host_impl().active_tree()->SetDeviceViewportSize(root->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
   CHECK_EQ(1u, GetRenderSurfaceList().size());
 
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 3ef4422..966124c 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -398,9 +398,8 @@
   if (smoothness_priority_expiration_notifier_.HasPendingNotification())
     tree_priority = SMOOTHNESS_TAKES_PRIORITY;
 
-  // New content always takes priority when there is an invalid viewport size or
-  // ui resources have been evicted.
-  if (host_impl_->active_tree()->ViewportSizeInvalid() ||
+  // New content always takes priority when ui resources have been evicted.
+  if (host_impl_->active_tree()->GetDeviceViewport().size().IsEmpty() ||
       host_impl_->EvictedUIResourcesExist() || input_throttled_until_commit_) {
     // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
     // tree might be freed. We need to set RequiresHighResToDraw to ensure that
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashScreenController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashScreenController.java
index dcc1504..b9ba687e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashScreenController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashScreenController.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.util.DisplayMetrics;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -240,16 +241,19 @@
         int bigThreshold =
                 resources.getDimensionPixelSize(R.dimen.webapp_splash_image_size_threshold);
 
+        DisplayMetrics metrics =
+                ContextUtils.getApplicationContext().getResources().getDisplayMetrics();
+
         // Inflate the correct layout for the image.
         int layoutId;
-        if (displayIcon == null || displayIcon.getWidth() < minimiumSizeThreshold
+        if (displayIcon == null || displayIcon.getScaledWidth(metrics) < minimiumSizeThreshold
                 || (displayIcon == webappInfo.icon() && webappInfo.isIconGenerated())) {
             mWebappUma.recordSplashscreenIconType(WebappUma.SplashScreenIconType.NONE);
             layoutId = R.layout.webapp_splash_screen_no_icon;
         } else {
             // The size of the splash screen image determines which layout to use.
-            boolean isUsingSmallSplashImage = displayIcon.getWidth() <= bigThreshold
-                    || displayIcon.getHeight() <= bigThreshold;
+            boolean isUsingSmallSplashImage = displayIcon.getScaledWidth(metrics) <= bigThreshold
+                    || displayIcon.getScaledHeight(metrics) <= bigThreshold;
             if (isUsingSmallSplashImage) {
                 layoutId = R.layout.webapp_splash_screen_small;
             } else {
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
index 40b00af1..6c71347 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
@@ -29,6 +29,7 @@
 <translation id="1201402288615127009">التالي</translation>
 <translation id="1204037785786432551">تنزيل الرابط</translation>
 <translation id="1206892813135768548">نسخ نص الرابط</translation>
+<translation id="1208340532756947324">للمزامنة والتخصيص على جميع الأجهزة، يمكنك تفعيل المزامنة.</translation>
 <translation id="1209206284964581585">إخفاء الآن</translation>
 <translation id="123724288017357924">إعادة تحميل الصفحة الحالية مع تجاهل المحتوى المُخزَّن مؤقتًا</translation>
 <translation id="124116460088058876">مزيد من اللغات</translation>
@@ -129,6 +130,7 @@
 <translation id="1989112275319619282">تصفّح</translation>
 <translation id="1993768208584545658">يريد <ph name="SITE" /> الاقتران</translation>
 <translation id="1994173015038366702">‏عنوان URL للموقع</translation>
+<translation id="2002537628803770967">‏بطاقات الائتمان والعناوين باستخدام Google Pay</translation>
 <translation id="200815880754187296">تطبيقات أخرى بحجم <ph name="KILOBYTES" /> كيلوبايت</translation>
 <translation id="2017836877785168846">مسح السجل وعمليات الإكمال التلقائي في شريط العناوين.</translation>
 <translation id="2021896219286479412">عناصر التحكم لموقع في وضع ملء الشاشة</translation>
@@ -225,6 +227,7 @@
 <translation id="2777555524387840389">عدد الثواني المتبقية: <ph name="SECONDS" /></translation>
 <translation id="2781151931089541271">يتبقى ثانية واحدة</translation>
 <translation id="2810645512293415242">صفحة مبسَّطة لحفظ البيانات والاستمتاع بتحميل أسرع.</translation>
+<translation id="2818669890320396765">للحصول على الإشارات المرجعية على جميع أجهزتك، يُرجى تسجيل الدخول وتفعيل المزامنة.</translation>
 <translation id="2836148919159985482">المس زر الرجوع للخروج من وضع ملء الشاشة.</translation>
 <translation id="2842985007712546952">المجلد الرئيسي</translation>
 <translation id="2870560284913253234">الموقع</translation>
@@ -303,6 +306,7 @@
 <translation id="3549657413697417275">البحث في السجل</translation>
 <translation id="3552151358455404883">‏إدارة مزامنة Chrome والتخصيص في <ph name="BEGIN_LINK1" />الإعدادات<ph name="END_LINK1" /></translation>
 <translation id="3557336313807607643">إضافة إلى جهات الاتصال</translation>
+<translation id="3568688522516854065">للحصول على علامات التبويب من أجهزتك الأخرى، يُرجى تسجيل الدخول وتفعيل المزامنة.</translation>
 <translation id="3587482841069643663">الكل</translation>
 <translation id="3590487821116122040">‏سعة تخزين الموقع التي لا يعتقد Chrome أنها مهمة (مثل المواقع التي لا تتضمَّن إعدادات محفوظة أو تلك التي لا تزورها مرارًا)</translation>
 <translation id="3599863153486145794">‏يمسح السجل من كل الأجهزة التي تم تسجيل الدخول عليها. وقد يتضمن حسابك في Google نماذج أخرى من سجل التصفح في <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -375,6 +379,7 @@
 <translation id="4192273449750167573">مراجعة الإعدادات في الشاشة التالية</translation>
 <translation id="4195643157523330669">فتح الإشارة في علامة تبويب جديدة</translation>
 <translation id="4198423547019359126">ما من مواقع تنزيل متاحة</translation>
+<translation id="4209895695669353772">‏للحصول على محتوى مُخصَّص اقترحته Google، يُرجى تفعيل المزامنة.</translation>
 <translation id="4226663524361240545">يمكن أن تؤدي الإشعارات إلى اهتزاز الجهاز</translation>
 <translation id="4242533952199664413">فتح الإعدادات</translation>
 <translation id="424864128008805179">‏هل تريد الخروج من Chrome؟</translation>
@@ -400,6 +405,7 @@
 <translation id="4452548195519783679">أُضيفَت إشارة مرجعية إلى <ph name="FOLDER_NAME" /></translation>
 <translation id="4453340223357552416">تم تنزيل <ph name="FILE_NAME" /> في <ph name="PRODUCT_NAME" /></translation>
 <translation id="4468959413250150279">كتم صوت موقع ويب معين.</translation>
+<translation id="4472118726404937099">للمزامنة والتخصيص على جميع الأجهزة، يُرجى تسجيل الدخول وتفعيل المزامنة.</translation>
 <translation id="4479647676395637221">السؤال أولاً قبل السماح للمواقع باستخدام الكاميرا (موصى به)</translation>
 <translation id="4487967297491345095">‏سيتم حذف جميع بيانات تطبيق Chrome نهائيًا. ويشمل ذلك جميع الملفات والإعدادات والحسابات وقواعد البيانات وما إلى ذلك.</translation>
 <translation id="4508440807153586353">‏لا يمكن لأحد قراءة بياناتك المشفرة سوى من لديه عبارة المرور التي تستخدمها.
@@ -585,6 +591,7 @@
 <translation id="5854790677617711513">مرّ عليها أكثر من 30 يومًا</translation>
 <translation id="5858741533101922242">‏يتعذر على Chrome تشغيل محوّل البلوتوث</translation>
 <translation id="5860033963881614850">إيقاف</translation>
+<translation id="5862731021271217234">للحصول على علامات التبويب من أجهزتك الأخرى، يُرجى تفعيل المزامنة.</translation>
 <translation id="5864174910718532887">التفاصيل: تم الترتيب بحسب اسم موقع الويب</translation>
 <translation id="5864419784173784555">في انتظار تنزيل آخر…</translation>
 <translation id="5869522115854928033">كلمات المرور المحفوظة</translation>
@@ -863,6 +870,7 @@
 <translation id="8100932616285851614">تم إغلاق لوحة التنقل</translation>
 <translation id="8103578431304235997">علامة تبويب للتصفح المتخفي</translation>
 <translation id="8105951947646329362">اقتراح الصفحات ذات الصلة</translation>
+<translation id="8109613176066109935">للحصول على الإشارات المرجعية على جميع أجهزتك، يُرجى تفعيل المزامنة.</translation>
 <translation id="8116925261070264013">مواقع الويب التي تم كتم الصوت فيها</translation>
 <translation id="813082847718468539">عرض معلومات الموقع</translation>
 <translation id="8168435359814927499">المحتوى</translation>
@@ -967,6 +975,7 @@
 <translation id="9065203028668620118">تحرير</translation>
 <translation id="9070377983101773829">بدء البحث الصوتي</translation>
 <translation id="9071742570345586758">‏لعرض محتوى الواقع الافتراضي، يلزمك تثبيت خدمات Google VR</translation>
+<translation id="9074336505530349563">‏للحصول على محتوى مُخصَّص اقترحته Google، يُرجى تسجيل الدخول وتفعيل المزامنة.</translation>
 <translation id="9086455579313502267">تعذر الدخول إلى الشبكة</translation>
 <translation id="9099018167121903954">تم تنزيل <ph name="KILOBYTES" /> كيلوبايت</translation>
 <translation id="9100505651305367705">اقتراح مشاهدة المقالات في العرض المبسَّط إذا كان ذلك متاحًا</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
index 0ba4b715..85630a0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
@@ -18,7 +18,7 @@
 <translation id="1141800923049248244">{FILE_COUNT,plural, =1{1 Download ausstehend.}other{# Downloads ausstehend.}}</translation>
 <translation id="1145536944570833626">Vorhandene Daten löschen</translation>
 <translation id="1146678959555564648">VR aktivieren</translation>
-<translation id="114721135501989771">Chrome intelligent nutzen mit Google</translation>
+<translation id="114721135501989771">Chrome cleverer nutzen – dank Google</translation>
 <translation id="1157102636231978136">Mit Ihrem Google-Konto synchronisierte Browserdaten und -aktivitäten</translation>
 <translation id="116280672541001035">Genutzt</translation>
 <translation id="1172593791219290334">"Beim Start"-Seite</translation>
@@ -35,7 +35,7 @@
 <translation id="124116460088058876">Weitere Sprachen</translation>
 <translation id="124678866338384709">Aktuellen Tab schließen</translation>
 <translation id="1258753120186372309">Google-Doodle: <ph name="DOODLE_DESCRIPTION" /></translation>
-<translation id="127138278192656016">Synchronisierung und alle Dienste verwenden</translation>
+<translation id="127138278192656016">Synchronisierung und alle Dienste nutzen</translation>
 <translation id="1272079795634619415">Stopp</translation>
 <translation id="1283039547216852943">Zum Maximieren tippen</translation>
 <translation id="1285320974508926690">Diese Website nie übersetzen</translation>
@@ -186,7 +186,7 @@
 <translation id="2426805022920575512">Anderes Konto auswählen</translation>
 <translation id="2433507940547922241">Darstellung</translation>
 <translation id="2434158240863470628">Download abgeschlossen <ph name="SEPARATOR" /> <ph name="BYTES_DOWNLOADED" /></translation>
-<translation id="2436117022029368436">Mit Google kommunizieren, um das Surferlebnis und Chrome zu verbessern</translation>
+<translation id="2436117022029368436">Funktionen nutzen, die helfen, Chrome für Sie noch besser zu machen</translation>
 <translation id="2440823041667407902">Standortzugriff</translation>
 <translation id="2450083983707403292">Möchten Sie den Download von <ph name="FILE_NAME" /> noch einmal starten?</translation>
 <translation id="2476578072172137802">Website-Einstellungen</translation>
@@ -241,7 +241,7 @@
 <translation id="290376772003165898">Ist diese Seite nicht auf <ph name="LANGUAGE" />?</translation>
 <translation id="2913331724188855103">Websites dürfen Cookiedaten speichern und lesen (empfohlen)</translation>
 <translation id="2932150158123903946">Google <ph name="APP_NAME" />-Speicher</translation>
-<translation id="2943166482989655199">Verbessern Sie Chrome und die Sicherheit, indem Sie System- und Nutzungsdaten an Google senden</translation>
+<translation id="2943166482989655199">System- und Nutzungsdaten an Google senden, um Chrome noch besser und sicherer zu machen</translation>
 <translation id="2956410042958133412">Dieses Konto wird von <ph name="PARENT_NAME_1" /> und <ph name="PARENT_NAME_2" /> verwaltet.</translation>
 <translation id="2960796085439532066">Copyright <ph name="YEAR" /> Google Inc. Alle Rechte vorbehalten.</translation>
 <translation id="2962095958535813455">Zu Inkognito-Tabs gewechselt</translation>
@@ -963,7 +963,7 @@
 <translation id="8972098258593396643">In Standardordner herunterladen?</translation>
 <translation id="8979405271719829084">Videos herunterladen, um sie später anzusehen</translation>
 <translation id="8981454092730389528">Google-Aktivitätseinstellungen</translation>
-<translation id="8983677657449185470">Ich möchte bei der Optimierung von Safe Browsing helfen</translation>
+<translation id="8983677657449185470">Bei der Optimierung von Safe Browsing helfen</translation>
 <translation id="8986494364107987395">Nutzungsstatistiken und Absturzberichte automatisch an Google senden</translation>
 <translation id="8993760627012879038">Neuen Tab im Inkognitomodus öffnen</translation>
 <translation id="8998729206196772491">Sie melden sich mit einem von <ph name="MANAGED_DOMAIN" /> verwalteten Konto an und geben dem Administrator der Domain Kontrolle über Ihre Chrome-Daten. Die Daten werden diesem Konto dauerhaft zugeordnet. Wenn Sie sich von Chrome abmelden, werden Ihre Daten auf dem Gerät gelöscht, bleiben jedoch in Ihrem Google-Konto erhalten.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
index 50d1aeb..4897fc8 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
@@ -18,7 +18,7 @@
 <translation id="1141800923049248244">{FILE_COUNT,plural, =1{1 descarga pendiente}other{# descargas pendientes}}</translation>
 <translation id="1145536944570833626">Borra los datos existentes.</translation>
 <translation id="1146678959555564648">Entrar al modo RV</translation>
-<translation id="114721135501989771">Obtener las funciones inteligentes de Google en Chrome</translation>
+<translation id="114721135501989771">Obtén las mejores funciones de Google en Chrome</translation>
 <translation id="1157102636231978136">Tus datos de navegación y actividad, sincronizados con tu cuenta de Google</translation>
 <translation id="116280672541001035">Usados</translation>
 <translation id="1172593791219290334">Página de inicio</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
index 681fcbc..10b8c72 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
@@ -18,7 +18,7 @@
 <translation id="1141800923049248244">{FILE_COUNT,plural, =1{1 download tertunda.}other{# download tertunda.}}</translation>
 <translation id="1145536944570833626">Hapus data yang sudah ada.</translation>
 <translation id="1146678959555564648">Masuki VR</translation>
-<translation id="114721135501989771">Dapatkan perangkat smart Google di Chrome</translation>
+<translation id="114721135501989771">Dapatkan kecanggihan Google di Chrome</translation>
 <translation id="1157102636231978136">Data dan aktivitas browsing internet Anda disinkronkan ke Akun Google</translation>
 <translation id="116280672541001035">Digunakan</translation>
 <translation id="1172593791219290334">Halaman Awal</translation>
@@ -35,7 +35,7 @@
 <translation id="124116460088058876">Bahasa lainnya</translation>
 <translation id="124678866338384709">Menutup tab aktif</translation>
 <translation id="1258753120186372309">Google doodle: <ph name="DOODLE_DESCRIPTION" /></translation>
-<translation id="127138278192656016">Menggunakan sinkronisasi dan semua layanan</translation>
+<translation id="127138278192656016">Gunakan sinkronisasi dan semua layanan</translation>
 <translation id="1272079795634619415">Berhenti</translation>
 <translation id="1283039547216852943">Tap untuk meluaskan</translation>
 <translation id="1285320974508926690">Jangan pernah terjemahkan situs ini</translation>
@@ -77,7 +77,7 @@
 <translation id="1569387923882100876">Perangkat yang Terhubung</translation>
 <translation id="1571304935088121812">Salin nama pengguna</translation>
 <translation id="1612196535745283361">Chrome memerlukan akses lokasi untuk memindai perangkat. Akses lokasi <ph name="BEGIN_LINK" />dinonaktifkan untuk perangkat ini<ph name="END_LINK" />.</translation>
-<translation id="162035744160882748">Mengaktifkan sinkronisasi, personalisasi, dan layanan Google lainnya</translation>
+<translation id="162035744160882748">Aktifkan sinkronisasi, personalisasi, dan layanan Google lainnya</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Cegah dialog lain dari halaman ini.</translation>
 <translation id="1628019612362412531">{NUM_SELECTED,plural, =1{Hapus 1 item yang dipilih}other{Hapus # item yang dipilih}}</translation>
@@ -707,7 +707,7 @@
 <translation id="6820686453637990663">CVC</translation>
 <translation id="6831043979455480757">Terjemahkan</translation>
 <translation id="6846298663435243399">Memuat…</translation>
-<translation id="685040365210406336">Tidak melakukan perubahan</translation>
+<translation id="685040365210406336">Jangan lakukan perubahan</translation>
 <translation id="6850409657436465440">Download sedang berlangsung</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> tab ditutup</translation>
 <translation id="6864459304226931083">Download gambar</translation>
@@ -815,7 +815,7 @@
 <translation id="7665369617277396874">Tambahkan akun</translation>
 <translation id="7682724950699840886">Coba tips berikut ini: pastikan ruang di perangkat Anda mencukupi, lalu coba ekspor lagi.</translation>
 <translation id="7698359219371678927">Buat email di <ph name="APP_NAME" /></translation>
-<translation id="7704317875155739195">Melengkapi otomatis penelusuran dan URL</translation>
+<translation id="7704317875155739195">Lengkapi otomatis penelusuran dan URL</translation>
 <translation id="773466115871691567">Selalu terjemahkan halaman dalam bahasa <ph name="SOURCE_LANGUAGE" /></translation>
 <translation id="7735672056998735387"><ph name="SPACE_FREE" /> (<ph name="SPACE_OTHER" />)</translation>
 <translation id="773905249182896430">Melindungi Anda dan perangkat dari situs berbahaya</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
index 5370a76..648b5ee 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
@@ -376,7 +376,7 @@
 <translation id="4170011742729630528">このサービスはご利用になれません。しばらくしてからもう一度お試しください。</translation>
 <translation id="4179980317383591987"><ph name="AMOUNT" /> 使用</translation>
 <translation id="4181841719683918333">言語</translation>
-<translation id="4192273449750167573">次の画面で設定を確認</translation>
+<translation id="4192273449750167573">次の画面で設定を確認する</translation>
 <translation id="4195643157523330669">新しいタブで開く</translation>
 <translation id="4198423547019359126">ダウンロードの保存先はありません</translation>
 <translation id="4209895695669353772">ユーザーに合わせた Google からのおすすめコンテンツを表示するには、同期を有効にします</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
index 399dd067..88b31ae 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -18,7 +18,7 @@
 <translation id="1141800923049248244">{FILE_COUNT,plural, =1{1 download pendente.}one{# download pendente.}other{# downloads pendentes.}}</translation>
 <translation id="1145536944570833626">Excluir dados já existentes.</translation>
 <translation id="1146678959555564648">Entrar na RV</translation>
-<translation id="114721135501989771">Use a tecnologia do Google no Chrome</translation>
+<translation id="114721135501989771">A tecnologia Google no Chrome</translation>
 <translation id="1157102636231978136">Seus dados e atividades de navegação, sincronizados com sua Conta do Google</translation>
 <translation id="116280672541001035">Dados usados</translation>
 <translation id="1172593791219290334">Página de inicialização</translation>
@@ -107,7 +107,7 @@
 <translation id="1832521218263067499">Incidentes de segurança</translation>
 <translation id="1853692000353488670">Nova guia anônima</translation>
 <translation id="1868024384445905608">Agora o Chrome faz o download de arquivos mais rapidamente</translation>
-<translation id="1878302395768190018">Você pode personalizar isso a qualquer momento nas configurações do Chrome</translation>
+<translation id="1878302395768190018">Você pode alterar isso a qualquer momento nas configurações do Chrome</translation>
 <translation id="1880072593381090678">Páginas conhecidas do Chrome</translation>
 <translation id="1883903952484604915">Meus arquivos</translation>
 <translation id="1887786770086287077">O acesso ao local está desativado para este dispositivo. Ative-o nas <ph name="BEGIN_LINK" />Configurações do Android<ph name="END_LINK" />.</translation>
@@ -376,7 +376,7 @@
 <translation id="4170011742729630528">O serviço não está disponível. Tente novamente mais tarde.</translation>
 <translation id="4179980317383591987"><ph name="AMOUNT" /> usado(s)</translation>
 <translation id="4181841719683918333">Idiomas</translation>
-<translation id="4192273449750167573">Revise suas configurações na próxima tela</translation>
+<translation id="4192273449750167573">Revisar as configurações na próxima tela</translation>
 <translation id="4195643157523330669">Abrir em uma nova guia</translation>
 <translation id="4198423547019359126">Não há locais de download disponíveis</translation>
 <translation id="4209895695669353772">Para receber conteúdo personalizado sugerido pelo Google, ative a sincronização</translation>
@@ -397,7 +397,7 @@
 <translation id="4404568932422911380">Nenhum favorito</translation>
 <translation id="4409723563706114196">Usar predições de páginas</translation>
 <translation id="4412992751769744546">Permitir cookies de terceiros</translation>
-<translation id="4419556793104466535">Controlar sincronização, personalização e muito mais</translation>
+<translation id="4419556793104466535">Controle a sincronização, personalização e muito mais</translation>
 <translation id="4432792777822557199">Páginas em <ph name="SOURCE_LANGUAGE" /> serão traduzidas para <ph name="TARGET_LANGUAGE" /> de agora em diante</translation>
 <translation id="4434045419905280838">Pop-ups e redirecionamentos</translation>
 <translation id="4445444302979002552">Usar os serviços de previsão para sugerir termos de pesquisa e websites</translation>
@@ -962,7 +962,7 @@
 <translation id="8979405271719829084">Faça o download de vídeos para assistir mais tarde</translation>
 <translation id="8981454092730389528">Controles de atividades do Google</translation>
 <translation id="8983677657449185470">Ajude a melhorar a Navegação segura</translation>
-<translation id="8986494364107987395">Enviar estatísticas de uso e relatórios de erros ao Google automaticamente</translation>
+<translation id="8986494364107987395">Envia estatísticas de uso e relatórios de erros ao Google automaticamente</translation>
 <translation id="8993760627012879038">Abrir uma nova guia no modo de navegação anônima</translation>
 <translation id="8998729206196772491">Você está fazendo login com uma conta gerenciada por <ph name="MANAGED_DOMAIN" /> e dando ao administrador dela o controle sobre seus dados do Chrome, os quais ficarão permanentemente vinculados a essa conta. Se você sair do Chrome, seus dados serão excluídos desse dispositivo, mas permanecerão armazenados na sua Conta do Google.</translation>
 <translation id="9019902583201351841">Gerenciado pelos seus pais</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
index d7244f41..7e17679 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
@@ -19,7 +19,7 @@
 <translation id="1145536944570833626">Удалить сохраненные данные.</translation>
 <translation id="1146678959555564648">Войти в режим VR</translation>
 <translation id="114721135501989771">Интеллектуальные функции Google в Chrome</translation>
-<translation id="1157102636231978136">Данные о работе в браузере и о ваших действиях, синхронизированные с аккаунтом Google</translation>
+<translation id="1157102636231978136">Данные о работе в браузере и ваших действиях, связанных с аккаунтом Google</translation>
 <translation id="116280672541001035">Использовано</translation>
 <translation id="1172593791219290334">Стартовая страница</translation>
 <translation id="1178581264944972037">Пауза</translation>
@@ -29,6 +29,7 @@
 <translation id="1201402288615127009">Далее</translation>
 <translation id="1204037785786432551">Сохранить данные по ссылке</translation>
 <translation id="1206892813135768548">Копировать текст ссылки</translation>
+<translation id="1208340532756947324">Чтобы синхронизировать и персонализировать данные на всех устройствах, включите синхронизацию.</translation>
 <translation id="1209206284964581585">Скрыть</translation>
 <translation id="123724288017357924">Обновить страницу без учета кешированного контента</translation>
 <translation id="124116460088058876">Другие языки</translation>
@@ -52,7 +53,7 @@
 <translation id="1389974829397082527">Закладок пока нет</translation>
 <translation id="1395084944394113895">Показать офлайн-контент</translation>
 <translation id="1397811292916898096">Поиск в <ph name="PRODUCT_NAME" /></translation>
-<translation id="1397854323885047133">Синхронизировать и настроить</translation>
+<translation id="1397854323885047133">Настройки синхронизации и персонализации</translation>
 <translation id="1404122904123200417">Встроено в <ph name="WEBSITE_URL" /></translation>
 <translation id="1406000523432664303">Запрет отслеживания</translation>
 <translation id="1407135791313364759">Открыть все</translation>
@@ -129,6 +130,7 @@
 <translation id="1989112275319619282">Выбрать</translation>
 <translation id="1993768208584545658">Сайт <ph name="SITE" /> запрашивает подключение</translation>
 <translation id="1994173015038366702">Адрес сайта</translation>
+<translation id="2002537628803770967">Кредитные карты и адреса из Google Pay</translation>
 <translation id="200815880754187296">Другие приложения: <ph name="KILOBYTES" /> КБ</translation>
 <translation id="2017836877785168846">Удаление истории и вариантов автозаполнения в адресной строке</translation>
 <translation id="2021896219286479412">Настройки полноэкранного режима</translation>
@@ -184,7 +186,7 @@
 <translation id="2426805022920575512">Сменить аккаунт</translation>
 <translation id="2433507940547922241">Внешний вид</translation>
 <translation id="2434158240863470628">Скачивание завершено <ph name="SEPARATOR" /> <ph name="BYTES_DOWNLOADED" /></translation>
-<translation id="2436117022029368436">Обмен информацией с Google для улучшения работы Chrome</translation>
+<translation id="2436117022029368436">Отправка данных в Google для улучшения работы Chrome</translation>
 <translation id="2440823041667407902">Данные о местоположении</translation>
 <translation id="2450083983707403292">Начать скачивание <ph name="FILE_NAME" /> ещё раз?</translation>
 <translation id="2476578072172137802">Настройки сайта</translation>
@@ -225,6 +227,7 @@
 <translation id="2777555524387840389">Осталось <ph name="SECONDS" /> сек.</translation>
 <translation id="2781151931089541271">Осталась 1 сек.</translation>
 <translation id="2810645512293415242">Страница была открыта в упрощенном виде, чтобы уменьшить объем трафика и время загрузки.</translation>
+<translation id="2818669890320396765">Чтобы получить доступ к закладкам на всех устройствах, войдите в аккаунт и включите синхронизацию.</translation>
 <translation id="2836148919159985482">Чтобы выйти из полноэкранного режима, нажмите кнопку "Назад".</translation>
 <translation id="2842985007712546952">Родительская папка</translation>
 <translation id="2870560284913253234">Сайт</translation>
@@ -303,6 +306,7 @@
 <translation id="3549657413697417275">Поиск в истории</translation>
 <translation id="3552151358455404883">Управление персонализацией и синхронизацией Chrome доступно в <ph name="BEGIN_LINK1" />настройках<ph name="END_LINK1" /></translation>
 <translation id="3557336313807607643">Добавить в контакты</translation>
+<translation id="3568688522516854065">Чтобы получить доступ к вкладкам на всех устройствах, войдите в аккаунт и включите синхронизацию.</translation>
 <translation id="3587482841069643663">Все</translation>
 <translation id="3590487821116122040">Маловажные данные сайтов (например, сайты, которые вы редко посещаете или на которых не сохранили настройки)</translation>
 <translation id="3599863153486145794">Удаление истории со всех устройств, на которых выполнен вход в аккаунт. Информация о других ваших действиях в Интернете может также храниться на странице <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -375,6 +379,7 @@
 <translation id="4192273449750167573">Проверить настройки на следующем экране</translation>
 <translation id="4195643157523330669">Открыть в новой вкладке</translation>
 <translation id="4198423547019359126">Нет доступных мест для скачивания</translation>
+<translation id="4209895695669353772">Чтобы мы могли рекомендовать вам интересный контент, включите синхронизацию.</translation>
 <translation id="4226663524361240545">Вибрация при получении уведомлений</translation>
 <translation id="4242533952199664413">Открыть настройки</translation>
 <translation id="424864128008805179">Выйти из Chrome?</translation>
@@ -400,6 +405,7 @@
 <translation id="4452548195519783679">Закладка добавлена в папку "<ph name="FOLDER_NAME" />"</translation>
 <translation id="4453340223357552416"><ph name="PRODUCT_NAME" />: скачан файл <ph name="FILE_NAME" /></translation>
 <translation id="4468959413250150279">Отключить звуки на определенном сайте.</translation>
+<translation id="4472118726404937099">Чтобы синхронизировать и персонализировать данные на всех устройствах, войдите в аккаунт и включите синхронизацию.</translation>
 <translation id="4479647676395637221">Запрашивать разрешение на доступ к камере (рекомендуется)</translation>
 <translation id="4487967297491345095">Все данные приложения Chrome, включая файлы, настройки, аккаунты и базы данных, будут безвозвратно удалены.</translation>
 <translation id="4508440807153586353">Ваши зашифрованные данные может прочитать только тот, кто знает кодовую фразу. Она не пересылается и не хранится в Google. Если вы забудете фразу или решите изменить эту настройку, вам придется сбросить параметры синхронизации. <ph name="BEGIN_LINK" />Подробнее…<ph name="END_LINK" /></translation>
@@ -566,7 +572,7 @@
 В режиме инкогнито ваши действия видны системному администратору и интернет-провайдеру, а также доступны веб-сайтам, которые вы посещаете.</translation>
 <translation id="572328651809341494">Недавние вкладки</translation>
 <translation id="5726692708398506830">Увеличить масштаб страницы</translation>
-<translation id="5731185123186077399">Персонализированные сервисы Google, например Google Pay</translation>
+<translation id="5731185123186077399">Пользуйтесь персонализированными сервисами Google, например Google Pay.</translation>
 <translation id="5738816946784116349">Скачанные файлы в Chrome</translation>
 <translation id="5748802427693696783">Переключено на обычные вкладки</translation>
 <translation id="5749068826913805084">Для скачивания файлов браузеру Chrome требуется доступ к хранилищу.</translation>
@@ -584,6 +590,7 @@
 <translation id="5854790677617711513">Сохраненные более 30 дней назад</translation>
 <translation id="5858741533101922242">Не удалось включить адаптер Bluetooth</translation>
 <translation id="5860033963881614850">Выкл.</translation>
+<translation id="5862731021271217234">Чтобы получить доступ к вкладкам на всех устройствах, включите синхронизацию.</translation>
 <translation id="5864174910718532887">Сортировка по названию сайта</translation>
 <translation id="5864419784173784555">Завершение предыдущего скачивания…</translation>
 <translation id="5869522115854928033">Сайты с сохраненными паролями</translation>
@@ -836,7 +843,7 @@
 <translation id="7942131818088350342">Версия <ph name="PRODUCT_NAME" /> устарела.</translation>
 <translation id="7947953824732555851">Принять и войти</translation>
 <translation id="7963646190083259054">Поставщик:</translation>
-<translation id="7981313251711023384">Разрешить предварительную настройку страниц для повышения скорости работы и поиска</translation>
+<translation id="7981313251711023384">Разрешить предзагрузку страниц для повышения скорости работы браузера и поиска</translation>
 <translation id="79859296434321399">Чтобы просматривать контент в режиме дополненной реальности, установите приложение ARCore.</translation>
 <translation id="7987073022710626672">Условия использования Chrome</translation>
 <translation id="7998918019931843664">Восстановить закрытую вкладку</translation>
@@ -862,6 +869,7 @@
 <translation id="8100932616285851614">Панель навигации закрыта</translation>
 <translation id="8103578431304235997">Вкладка инкогнито</translation>
 <translation id="8105951947646329362">Предлагать похожие страницы</translation>
+<translation id="8109613176066109935">Чтобы получить доступ к закладкам на всех устройствах, включите синхронизацию.</translation>
 <translation id="8116925261070264013">Сайты с отключенным звуком</translation>
 <translation id="813082847718468539">Сведения о сайте</translation>
 <translation id="8168435359814927499">Контент</translation>
@@ -888,7 +896,7 @@
 <translation id="8413126021676339697">Показать всю историю</translation>
 <translation id="8420510748452002155">Неперсонализированные сервисы</translation>
 <translation id="8428213095426709021">Настройки</translation>
-<translation id="8438566539970814960">Улучшить поиск и просмотр страниц</translation>
+<translation id="8438566539970814960">Помогать улучшить просмотр страниц и поиск</translation>
 <translation id="8441146129660941386">Перемотать назад</translation>
 <translation id="8445448999790540984">Не удалось экспортировать пароли</translation>
 <translation id="8447861592752582886">Отключить доступ к устройству</translation>
@@ -954,7 +962,7 @@
 <translation id="8972098258593396643">Скачать в папку по умолчанию?</translation>
 <translation id="8979405271719829084">Скачивайте видео для просмотра</translation>
 <translation id="8981454092730389528">Отслеживание действий в Google</translation>
-<translation id="8983677657449185470">Помогите улучшить режим Безопасного просмотра</translation>
+<translation id="8983677657449185470">Помогать улучшить режим Безопасного просмотра</translation>
 <translation id="8986494364107987395">Автоматически отправлять в Google статистику использования и отчеты о сбоях</translation>
 <translation id="8993760627012879038">Открыть новое окно в режиме инкогнито</translation>
 <translation id="8998729206196772491">Вы входите в аккаунт, которым управляет администратор домена <ph name="MANAGED_DOMAIN" />. Он может контролировать ваши данные Chrome, которые теперь будут связаны с управляемым аккаунтом. При выходе из системы все данные Chrome, хранящиеся на этом устройстве, будут удалены, но останутся в вашем аккаунте Google.</translation>
@@ -966,6 +974,7 @@
 <translation id="9065203028668620118">Изменить</translation>
 <translation id="9070377983101773829">Голосовой поиск</translation>
 <translation id="9071742570345586758">Чтобы просматривать контент в режиме виртуальной реальности, установите Google VR-сервисы</translation>
+<translation id="9074336505530349563">Чтобы мы могли рекомендовать вам интересный контент, войдите в аккаунт и включите синхронизацию.</translation>
 <translation id="9086455579313502267">Нет доступа к сети</translation>
 <translation id="9099018167121903954">Скачанные файлы: <ph name="KILOBYTES" /> КБ</translation>
 <translation id="9100505651305367705">Предлагать упрощенный просмотр статей, если он поддерживается</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
index d9f0172..814c7d0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -169,7 +169,7 @@
 <translation id="2321086116217818302">正在准备密码…</translation>
 <translation id="2321958826496381788">拖动该滑块,将文字调整到适合您阅读的大小。点按两次某段落后,显示的文字至少应是这么大。</translation>
 <translation id="2323763861024343754">网站存储数据</translation>
-<translation id="2325181368089033281">您或您的父母随时可以自定义<ph name="BEGIN_LINK1" />设置<ph name="END_LINK1" />。Google 可能会根据您所访问网站中的内容、浏览器互动行为和活动对 Chrome 以及 Google 服务(例如翻译、搜索和广告)进行个性化设置。</translation>
+<translation id="2325181368089033281">您或您的父母随时可以自定义<ph name="BEGIN_LINK1" />设置<ph name="END_LINK1" />。Google 可能会根据您访问的网站上的内容、您在浏览器中的互动行为和活动,为您提供个性化的 Chrome 体验和其他 Google 服务体验(例如翻译、搜索和广告)。</translation>
 <translation id="2328985652426384049">无法登录</translation>
 <translation id="2342981853652716282">登录 Chrome 即可将您的书签、密码等同步到您的所有设备上。</translation>
 <translation id="2343328333327081434">正在安装…</translation>
@@ -241,7 +241,7 @@
 <translation id="290376772003165898">网页的源语言不是<ph name="LANGUAGE" />?</translation>
 <translation id="2913331724188855103">允许网站保存和读取 Cookie 数据(推荐)</translation>
 <translation id="2932150158123903946">Google <ph name="APP_NAME" /> 存储数据</translation>
-<translation id="2943166482989655199">通过将系统信息和使用情况数据发送给 Google,协助改进 Chrome 并提高其安全性</translation>
+<translation id="2943166482989655199">将系统信息和使用情况数据发送给 Google,帮助改进 Chrome 并提高其安全性</translation>
 <translation id="2956410042958133412">该帐号由 <ph name="PARENT_NAME_1" /> 和 <ph name="PARENT_NAME_2" /> 管理。</translation>
 <translation id="2960796085439532066">版权所有 <ph name="YEAR" /> Google Inc. 保留所有权利。</translation>
 <translation id="2962095958535813455">已切换到隐身标签页</translation>
@@ -283,7 +283,7 @@
 <translation id="3328801116991980348">网站信息</translation>
 <translation id="3341058695485821946">查看您已节省多少数据流量</translation>
 <translation id="3350687908700087792">关闭所有隐身标签页</translation>
-<translation id="3361477720586884778">您随时可以自定义<ph name="BEGIN_LINK1" />设置<ph name="END_LINK1" />。Google 可能会根据您所访问网站中的内容、浏览器互动行为和活动对 Chrome 以及 Google 服务(例如翻译、搜索和广告)进行个性化设置。</translation>
+<translation id="3361477720586884778">您随时可以自定义<ph name="BEGIN_LINK1" />设置<ph name="END_LINK1" />。Google 可能会根据您访问的网站上的内容、您在浏览器中的互动行为和活动,为您提供个性化的 Chrome 体验和其他 Google 服务体验(例如翻译、搜索和广告)。</translation>
 <translation id="3365671512111106261">在流量节省程序处于开启状态时不可用</translation>
 <translation id="3367813778245106622">重新登录以开始同步</translation>
 <translation id="3384347053049321195">分享图片</translation>
@@ -732,7 +732,7 @@
 <translation id="699220179437400583">自动向 Google 报告可能出现的安全事件详情</translation>
 <translation id="6992289844737586249">在允许网站使用您的麦克风前先询问(推荐)</translation>
 <translation id="7016516562562142042">已设为可供当前的搜索引擎使用</translation>
-<translation id="7017968314960951695">根据您所访问的网站上的内容以及您的浏览器活动和互动行为,提供个性化的使用体验</translation>
+<translation id="7017968314960951695">根据您访问的网站上的内容以及您在浏览器中的活动和互动行为,提供个性化的使用体验</translation>
 <translation id="7021515813996758557"><ph name="FILE_NAME" /> 已下载完毕</translation>
 <translation id="7022756207310403729">在浏览器中打开</translation>
 <translation id="7029809446516969842">密码</translation>
@@ -775,7 +775,7 @@
 <translation id="7396940094317457632"><ph name="FILE_NAME" />。</translation>
 <translation id="7400418766976504921">网址</translation>
 <translation id="7403691278183511381">Chrome 首次运行体验</translation>
-<translation id="741204030948306876">确认</translation>
+<translation id="741204030948306876">立即启用</translation>
 <translation id="7413229368719586778">开始日期:<ph name="DATE" /></translation>
 <translation id="7423098979219808738">先询问</translation>
 <translation id="7423538860840206698">已阻止读取剪贴板中的内容</translation>
@@ -829,7 +829,7 @@
 <translation id="7791543448312431591">添加</translation>
 <translation id="780301667611848630">不用了,谢谢</translation>
 <translation id="7810647596859435254">打开方式…</translation>
-<translation id="7832327313660264358">您同步到 Google 中的数据和您使用的功能将保持不变</translation>
+<translation id="7832327313660264358">您同步到 Google 的数据和您使用的功能不会改变</translation>
 <translation id="7837721118676387834">允许特定网站自动播放静音的视频。</translation>
 <translation id="7846076177841592234">取消选择</translation>
 <translation id="784934925303690534">时间范围</translation>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
index 8e24809..62021ed 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
@@ -45,6 +45,10 @@
         sendClickButtonToggleEvent();
     }
 
+    /**
+     * Either presses or releases the Daydream controller's touchpad button depending on wheter
+     * the button is currently pressed or not.
+     */
     public void sendClickButtonToggleEvent() {
         mApi.buttonEvent.sendClickButtonToggleEvent();
     }
@@ -95,10 +99,10 @@
      * scrolling up at the same speed won't necessarily scroll back to the exact
      * starting position on the page.
      *
-     * @param direction the ScrollDirection to scroll with
-     * @param steps the number of intermediate steps to send while scrolling
+     * @param direction the ScrollDirection to scroll with.
+     * @param steps the number of intermediate steps to send while scrolling.
      * @param speed how long to wait between steps in the scroll, with higher
-     * numbers resulting in a faster scroll
+     *        numbers resulting in a faster scroll.
      */
     public void scroll(ScrollDirection direction, int steps, int speed) {
         float startX, startY, endX, endY;
@@ -142,14 +146,14 @@
     /**
      * Simulates a touch down-drag-touch up sequence on the touchpad between two points.
      *
-     * @param xStart the x coordinate to start the touch sequence at, in range [0.0f, 1.0f]
-     * @param yStart the y coordinate to start the touch sequence at, in range [0.0f, 1.0f]
-     * @param xEnd the x coordinate to end the touch sequence at, in range [0.0f, 1.0f]
-     * @param yEnd the y coordinate to end the touch sequence at, in range [0.0f, 1.0f]
-     * @param steps the number of steps the drag will have
+     * @param xStart the x coordinate to start the touch sequence at, in range [0.0f, 1.0f].
+     * @param yStart the y coordinate to start the touch sequence at, in range [0.0f, 1.0f].
+     * @param xEnd the x coordinate to end the touch sequence at, in range [0.0f, 1.0f].
+     * @param yEnd the y coordinate to end the touch sequence at, in range [0.0f, 1.0f].
+     * @param steps the number of steps the drag will have.
      * @param speed how long to wait between steps in the sequence. Generally, higher numbers
-     * result in faster movement, e.g. when used for scrolling, a higher number results in faster
-     * scrolling.
+     *        result in faster movement, e.g. when used for scrolling, a higher number results in
+     *        faster scrolling.
      */
     public void performLinearTouchpadMovement(
             float xStart, float yStart, float xEnd, float yEnd, int steps, int speed) {
@@ -166,10 +170,10 @@
     /**
      * Instantly moves the controller to the specified quaternion coordinates.
      *
-     * @param x the x component of the quaternion
-     * @param y the y component of the quaternion
-     * @param z the z component of the quaternion
-     * @param w the w component of the quaternion
+     * @param x the x component of the quaternion.
+     * @param y the y component of the quaternion.
+     * @param z the z component of the quaternion.
+     * @param w the w component of the quaternion.
      */
     public void moveControllerInstant(float x, float y, float z, float w) {
         mApi.moveEvent.sendMoveEvent(x, y, z, w, 0);
@@ -178,10 +182,10 @@
     /**
      * Moves the controller from one position to another over a period of time.
      *
-     * @param startAngles the x/y/z angles to start the controller at, in radians
-     * @param endAngles the x/y/z angles to end the controller at, in radians
-     * @param steps the number of steps the controller will take moving between the positions
-     * @param delayBetweenSteps how long to sleep between positions
+     * @param startAngles the x/y/z angles to start the controller at, in radians.
+     * @param endAngles the x/y/z angles to end the controller at, in radians.
+     * @param steps the number of steps the controller will take moving between the positions.
+     * @param delayBetweenSteps how long to sleep between positions.
      */
     public void moveControllerInterpolated(
             float[] startAngles, float[] endAngles, int steps, int delayBetweenSteps) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
index 5bffd9e..261c8c1b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
@@ -12,8 +12,8 @@
 /**
  * Class for accessing VrShellDelegate internals for testing purposes.
  * This does two things:
- * - Prevents us from needing @VisibleForTesting annotations everywhere in production code
- * - Allows us to have test-specific behavior if necessary without changing production code
+ * - Prevents us from needing @VisibleForTesting annotations everywhere in production code.
+ * - Allows us to have test-specific behavior if necessary without changing production code.
  */
 public class TestVrShellDelegate extends VrShellDelegate {
     private Runnable mOnVSyncPausedCallback;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserCompositorViewHolderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserCompositorViewHolderTest.java
index 38a4191..e565ced 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserCompositorViewHolderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserCompositorViewHolderTest.java
@@ -14,7 +14,6 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
@@ -24,7 +23,7 @@
 import org.chromium.content_public.browser.WebContents;
 
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * End-to-end tests for the CompositorViewHolder's behavior while in VR.
@@ -45,11 +44,10 @@
      */
     @Test
     @MediumTest
-    @RetryOnFailure
     public void testResizeWithCompositorViewHolderDetached()
             throws InterruptedException, TimeoutException {
-        final AtomicReference<Integer> oldWidth = new AtomicReference<>();
-        final AtomicReference<Integer> oldHeight = new AtomicReference<>();
+        final AtomicInteger oldWidth = new AtomicInteger();
+        final AtomicInteger oldHeight = new AtomicInteger();
         final int testWidth = 123;
         final int testHeight = 456;
         final WebContents webContents = mVrTestRule.getWebContents();
@@ -78,10 +76,10 @@
         ThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertEquals(
                     "Viewport width changed when resizing a detached CompositorViewHolder",
-                    webContents.getWidth(), oldWidth.get().intValue());
+                    webContents.getWidth(), oldWidth.get());
             Assert.assertEquals(
                     "Viewport height changed when resizing a detached CompositorViewHolder",
-                    webContents.getHeight(), oldHeight.get().intValue());
+                    webContents.getHeight(), oldHeight.get());
 
             CompositorViewHolder compositorViewHolder =
                     (CompositorViewHolder) mVrTestRule.getActivity().findViewById(
@@ -89,10 +87,10 @@
             compositorViewHolder.onExitVr();
             Assert.assertNotEquals(
                     "Viewport width did not change after CompositorViewHolder re-attached",
-                    webContents.getHeight(), oldHeight.get().intValue());
+                    webContents.getHeight(), oldHeight.get());
             Assert.assertNotEquals(
                     "Viewport height did not change after CompositorViewHolder re-attached",
-                    webContents.getWidth(), oldWidth.get().intValue());
+                    webContents.getWidth(), oldWidth.get());
         });
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
index cb8cb808..a3626cb3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
@@ -23,7 +23,6 @@
 
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.history.HistoryPage;
 import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
@@ -249,7 +248,6 @@
      */
     @Test
     @MediumTest
-    @RetryOnFailure(message = "Very rarely, button press not registered (race condition?)")
     public void testAppButtonExitsFullscreen() throws InterruptedException, TimeoutException {
         mVrBrowserTestFramework.loadUrlAndAwaitInitialization(
                 VrBrowserTestFramework.getFileUrlForHtmlTestFile("test_navigation_2d_page"),
@@ -274,5 +272,6 @@
                 },
                 "Page did not exit fullscreen after app button was pressed", POLL_TIMEOUT_LONG_MS,
                 POLL_CHECK_INTERVAL_LONG_MS);
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java
index 6e568604..764aa0e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java
@@ -49,8 +49,6 @@
     // A long enough sleep after triggering/interacting with a dialog to ensure that the interaction
     // has propagated through the render pipeline, i.e. the result of the interaction will actually
     // be visible on the screen.
-    // TODO(https://crbug.com/826841): Remove this in favor of notifications from the native code.
-    private static final int VR_DIALOG_RENDER_SLEEP_MS = 500;
     private static final String TEST_IMAGE_DIR = "chrome/test/data/vr/UiCapture";
     private static final File sBaseDirectory =
             new File(UrlUtils.getIsolatedTestFilePath(TEST_IMAGE_DIR));
@@ -94,7 +92,7 @@
         Assert.assertTrue("Failed to take screenshot", uiDevice.takeScreenshot(screenshotFile));
     }
 
-    private void displayPermissionPrompt(String initialPage, String navigationCommand)
+    private void navigateAndDisplayPermissionPrompt(String page, String promptCommand)
             throws InterruptedException, TimeoutException {
         // Trying to grant permissions on file:// URLs ends up hitting DCHECKS, so load from a local
         // server instead.
@@ -102,13 +100,12 @@
             mServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
         }
         mVrBrowserTestFramework.loadUrlAndAwaitInitialization(
-                mServer.getURL(
-                        VrBrowserTestFramework.getEmbeddedServerPathForHtmlTestFile(initialPage)),
+                mServer.getURL(VrBrowserTestFramework.getEmbeddedServerPathForHtmlTestFile(page)),
                 PAGE_LOAD_TIMEOUT_S);
 
         // Display the given permission prompt.
         VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
-        mVrBrowserTestFramework.runJavaScriptOrFail(navigationCommand, POLL_TIMEOUT_SHORT_MS);
+        mVrBrowserTestFramework.runJavaScriptOrFail(promptCommand, POLL_TIMEOUT_SHORT_MS);
         VrBrowserTransitionUtils.waitForNativeUiPrompt(POLL_TIMEOUT_LONG_MS);
 
         // There is currently no way to know whether a dialog has been drawn yet,
@@ -116,17 +113,17 @@
         Thread.sleep(VR_ENTRY_SLEEP_MS);
     }
 
-    private void displayJavascriptDialog(String initialPage, String navigationCommand)
+    private void navigateAndDisplayJavaScriptDialog(String page, String dialogCommand)
             throws InterruptedException, TimeoutException {
         mVrBrowserTestFramework.loadUrlAndAwaitInitialization(
-                VrBrowserTestFramework.getFileUrlForHtmlTestFile(initialPage), PAGE_LOAD_TIMEOUT_S);
+                VrBrowserTestFramework.getFileUrlForHtmlTestFile(page), PAGE_LOAD_TIMEOUT_S);
 
         // Display the JavaScript dialog.
         VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
         // We can't use runJavaScriptOrFail here because JavaScript execution is blocked while a
         // JS dialog is visible, so runJavaScriptOrFail will always time out.
         JavaScriptUtils.executeJavaScript(
-                mVrBrowserTestFramework.getFirstTabWebContents(), navigationCommand);
+                mVrBrowserTestFramework.getFirstTabWebContents(), dialogCommand);
         VrBrowserTransitionUtils.waitForNativeUiPrompt(POLL_TIMEOUT_LONG_MS);
 
         // There is currently no way to know whether a dialog has been drawn yet,
@@ -156,13 +153,14 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testMicrophonePermissionPrompt() throws InterruptedException, TimeoutException {
         // Display audio permissions prompt.
-        displayPermissionPrompt(
+        navigateAndDisplayPermissionPrompt(
                 "test_navigation_2d_page", "navigator.getUserMedia({audio: true}, ()=>{}, ()=>{})");
 
         // Capture image
         captureScreen("MicrophonePermissionPrompt_Visible");
         NativeUiUtils.clickFallbackUiPositiveButton();
         captureScreen("MicrophonePermissionPrompt_Granted");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -173,11 +171,12 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testCameraPermissionPrompt() throws InterruptedException, TimeoutException {
         // Display Camera permissions prompt.
-        displayPermissionPrompt(
+        navigateAndDisplayPermissionPrompt(
                 "test_navigation_2d_page", "navigator.getUserMedia({video: true}, ()=>{}, ()=>{})");
 
         // Capture image
         captureScreen("CameraPermissionPrompt_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -188,11 +187,12 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testLocationPermissionPrompt() throws InterruptedException, TimeoutException {
         // Display Location permissions prompt.
-        displayPermissionPrompt("test_navigation_2d_page",
+        navigateAndDisplayPermissionPrompt("test_navigation_2d_page",
                 "navigator.geolocation.getCurrentPosition(()=>{}, ()=>{})");
 
         // Capture image
         captureScreen("LocationPermissionPrompt_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -203,11 +203,12 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testNotificationPermissionPrompt() throws InterruptedException, TimeoutException {
         // Display Notification permissions prompt.
-        displayPermissionPrompt(
+        navigateAndDisplayPermissionPrompt(
                 "test_navigation_2d_page", "Notification.requestPermission(()=>{})");
 
         // Capture image
         captureScreen("NotificationPermissionPrompt_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -218,11 +219,12 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testMidiPermisionPrompt() throws InterruptedException, TimeoutException {
         // Display MIDI permissions prompt.
-        displayPermissionPrompt(
+        navigateAndDisplayPermissionPrompt(
                 "test_navigation_2d_page", "navigator.requestMIDIAccess({sysex: true})");
 
         // Capture image
         captureScreen("MidiPermissionPrompt_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -233,11 +235,13 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testJavaScriptAlert() throws InterruptedException, TimeoutException {
         // Display a JavaScript alert()
-        displayJavascriptDialog(
+        navigateAndDisplayJavaScriptDialog(
                 "test_navigation_2d_page", "alert('538 perf regressions detected')");
 
         // Capture image
         captureScreen("JavaScriptAlert_Visible");
+        // No assertNoJavaScriptErrors since the alert is still visible, preventing further
+        // JavaScript execution.
     }
 
     /**
@@ -248,7 +252,7 @@
     @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
     public void testJavaScriptConfirm() throws InterruptedException, TimeoutException {
         // Display a JavaScript confirm()
-        displayJavascriptDialog(
+        navigateAndDisplayJavaScriptDialog(
                 "test_navigation_2d_page", "var c = confirm('This is a confirmation dialog')");
 
         // Capture image
@@ -261,6 +265,7 @@
                 mVrBrowserTestFramework.runJavaScriptOrFail("c", POLL_TIMEOUT_SHORT_MS)
                         .equals("false"));
         captureScreen("JavaScriptConfirm_Dismissed");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -273,7 +278,7 @@
     public void testJavaScriptPrompt() throws InterruptedException, TimeoutException {
         // Display a JavaScript prompt()
         String expectedString = "Probably most likely yes";
-        displayJavascriptDialog("test_navigation_2d_page",
+        navigateAndDisplayJavaScriptDialog("test_navigation_2d_page",
                 "var p = prompt('Are the Chrome controls broken?', '" + expectedString + "')");
 
         // Capture image
@@ -288,6 +293,7 @@
                         .runJavaScriptOrFail("p == '" + expectedString + "'", POLL_TIMEOUT_SHORT_MS)
                         .equals("true"));
         captureScreen("JavaScriptPrompt_Dismissed");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     @Test
@@ -296,6 +302,7 @@
     public void testKeyboardAppearsOnUrlBarClick() throws InterruptedException, TimeoutException {
         clickElement("test_navigation_2d_page", UserFriendlyElementName.URL);
         captureScreen("KeyboardAppearsOnUrlBarClick_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     @Test
@@ -304,6 +311,7 @@
     public void testOverflowMenuAppears() throws InterruptedException, TimeoutException {
         clickElement("test_navigation_2d_page", UserFriendlyElementName.OVERFLOW_MENU);
         captureScreen("OverflowMenuAppears_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     @Test
@@ -313,5 +321,6 @@
             throws InterruptedException, TimeoutException {
         clickElement("test_navigation_2d_page", UserFriendlyElementName.PAGE_INFO_BUTTON);
         captureScreen("PageInfoAppearsOnSecurityTokenClick_Visible");
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
index 6da1d81..1ee76a0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
@@ -28,7 +28,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
@@ -107,7 +106,6 @@
      */
     @Test
     @Restriction({RESTRICTION_TYPE_VIEWER_DAYDREAM})
-    @RetryOnFailure(message = "crbug.com/736527")
     @LargeTest
     public void test2dtoVrShellNfcSupported() {
         enterVrShellNfc(true /* supported */);
@@ -226,6 +224,7 @@
                 },
                 "Exiting VR did not exit fullscreen", POLL_TIMEOUT_SHORT_MS,
                 POLL_CHECK_INTERVAL_SHORT_MS);
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -240,7 +239,7 @@
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         exitPresentationToVrShellImpl(
                 WebVrTestFramework.getFileUrlForHtmlTestFile("test_navigation_webvr_page"),
-                mWebVrTestFramework, "vrDisplay.exitPresent();");
+                mWebVrTestFramework);
     }
 
     /**
@@ -255,11 +254,11 @@
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         exitPresentationToVrShellImpl(
                 WebXrVrTestFramework.getFileUrlForHtmlTestFile("test_navigation_webxr_page"),
-                mWebXrVrTestFramework, "immersiveSession.end();");
+                mWebXrVrTestFramework);
     }
 
-    private void exitPresentationToVrShellImpl(String url, WebXrVrTestFramework framework,
-            String exitPresentString) throws InterruptedException {
+    private void exitPresentationToVrShellImpl(String url, WebXrVrTestFramework framework)
+            throws InterruptedException {
         VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
         framework.loadUrlAndAwaitInitialization(url, PAGE_LOAD_TIMEOUT_S);
         VrShellImpl vrShellImpl = (VrShellImpl) TestVrShellDelegate.getVrShellForTesting();
@@ -274,9 +273,10 @@
         framework.pollJavaScriptBooleanOrFail(javascript, POLL_TIMEOUT_LONG_MS);
 
         // Exit presentation through JavaScript.
-        framework.runJavaScriptOrFail(exitPresentString, POLL_TIMEOUT_SHORT_MS);
+        framework.endSession();
 
         framework.pollJavaScriptBooleanOrFail(javascript, POLL_TIMEOUT_LONG_MS);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -464,5 +464,6 @@
                 "navigator.getUserMedia({video: true}, ()=>{}, ()=>{})", POLL_TIMEOUT_SHORT_MS);
         VrBrowserTransitionUtils.waitForNativeUiPrompt(POLL_TIMEOUT_LONG_MS);
         VrBrowserTransitionUtils.forceExitVr();
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrFeedbackInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrFeedbackInfoBarTest.java
index 562be4c..b60584e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrFeedbackInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrFeedbackInfoBarTest.java
@@ -20,7 +20,6 @@
 
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils;
@@ -37,8 +36,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
-@RetryOnFailure(message = "These tests have a habit of hitting a race condition, preventing "
-                + "VR entry. See crbug.com/762724")
 public class VrFeedbackInfoBarTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
     // only ever runs in ChromeTabbedActivity.
@@ -102,6 +99,7 @@
         enterThenExitVr();
         assertState(false /* isInVr */, true /* isInfobarVisible  */);
         VrInfoBarUtils.clickInfobarCloseButton(mTestRule);
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -128,6 +126,7 @@
         // The infobar should not show because the user opted out.
         enterThenExitVr();
         assertState(false /* isInVr */, false /* isInfobarVisible  */);
+        mVrBrowserTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -164,6 +163,7 @@
         // Exiting VR should not prompt for feedback since the no VR browsing was performed.
         VrBrowserTransitionUtils.forceExitVr();
         assertState(false /* isInVr */, false /* isInfobarVisible  */);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -210,5 +210,6 @@
         // Exiting VR should prompt for feedback since 2D browsing was performed after.
         VrBrowserTransitionUtils.forceExitVr();
         assertState(false /* isInVr */, true /* isInfobarVisible  */);
+        framework.assertNoJavaScriptErrors();
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
index 3b53ea4..1acac0c9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
@@ -60,7 +60,7 @@
      * Helper function to run the tests checking for the upgrade/install InfoBar being present since
      * all that differs is the value returned by VrCoreVersionChecker and a couple asserts.
      *
-     * @param checkerReturnCompatibility The compatibility to have the VrCoreVersionChecker return
+     * @param checkerReturnCompatibility The compatibility to have the VrCoreVersionChecker return.
      */
     private void infoBarTestHelper(final int checkerReturnCompatibility) {
         VrShellDelegateUtils.setVrCoreCompatibility(checkerReturnCompatibility);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
index 3e1df68..3a4404e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
@@ -21,6 +21,7 @@
      * Checks whether a VRDisplay was actually found. Keeps the "xrDeviceFound" naming instead of
      * "vrDisplayFound" since WebVR is being deprecated and maintaining consistency with WebXR
      * naming is more important in the long run.
+     *
      * @param webContents The WebContents to run the JavaScript through.
      * @return Whether a VRDisplay was found.
      */
@@ -31,6 +32,7 @@
 
     /**
      * WebVR-specific implementation of enterSessionWithUserGestureOrFail.
+     *
      * @param webContents The WebContents of the tab to enter WebVR presentation in.
      */
     @Override
@@ -43,6 +45,7 @@
 
     /**
      * Exits WebVR presentation.
+     *
      * @param webContents The WebContents of the tab to exit WebVR presentation in.
      */
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArSessionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArSessionTest.java
index 9d29b96..6de9743 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArSessionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArSessionTest.java
@@ -138,5 +138,6 @@
         mWebXrArTestFramework.enterSessionWithUserGesture();
         mWebXrArTestFramework.pollJavaScriptBooleanOrFail(
                 "sessionInfos[sessionTypes.AR].currentSession != null", POLL_TIMEOUT_LONG_MS);
+        mWebXrArTestFramework.assertNoJavaScriptErrors();
     }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArTestFramework.java
index fc24a2d5..09c646ea 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArTestFramework.java
@@ -18,7 +18,8 @@
 public class WebXrArTestFramework extends WebXrTestFramework {
     /**
      * Checks whether an AR session request would prompt the user for Camera permissions.
-     * @param webContents The WebContents to check for the permission in
+     *
+     * @param webContents The WebContents to check for the permission in.
      * @return True if an AR session request will cause a permission prompt, false otherwise.
      */
     public static boolean arSessionRequestWouldTriggerPermissionPrompt(WebContents webContents) {
@@ -32,7 +33,7 @@
 
     /**
      * Must be constructed after the rule has been applied (e.g. in whatever method is
-     * tagged with @Before)
+     * tagged with @Before).
      */
     public WebXrArTestFramework(ChromeActivityTestRule rule) {
         super(rule);
@@ -41,6 +42,7 @@
     /**
      * Requests an AR session, automatically accepting the Camera permission prompt if necessary.
      * Causes a test failure if it is unable to do so.
+     *
      * @param webContents The Webcontents to start the AR session in.
      */
     @Override
@@ -74,7 +76,8 @@
     /**
      * Helper function to run arSessionRequestWouldTriggerPermissionPrompt with the first tab's
      * WebContents.
-     * @return True if an AR session request will cause a permission prompt, false otherwise
+     *
+     * @return True if an AR session request will cause a permission prompt, false otherwise.
      */
     public boolean arSessionRequestWouldTriggerPermissionPrompt() {
         return arSessionRequestWouldTriggerPermissionPrompt(mFirstTabWebContents);
@@ -82,6 +85,7 @@
 
     /**
      * Exits a WebXR AR session.
+     *
      * @param webcontents The WebContents to exit the AR session in
      */
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrTestFramework.java
index 826e08d..f8e4ac74 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrTestFramework.java
@@ -18,7 +18,7 @@
 public abstract class WebXrTestFramework extends XrTestFramework {
     /**
      * Must be constructed after the rule has been applied (e.g. in whatever method is
-     * tagged with @Before)
+     * tagged with @Before).
      */
     public WebXrTestFramework(ChromeActivityTestRule rule) {
         super(rule);
@@ -28,6 +28,7 @@
      * Checks whether an XRDevice was actually found. Needs to be non-static despite not using any
      * member variables in order for the WebContents-less helper version to work properly in
      * subclasses.
+     *
      * @param webContents The WebContents to run the JavaScript through.
      * @return Whether an XRDevice was found.
      */
@@ -37,6 +38,7 @@
 
     /**
      * Helper function to run xrDeviceFound with the first tab's WebContents.
+     *
      * @return Whether an XRDevice was found.
      */
     public boolean xrDeviceFound() {
@@ -47,6 +49,7 @@
      * Enters a WebXR or WebVR session of some kind by tapping on the canvas on the page. Needs to
      * be non-static despite not using any member variables in order for the WebContents-less helper
      * version to work properly in subclasses.
+     *
      * @param webContents The WebContents for the tab the canvas is in.
      */
     public void enterSessionWithUserGesture(WebContents webContents) {
@@ -68,6 +71,7 @@
      * Enters a WebXR or WebVR session of some kind and waits until the page reports it is finished
      * with its JavaScript step. Needs to be non-static despite not using any member variables in
      * order for the WebContents-less helper version to work properly in subclasses.
+     *
      * @param webContents The WebContents for the tab to enter the session in.
      */
     public void enterSessionWithUserGestureAndWait(WebContents webContents) {
@@ -84,6 +88,7 @@
 
     /**
      * Attempts to enter a WebXR or WebVR session of some kind, failing if it is unable to.
+     *
      * @param webContents The WebContents for the tab to enter the session in.
      */
     public abstract void enterSessionWithUserGestureOrFail(WebContents webContents);
@@ -97,6 +102,7 @@
 
     /**
      * Ends whatever type of session a subclass enters with enterSessionWithUserGesture.
+     *
      * @param webContents The WebContents to end the session in
      */
     public abstract void endSession(WebContents webContents);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
index 869f0be..74befc43 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -35,7 +35,6 @@
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr.mock.MockVrDaydreamApi;
 import org.chromium.chrome.browser.vr.rules.XrActivityRestriction;
@@ -361,7 +360,6 @@
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
-    @RetryOnFailure(message = "Very rarely, button press not registered (race condition?)")
     public void testAppButtonExitsPresentation() throws InterruptedException {
         appButtonExitsPresentationImpl(
                 WebVrTestFramework.getFileUrlForHtmlTestFile("generic_webvr_page"),
@@ -378,7 +376,6 @@
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
-            @RetryOnFailure(message = "Very rarely, button press not registered (race condition?)")
             public void testAppButtonExitsPresentation_WebXr() throws InterruptedException {
         appButtonExitsPresentationImpl(
                 WebXrVrTestFramework.getFileUrlForHtmlTestFile("generic_webxr_page"),
@@ -392,6 +389,7 @@
         EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity());
         controller.pressReleaseAppButton();
         assertAppButtonEffect(true /* shouldHaveExited */, framework);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -480,6 +478,7 @@
                 }));
         assertAppButtonEffect(false /* shouldHaveExited */, framework);
         VrShellDelegateUtils.getDelegateInstance().overrideDaydreamApiForTesting(null);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -509,6 +508,7 @@
                     "VR Shell is listening for headset insertion after WebContents paused",
                     VrShellDelegateUtils.getDelegateInstance().isListeningForWebVrActivate());
         });
+        mWebVrTestFramework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -518,7 +518,6 @@
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
-    @RetryOnFailure(message = "Very rarely, button press not registered (race condition?)")
     public void testAppButtonAfterPageStopsSubmitting() throws InterruptedException {
         appButtonAfterPageStopsSubmittingImpl(
                 WebVrTestFramework.getFileUrlForHtmlTestFile("webvr_page_submits_once"),
@@ -535,7 +534,6 @@
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
-            @RetryOnFailure(message = "Very rarely, button press not registered (race condition?)")
             public void testAppButtonAfterPageStopsSubmitting_WebXr() throws InterruptedException {
         appButtonAfterPageStopsSubmittingImpl(
                 WebXrVrTestFramework.getFileUrlForHtmlTestFile("webxr_page_submits_once"),
@@ -551,6 +549,7 @@
         EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity());
         controller.pressReleaseAppButton();
         assertAppButtonEffect(true /* shouldHaveExited */, framework);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
index 2be9122b..a6f0a00 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
@@ -23,6 +23,7 @@
     /**
      * VR-specific implementation of enterSessionWithUserGesture that includes a workaround for
      * receiving broadcasts late.
+     *
      * @param webContents The WebContents for the tab to enter the VR session in.
      */
     @Override
@@ -41,6 +42,7 @@
 
     /**
      * WebXR for VR-specific implementation of enterSessionWithUserGestureOrFail.
+     *
      * @param webContents The WebContents of the tab to enter the immersive session in.
      */
     @Override
@@ -56,7 +58,8 @@
 
     /**
      * Ends a WebXR immersive session.
-     * @param webContents The WebContents for the tab to end the session in
+     *
+     * @param webContents The WebContents for the tab to end the session in.
      */
     @Override
     public void endSession(WebContents webContents) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
index c67a5229..e09b8e0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -36,7 +36,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr.rules.XrActivityRestriction;
@@ -146,6 +145,7 @@
                 },
                 "Immersive session started, but browser not visibly in VR", POLL_TIMEOUT_LONG_MS,
                 POLL_CHECK_INTERVAL_LONG_MS);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -342,6 +342,7 @@
                 },
                 "Browser controls did not unhide after exiting VR", POLL_TIMEOUT_SHORT_MS,
                 POLL_CHECK_INTERVAL_SHORT_MS);
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
@@ -351,7 +352,6 @@
     @Test
     @MediumTest
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
-    @RetryOnFailure
     public void testWindowRafStopsFiringWhilePresenting() throws InterruptedException {
         windowRafStopsFiringWhilePresentingImpl(
                 WebVrTestFramework.getFileUrlForHtmlTestFile(
@@ -428,6 +428,7 @@
         framework.enterSessionWithUserGestureOrFail();
         framework.simulateRendererKilled();
         Assert.assertTrue("Browser did not enter VR", VrShellDelegate.isInVr());
+        framework.assertNoJavaScriptErrors();
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
index 369717e..3396f50 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
@@ -74,7 +74,8 @@
     private View mFirstTabContentView;
 
     /**
-     * Gets the file:// URL to the test file
+     * Gets the file:// URL to the test file.
+     *
      * @param testName The name of the test whose file will be retrieved.
      * @return The file:// URL to the specified test file.
      */
@@ -85,6 +86,7 @@
 
     /**
      * Gets the path to pass to an EmbeddedTestServer.getURL to load the given HTML test file.
+     *
      * @param testName The name of the test whose file will be retrieved.
      * @param A path that can be passed to EmbeddedTestServer.getURL to load the test file.
      */
@@ -93,9 +95,9 @@
     }
 
     /**
-     * Helper function to run the given JavaScript, return the return value,
-     * and fail if a timeout/interrupt occurs so we don't have to catch or
-     * declare exceptions all the time.
+     * Helper function to run the given JavaScript, return the return value, and fail if a
+     * timeout/interrupt occurs so we don't have to catch or declare exceptions all the time.
+     *
      * @param js The JavaScript to run.
      * @param timeout The timeout in milliseconds before a failure.
      * @param webContents The WebContents object to run the JavaScript in.
@@ -112,8 +114,9 @@
     }
 
     /**
-     * Polls the provided JavaScript boolean expression until the timeout is reached or
-     * the boolean is true.
+     * Polls the provided JavaScript boolean expression until the timeout is reached or the boolean
+     * is true.
+     *
      * @param boolExpression The JavaScript boolean expression to poll.
      * @param timeoutMs The polling timeout in milliseconds.
      * @param webContents The WebContents to run the JavaScript through.
@@ -142,6 +145,7 @@
     /**
      * Polls the provided JavaScript boolean expression, failing the test if it does not evaluate
      * to true within the provided timeout.
+     *
      * @param boolExpression The JavaScript boolean expression to poll.
      * @param timeoutMs The polling timeout in milliseconds.
      * @param webContents The Webcontents to run the JavaScript through.
@@ -154,6 +158,7 @@
 
     /**
      * Executes a JavaScript step function using the given WebContents.
+     *
      * @param stepFunction The JavaScript step function to call.
      * @param webContents The WebContents for the tab the JavaScript is in.
      */
@@ -164,8 +169,9 @@
     }
 
     /**
-     * Waits for a JavaScript step to finish, asserting that the step finished
-     * instead of timing out.
+     * Waits for a JavaScript step to finish, asserting that the step finished instead of timing
+     * out.
+     *
      * @param webContents The WebContents for the tab the JavaScript step is in.
      */
     public static void waitOnJavaScriptStep(WebContents webContents) {
@@ -208,8 +214,9 @@
 
     /**
      * Retrieves the current status of the JavaScript test and returns an enum corresponding to it.
+     *
      * @param webContents The WebContents for the tab to check the status in.
-     * @return A TestStatus integer corresponding to the current state of the JavaScript test
+     * @return A TestStatus integer corresponding to the current state of the JavaScript test.
      */
     @TestStatus
     public static int checkTestStatus(WebContents webContents) {
@@ -228,8 +235,9 @@
     }
 
     /**
-     * Helper function to end the test harness test and assert that it passed,
-     * setting the failure reason as the description if it didn't.
+     * Helper function to end the test harness test and assert that it passed, setting the failure
+     * reason as the description if it didn't.
+     *
      * @param webContents The WebContents for the tab to check test results in.
      */
     public static void endTest(WebContents webContents) {
@@ -255,6 +263,7 @@
      * useful because not all tests make use of the test harness' test/assert features (particularly
      * simple enter/exit tests), but may still want to ensure that no unexpected JavaScript errors
      * were encountered.
+     *
      * @param webContents The Webcontents for the tab to check for failures in.
      */
     public static void assertNoJavaScriptErrors(WebContents webContents) {
@@ -263,7 +272,7 @@
 
     /**
      * Must be constructed after the rule has been applied (e.g. in whatever method is
-     * tagged with @Before)
+     * tagged with @Before).
      */
     public XrTestFramework(ChromeActivityTestRule rule) {
         mRule = rule;
@@ -274,9 +283,10 @@
     /**
      * Loads the given URL with the given timeout then waits for JavaScript to
      * signal that it's ready for testing.
+     *
      * @param url The URL of the page to load.
      * @param timeoutSec The timeout of the page load in seconds.
-     * @return The return value of ChromeActivityTestRule.loadUrl()
+     * @return The return value of ChromeActivityTestRule.loadUrl().
      */
     public int loadUrlAndAwaitInitialization(String url, int timeoutSec)
             throws InterruptedException {
@@ -289,6 +299,7 @@
 
     /**
      * Helper method to run runJavaScriptOrFail with the first tab's WebContents.
+     *
      * @param js The JavaScript to run.
      * @param timeout The timeout in milliseconds before a failure.
      * @return The return value of the JavaScript.
@@ -299,6 +310,7 @@
 
     /**
      * Helper function to run pollJavaScriptBoolean with the first tab's WebContents.
+     *
      * @param boolExpression The JavaScript boolean expression to poll.
      * @param timeoutMs The polling timeout in milliseconds.
      * @return True if the boolean evaluated to true, false if timed out.
@@ -309,6 +321,7 @@
 
     /**
      * Helper function to run pollJavaScriptBooleanOrFail with the first tab's WebContents.
+     *
      * @param boolExpression The JavaScript boolean expression to poll.
      * @param timeoutMs The polling timeout in milliseconds.
      */
@@ -318,6 +331,7 @@
 
     /**
      * Helper function to run executeStepAndWait using the first tab's WebContents.
+     *
      * @param stepFunction The JavaScript step function to call.
      */
     public void executeStepAndWait(String stepFunction) {
@@ -333,7 +347,8 @@
 
     /**
      * Helper method to run checkTestSTatus with the first tab's WebContents.
-     * @return A TestStatus integer corresponding to the current state of the JavaScript test
+     *
+     * @return A TestStatus integer corresponding to the current state of the JavaScript test.
      */
     @TestStatus
     public int checkTestStatus() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrTestRule.java
index c422ec8..411e62d7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrTestRule.java
@@ -12,6 +12,8 @@
 public interface VrTestRule extends XrTestRule {
     /**
      * Whether the head tracking mode has been changed.
+     *
+     * @return True if the head tracking mode has been changed, false otherwise.
      */
     public boolean isTrackerDirty();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
index f95999e8..35809e0f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
@@ -12,7 +12,8 @@
  */
 public interface XrTestRule {
     /**
-     * Get the XrActivityRestriction.SupportedActivity that this rule is restricted to running in.
+     * @return The XrActivityRestriction.SupportedActivity that this rule is restricted to running
+     *         in.
      */
     public SupportedActivity getRestriction();
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
index d8b6af6..1c9daf5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
@@ -51,28 +51,63 @@
         private float[] mRotationEulerAngles;
         private float[] mRoomSpacePosition;
 
+        /**
+         * Sets the head pose using a quaternion.
+         *
+         * @param x The X component of the quaternion.
+         * @param y The Y component of the quaternion.
+         * @param z The Z component of the quaternion.
+         * @param w The W component of the quaternion.
+         * @return The updated FakePose instance.
+         */
         public FakePose setQuaternion(float x, float y, float z, float w) {
             mQuaternion = new float[] {x, y, z, w};
             mRotationEulerAngles = null;
             return this;
         }
 
+        /**
+         * Sets the head pose using Euler angles.
+         *
+         * @param rollDeg The head pose's roll component in degrees.
+         * @param pitchDeg The head pose's pitch component in degrees.
+         * @param yawDeg The head pose's yaw component in degrees.
+         * @return The updated FakePose instance.
+         */
         public FakePose setRotationEulerAngles(float rollDeg, float pitchDeg, float yawDeg) {
             mRotationEulerAngles = new float[] {rollDeg, pitchDeg, yawDeg};
             mQuaternion = null;
             return this;
         }
 
+        /**
+         * Sets the head pose's positional coordinates in room space.
+         *
+         * @param x The X position of the head pose in meters.
+         * @param y The Y position of the head pose in meters.
+         * @param z The Z position of the head pose in meters.
+         * @return The updated FakePose instance.
+         */
         public FakePose setRoomSpacePosition(float x, float y, float z) {
             mRoomSpacePosition = new float[] {x, y, z};
             return this;
         }
 
+        /**
+         * Clears any previously set room space head pose position.
+         *
+         * @return The updated FakePose instance.
+         */
         public FakePose clearRoomSpacePosition() {
             mRoomSpacePosition = null;
             return this;
         }
 
+        /**
+         * Formats the FakePose's stored data into a format usable as an extra in an Intent.
+         *
+         * @return A float array containing all the data of the FakePose instance.
+         */
         public float[] getDataForExtra() {
             if (mQuaternion == null && mRotationEulerAngles == null) {
                 throw new IllegalArgumentException(
@@ -126,7 +161,7 @@
      *
      * @param rule The VrTestRule used by the current test case.
      * @param pose The FakePose instance containing the pose data that will be sent to the head
-     *     tracking service.
+     *        tracking service.
      */
     public static void setHeadPose(VrTestRule rule, FakePose pose) {
         restartHeadTrackingServiceIfNecessary(rule);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
index 1fe0f3a..1d3f32c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
@@ -33,7 +33,10 @@
 
     /**
      * Clicks on a UI element as if done via a controller.
+     *
      * @param elementName The UserFriendlyElementName that will be clicked on.
+     * @param position A PointF specifying where on the element to send the click relative to a
+     *        unit square centered at (0, 0).
      */
     public static void clickElement(int elementName, PointF position) {
         TestVrShellDelegate.getInstance().performControllerActionForTesting(
@@ -43,7 +46,10 @@
     /**
      * Clicks on a UI element as if done via a controller and waits until all resulting
      * animations have finished and propogated to the point of being visible in screenshots.
+     *
      * @param elementName The UserFriendlyElementName that will be clicked on.
+     * @param position A PointF specifying where on the element to send the click relative to a
+     *        unit square centered at (0, 0).
      */
     public static void clickElementAndWaitForUiQuiescence(
             final int elementName, final PointF position) throws InterruptedException {
@@ -84,6 +90,7 @@
 
     /**
      * Runs the given Runnable and waits until the native UI reports that it is quiescent.
+     *
      * @param action A Runnable containing the action to perform.
      */
     public static void performActionAndWaitForUiQuiescence(Runnable action)
@@ -108,6 +115,7 @@
 
     /**
      * Blocks until the specified number of frames have been triggered by the Choreographer.
+     *
      * @param numFrames The number of frames to wait for.
      */
     public static void waitNumFrames(int numFrames) throws InterruptedException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NfcSimUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NfcSimUtils.java
index 478dd45..c6e20b2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NfcSimUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NfcSimUtils.java
@@ -42,6 +42,7 @@
     /**
      * Makes an Intent that triggers VrCore as if the Daydream headset's NFC
      * tag was scanned.
+     *
      * @return The intent to send to VrCore to simulate an NFC scan.
      */
     public static Intent makeNfcIntent() {
@@ -59,6 +60,7 @@
 
     /**
      * Simulates the NFC tag of the Daydream headset being scanned.
+     *
      * @param context The Context that the NFC scan activity will be started from.
      */
     public static void simNfcScan(Context context) {
@@ -73,6 +75,7 @@
     /**
      * Repeatedly simulates an NFC scan until VR is actually entered. This is a workaround for
      * https://crbug.com/736527.
+     *
      * @param context The Context that the NFC scan activity will be started from.
      */
     public static void simNfcScanUntilVrEntry(final Context context) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrBrowserTransitionUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrBrowserTransitionUtils.java
index a979aec..a7f020ce 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrBrowserTransitionUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrBrowserTransitionUtils.java
@@ -31,6 +31,7 @@
 public class VrBrowserTransitionUtils extends VrTransitionUtils {
     /**
      * Forces Chrome into the VR Browser.
+     *
      * @return True if the request to enter the VR Browser succeeded, false otherwise.
      */
     public static boolean forceEnterVrBrowser() {
@@ -46,8 +47,9 @@
     /**
      * Forces Chrome into the VR Browser, causing a test failure if it is not entered in the
      * allotted time.
+     *
      * @param timeoutMs The amount of time in milliseconds to wait for VR Browser entry before
-     *    failing.
+     *        failing.
      */
     public static void forceEnterVrBrowserOrFail(int timeoutMs) {
         Assert.assertTrue("Request to enter VR Browser failed", forceEnterVrBrowser());
@@ -99,10 +101,10 @@
      * true, this is expected to fail unless the trusted intent check is disabled in
      * VrShellDelegate.
      *
-     * @param url String containing the URL to open
-     * @param autopresent If this intent is expected to auto-present WebVR
+     * @param url String containing the URL to open.
+     * @param autopresent If this intent is expected to auto-present WebVR.
      * @param avoidRelaunch Include an extra that prevents relaunching Chrome once the intent is
-     *    received
+     *        received.
      */
     public static void sendVrLaunchIntent(String url, boolean autopresent, boolean avoidRelaunch) {
         // Create an intent that will launch Chrome at the specified URL.
@@ -142,6 +144,7 @@
     /**
      * Waits until either a JavaScript dialog or permission prompt is being displayed using the
      * Android native UI in the VR browser.
+     *
      * @param timeout How long in milliseconds to wait before timing out and failing.
      */
     public static void waitForNativeUiPrompt(final int timeout) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
index 6dc4df8..c510bfd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
@@ -25,8 +25,9 @@
 
     /**
      * Determines whether InfoBars are present in the current activity.
-     * @param rule The ChromeActivityTestRule to get the InfoBars from
-     * @return True if there are any InfoBars present, false otherwise
+     *
+     * @param rule The ChromeActivityTestRule to get the InfoBars from.
+     * @return True if there are any InfoBars present, false otherwise.
      */
     @SuppressWarnings("unchecked")
     public static boolean isInfoBarPresent(ChromeActivityTestRule rule) {
@@ -37,8 +38,9 @@
     /**
      * Clicks on either the primary or secondary button of the first InfoBar
      * in the activity.
-     * @param button Which button to click
-     * @param rule The ChromeActivityTestRule to get the InfoBars from
+     *
+     * @param button Which button to click.
+     * @param rule The ChromeActivityTestRule to get the InfoBars from.
      */
     @SuppressWarnings("unchecked")
     public static void clickInfoBarButton(final Button button, ChromeActivityTestRule rule) {
@@ -58,7 +60,8 @@
 
     /**
      * Clicks on the close button of the first InfoBar in the activity.
-     * @param rule The ChromeActivityTestRule to get the InfoBars from
+     *
+     * @param rule The ChromeActivityTestRule to get the InfoBars from.
      */
     @SuppressWarnings("unchecked")
     public static void clickInfobarCloseButton(ChromeActivityTestRule rule) {
@@ -70,7 +73,8 @@
 
     /**
      * Determines is there is any InfoBar present in the given View hierarchy.
-     * @param rule The ChromeActivityTestRule to get the InfoBars from
+     *
+     * @param rule The ChromeActivityTestRule to get the InfoBars from.
      * @param present Whether an InfoBar should be present.
      */
     public static void expectInfoBarPresent(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrShellDelegateUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrShellDelegateUtils.java
index 8751fa1e6..c9e7e11 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrShellDelegateUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrShellDelegateUtils.java
@@ -19,9 +19,11 @@
  */
 public class VrShellDelegateUtils {
     /**
-     * Retrieves the current VrShellDelegate instance from the UI thread.
-     * This is necessary in case acquiring the instance causes the delegate
-     * to be constructed, which must happen on the UI thread.
+     * Retrieves the current VrShellDelegate instance from the UI thread. This is necessary in case
+     * acquiring the instance causes the delegate to be constructed, which must happen on the UI
+     * thread.
+     *
+     * @return The TestVrShellDelegate instance currently in use.
      */
     public static TestVrShellDelegate getDelegateInstance() {
         final AtomicReference<TestVrShellDelegate> delegate =
@@ -32,12 +34,13 @@
     }
 
     /**
-     * Creates and sets a MockVrCoreVersionCheckerImpl as the VrShellDelegate's
-     * VrCoreVersionChecker instance.
+     * Creates and sets a MockVrCoreVersionCheckerImpl as the VrShellDelegate's VrCoreVersionChecker
+     * instance.
+     *
      * @param compatibility An int corresponding to a VrCoreCompatibility value that the mock
-     *     version checker will return.
+     *        version checker will return.
      * @return The MockVrCoreVersionCheckerImpl that was set as VrShellDelegate's
-     *     VrCoreVersionChecker instance.
+     *        VrCoreVersionChecker instance.
      */
     public static MockVrCoreVersionCheckerImpl setVrCoreCompatibility(int compatibility) {
         final MockVrCoreVersionCheckerImpl mockChecker = new MockVrCoreVersionCheckerImpl();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
index 3fe03923..0d03525 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
@@ -28,6 +28,9 @@
     /**
      * Creates the list of VrTestRules that are currently supported for use in test
      * parameterization.
+     *
+     * @return An ArrayList of ParameterSets, with each ParameterSet containing a callable to create
+     *         a VrTestRule for a supported ChromeActivity.
      */
     public static ArrayList<ParameterSet> generateDefaultTestRuleParameters() {
         ArrayList<ParameterSet> parameters = new ArrayList<ParameterSet>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTransitionUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTransitionUtils.java
index e602c58..b7f34cd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTransitionUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTransitionUtils.java
@@ -33,6 +33,7 @@
 
     /**
      * Waits until Chrome believes it is in VR.
+     *
      * @param timeout How long to wait for VR entry before timing out and failing.
      */
     public static void waitForVrEntry(final int timeout) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
index 153c9de..7ff4463 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
@@ -27,6 +27,9 @@
     /**
      * Creates the list of XrTestRules that are currently supported for use in test
      * parameterization.
+     *
+     * @return An ArrayList of ParameterSets, with each ParameterSet containing a callable to create
+     *         an XrTestRule for a supported ChromeActivity.
      */
     public static ArrayList<ParameterSet> generateDefaultTestRuleParameters() {
         ArrayList<ParameterSet> parameters = new ArrayList<ParameterSet>();
@@ -62,6 +65,10 @@
 
     /**
      * Creates a RuleChain that applies the XrActivityRestrictionRule before the given XrTestRule.
+     *
+     * @param rule The TestRule to wrap in an XrActivityRestrictionRule.
+     * @return A RuleChain that ensures an XrActivityRestrictionRule is applied before the provided
+     *         TestRule.
      */
     public static RuleChain wrapRuleInXrActivityRestrictionRule(TestRule rule) {
         Assert.assertTrue("Given rule is not an XrTestRule", rule instanceof XrTestRule);
@@ -71,7 +78,10 @@
     }
 
     /**
-     * Converts XrActivityRestriction.SupportedActivity enum to strings
+     * Converts XrActivityRestriction.SupportedActivity enum to strings.
+     *
+     * @param activity The SupportedActivity value to convert to a String.
+     * @return A String representation of the activity.
      */
     public static String supportedActivityToString(SupportedActivity activity) {
         switch (activity) {
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 643d715..91db96366 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1661,9 +1661,6 @@
   <message name="IDS_ENTERPRISE_ENROLLMENT_WORKING_MESSAGE" desc="Message to show while enrollment is in progress">
     Enrolling device...
   </message>
-  <message name="IDS_NETWORK_SELECTION_TITLE" desc="Welcome title shown on network selection screen">
-    Let's get started
-  </message>
   <message name="IDS_OOBE_ASSET_ID_LABEL" desc="Chrome OS OOBE: label for asset identifier.">
     Asset ID: <ph name="ASSET_ID">$1<ex>None specified</ex></ph>
   </message>
@@ -1712,10 +1709,10 @@
   <message name="IDS_HID_DETECTION_CONTINUE_BUTTON" desc="Text shown on continue button" meaning="Continue button label of HID detection screen.">
     Continue
   </message>
-  <message name="IDS_NETWORK_SELECTION_CONTINUE_BUTTON" desc="Text shown on continue button" meaning="Continue button label of welcome screen.">
+  <message name="IDS_WELCOME_SELECTION_CONTINUE_BUTTON" desc="Text shown on continue button" meaning="Continue button label of welcome screen.">
     Continue
   </message>
-  <message name="IDS_NETWORK_ENABLE_DEV_FEATURES_LINK" desc="Text shown on continue button" meaning="Link shown on OOBE screens that opens enable debugging features dialog">
+  <message name="IDS_WELCOME_ENABLE_DEV_FEATURES_LINK" desc="Link shown on welcome screen" meaning="Link shown on OOBE screens that opens enable debugging features dialog">
     Enable debugging features
   </message>
   <message name="IDS_LANGUAGE_DROPDOWN_TITLE" desc="Title of language selection dropdown menu" meaning="Small title near language dropdown menu suggesting that this is a language selector.">
@@ -1742,10 +1739,10 @@
   <message name="IDS_ACCESSIBILITY_SECTION_HINT" desc="Under-title line on the accessibility options screen" meaning="A hint to the user what these settings do and how to update them later.">
     You can customize this device to fit your needs. These accessibility features can be changed later in Settings.
   </message>
-  <message name="IDS_NETWORK_SECTION_TITLE" desc="Title of network selection screen" meaning="A title of the dialog where user should select network to connect to Internet">
+  <message name="IDS_NETWORK_SELECTION_TITLE" desc="Title of network selection screen" meaning="A title of the dialog where user should select network to connect to Internet">
     Connect to network
   </message>
-  <message name="IDS_NETWORK_SECTION_HINT" desc="Under-title line on the network selection screen" meaning="A hint to the user why device should be connected to the network">
+  <message name="IDS_NETWORK_SELECTION_HINT" desc="Under-title line on the network selection screen" meaning="A hint to the user why device should be connected to the network">
     To restore your data, you need an Internet connection.
   </message>
   <message name="IDS_NETWORK_SELECTION_ERROR" desc="Error shown when connection to network failed or timed out.">
diff --git a/chrome/app/resources/chromium_strings_ar.xtb b/chrome/app/resources/chromium_strings_ar.xtb
index 857fc4d8..5ff80b2 100644
--- a/chrome/app/resources/chromium_strings_ar.xtb
+++ b/chrome/app/resources/chromium_strings_ar.xtb
@@ -213,6 +213,7 @@
 <translation id="7962572577636132072">‏يجري تحديث Chromium تلقائيًا بحيث يكون لديك أحدث إصدار.</translation>
 <translation id="7975919845073681630">‏هذا تثبيت ثانوي من Chromium، ولا يمكن جعله متصفحك التلقائي.</translation>
 <translation id="7979877361127045932">‏الإخفاء في قائمة Chromium</translation>
+<translation id="8013436988911883588">‏بعد حصول Chromium على إمكانية الوصول، ستتمكن المواقع الإلكترونية من مطالبتك بإمكانية الوصول.</translation>
 <translation id="8030318113982266900">جارٍ تحديث جهازك إلى قناة <ph name="CHANNEL_NAME" />...</translation>
 <translation id="8157153840442649507">‏يتم عرض Chromium بهذه اللغة</translation>
 <translation id="81770708095080097">‏هذا الملف ضار، لذلك فقد حظره Chromium.</translation>
diff --git a/chrome/app/resources/chromium_strings_bn.xtb b/chrome/app/resources/chromium_strings_bn.xtb
index b53ff4e..cd4ba7bf 100644
--- a/chrome/app/resources/chromium_strings_bn.xtb
+++ b/chrome/app/resources/chromium_strings_bn.xtb
@@ -209,6 +209,7 @@
 <translation id="7962572577636132072">Chromium স্বয়ংক্রিয়ভাবে আপডেট হয় তাই আপনি সবসময় নবীনতম সংস্করণটি পান৷</translation>
 <translation id="7975919845073681630">এটা Chromium এর অপ্রধান ইনস্টলেশন এবং একে আপনার ডিফল্ট ব্রাউজার করা যাবে না।</translation>
 <translation id="7979877361127045932">Chromium মেনুর মধ্যে লুকান</translation>
+<translation id="8013436988911883588">একবার Chromium অ্যাক্সেস করার পরে, ওয়েবসাইটগুলি অ্যাক্সেস চাইতে পারে।</translation>
 <translation id="8030318113982266900">আপনার ডিভাইস <ph name="CHANNEL_NAME" /> চ্যানেলে আপডেট করা হচ্ছে...</translation>
 <translation id="8157153840442649507">এই ভাষায় Chromium  প্রদর্শিত হচ্ছে</translation>
 <translation id="81770708095080097">এই ফাইলটি বিপজ্জনক, তাই Chromium এটিকে অবরুদ্ধ করেছে।</translation>
diff --git a/chrome/app/resources/chromium_strings_de.xtb b/chrome/app/resources/chromium_strings_de.xtb
index 64a475b..f84277e 100644
--- a/chrome/app/resources/chromium_strings_de.xtb
+++ b/chrome/app/resources/chromium_strings_de.xtb
@@ -149,7 +149,7 @@
 <translation id="6394232988457703198">Chromium jetzt neu starten.</translation>
 <translation id="6400072781405947421">Chromium funktioniert unter Umständen nicht ordnungsgemäß, da es unter Mac OS X 10.9 nicht mehr unterstützt wird.</translation>
 <translation id="6403826409255603130">Chromium ist ein Webbrowser, der Webseiten und Apps in Sekundenschnelle lädt und dabei äußerst stabil und nutzerfreundlich ist. Dank des integrierten Malware- und Phishing-Schutzes können Sie bedenkenlos im Internet surfen.</translation>
-<translation id="641451971369018375">Mit Google kommunizieren, um das Surferlebnis und Chromium zu verbessern</translation>
+<translation id="641451971369018375">Funktionen nutzen, die helfen, Chrome für Sie noch besser zu machen</translation>
 <translation id="6457450909262716557">{SECONDS,plural, =1{Chromium wird in 1 Sekunde neu gestartet}other{Chromium wird in # Sekunden neu gestartet}}</translation>
 <translation id="6475912303565314141">Die Erweiterung legt auch die Seite fest, die beim Start von Chromium angezeigt wird.</translation>
 <translation id="6485906693002546646">Ihre E-Mail-Adresse <ph name="PROFILE_EMAIL" /> wird zurzeit für die Synchronisierung Ihrer Chromium-Inhalte verwendet. Wenn Sie Ihre Synchronisierungseinstellungen ändern oder Chromium ohne Google-Konto verwenden möchten, rufen Sie <ph name="SETTINGS_LINK" /> auf.</translation>
diff --git a/chrome/app/resources/chromium_strings_ru.xtb b/chrome/app/resources/chromium_strings_ru.xtb
index 6f0e1972..7cda3444 100644
--- a/chrome/app/resources/chromium_strings_ru.xtb
+++ b/chrome/app/resources/chromium_strings_ru.xtb
@@ -209,6 +209,7 @@
 <translation id="7962572577636132072">Chromium обновляется автоматически, поэтому у вас всегда будет установлена последняя версия.</translation>
 <translation id="7975919845073681630">Это дополнительная установка Chromium. Его нельзя сделать браузером по умолчанию.</translation>
 <translation id="7979877361127045932">Не показывать в меню Chromium</translation>
+<translation id="8013436988911883588">Когда вы предоставите доступ Chromium, веб-сайты также смогут запрашивать у вас доступ.</translation>
 <translation id="8030318113982266900">Переключение устройства на канал <ph name="CHANNEL_NAME" />...</translation>
 <translation id="8157153840442649507">Этот язык сейчас используется в Chromium</translation>
 <translation id="81770708095080097">Chromium заблокировал этот файл как опасный.</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 395aa0e..1e3ee8f 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -299,6 +299,7 @@
 <translation id="1433811987160647649">السؤال قبل الوصول</translation>
 <translation id="1434696352799406980">سيعيد هذا تعيين صفحة بدء التشغيل، وصفحة علامة تبويب جديدة، ومحرك البحث، وعلامات التبويب المثبتة. وستعطِّل أيضًا جميع الإضافات وتمحو البيانات المؤقتة مثل ملفات تعريف الارتباط. ولن يتم محو الإشارات المرجعية، والسجل، وكلمات المرور المحفوظة.</translation>
 <translation id="1434886155212424586">الصفحة الرئيسية هي صفحة "علامة تبويب جديدة"</translation>
+<translation id="1436671784520050284">متابعة الإعداد</translation>
 <translation id="1436784010935106834">تمت الإزالة</translation>
 <translation id="1438632560381091872">إلغاء تجاهل علامات التبويب</translation>
 <translation id="1442392616396121389">بادئة توجيه</translation>
@@ -318,6 +319,7 @@
 <translation id="1465827627707997754">شريحة بيتزا</translation>
 <translation id="1467432559032391204">اليسار</translation>
 <translation id="1468571364034902819">يتعذّر استخدام هذا الملف الشخصي</translation>
+<translation id="1470533772306424441">‏سوف نثبّت هذه التطبيقات من أجلك. يمكنك العثور على المزيد من التطبيقات لجهازك في متجر Play.</translation>
 <translation id="1470811252759861213">للحصول على الإضافات على جميع أجهزة الكمبيوتر، <ph name="SIGN_IN_LINK" />.</translation>
 <translation id="1474339897586437869">‏لم يتم تحميل "<ph name="FILENAME" />". حيث لا توجد لديك مساحة فارغة كافية في Google Drive.</translation>
 <translation id="1475502736924165259">لديك شهادات في الملف لا تندرج تحت أي فئة من الفئات الأخرى</translation>
@@ -792,6 +794,7 @@
 <translation id="2192505247865591433">من:</translation>
 <translation id="2193365732679659387">إعدادات الثقة</translation>
 <translation id="2195729137168608510">حماية البريد الإلكتروني</translation>
+<translation id="2199298570273670671">خطأ</translation>
 <translation id="2200356397587687044">‏يحتاج Chrome إلى إذن للمتابعة</translation>
 <translation id="220138918934036434">إخفاء الزر</translation>
 <translation id="2202898655984161076">حدثت مشكلة أثناء إدراج الطابعات. ربما لا يتم تسجيل بعض الطابعات بنجاح في <ph name="CLOUD_PRINT_NAME" />.</translation>
@@ -944,6 +947,7 @@
 <translation id="2440604414813129000">عرض الم&amp;صدر</translation>
 <translation id="2445081178310039857">دليل الجذر للإضافة مطلوب.</translation>
 <translation id="2445484935443597917">إنشاء ملف شخصي جديد</translation>
+<translation id="2446585455334014596">يريد <ph name="APP_NAME" /> إثبات هويتك</translation>
 <translation id="2448312741937722512">النوع</translation>
 <translation id="2450223707519584812">‏لن تتمكن من إضافة المستخدمين لأن مفاتيح واجهة برمجة تطبيقات Google مفقودة. راجع <ph name="DETAILS_URL" /> للحصول على تفاصيل.</translation>
 <translation id="2450310832094867474">هل تريد إيقاف المزامنة وتسجيل الخروج؟</translation>
@@ -953,6 +957,7 @@
 <translation id="2453576648990281505">الملف موجود فعلاً</translation>
 <translation id="2453860139492968684">اكتمل</translation>
 <translation id="2454247629720664989">الكلمة المفتاحية</translation>
+<translation id="245661998428026871">سيتم إيقاف تشغيل الفيديو في وضع "نافذة ضمن نافذة".</translation>
 <translation id="2457246892030921239">يريد <ph name="APP_NAME" /> نسخ الملفات من <ph name="VOLUME_NAME" />.</translation>
 <translation id="2462724976360937186">معرّف مفتاح المرجع المصدق</translation>
 <translation id="2462752602710430187">تمت إضافة <ph name="PRINTER_NAME" /></translation>
@@ -1359,6 +1364,7 @@
 <translation id="304826556400666995">إلغاء تجاهل علامات التبويب</translation>
 <translation id="3053013834507634016">استخدام مفتاح الشهادة</translation>
 <translation id="3057861065630527966">نسخ الصور والفيديوهات احتياطيًا</translation>
+<translation id="3059313675706898490">‏رسائل Android</translation>
 <translation id="3060379269883947824">تفعيل سماع الاختيار</translation>
 <translation id="3061707000357573562">خدمة رمز التصحيح</translation>
 <translation id="3064410671692449875">بيانات غير كافية</translation>
@@ -1407,6 +1413,7 @@
 <translation id="313205617302240621">هل نسيت كلمة المرور؟</translation>
 <translation id="3132996321662585180">التحديث يوميًا</translation>
 <translation id="3135204511829026971">تدوير الشاشة</translation>
+<translation id="313638818480447860">لقد عثرنا على <ph name="NUMBER_OF_APPS" /> من التطبيقات المرتبطة بحسابك التي تم تحسينها لهذا الجهاز.</translation>
 <translation id="313963229645891001">جارٍ التنزيل، <ph name="STATUS" /></translation>
 <translation id="3139925690611372679">الصورة الرمزية التلقائية الصفراء</translation>
 <translation id="3140353188828248647">تركيز شريط العناوين</translation>
@@ -1437,6 +1444,7 @@
 <translation id="3182749001423093222">التدقيق الإملائي</translation>
 <translation id="3183139917765991655">مستورد الملف الشخصي</translation>
 <translation id="3184560914950696195">تعذر الحفظ في $1. سيتم حفظ الصورة التي تم تعديلها في مجلد التنزيلات.</translation>
+<translation id="3188257591659621405">ملفاتي</translation>
 <translation id="3188465121994729530">معدل الانتقال</translation>
 <translation id="3190558889382726167">تم حفظ كلمة المرور</translation>
 <translation id="3192947282887913208">ملفات صوتية</translation>
@@ -1523,6 +1531,7 @@
 <translation id="3326821416087822643">جارٍ ضغط <ph name="FILE_NAME" />...</translation>
 <translation id="3331321258768829690">(<ph name="UTCOFFSET" />) <ph name="LONGTZNAME" /> (<ph name="EXEMPLARCITY" />)</translation>
 <translation id="3331974543021145906">معلومات التطبيق</translation>
+<translation id="3334632933872291866"><ph name="WINDOW_TITLE" /> - جارٍ تشغيل الفيديو في وضع "نافذة ضمن نافذة"</translation>
 <translation id="3335337277364016868">عام التسجيل</translation>
 <translation id="3335947283844343239">إعادة فتح علامة التبويب المغلقة</translation>
 <translation id="3336664756920573711">‏إلغاء قفل <ph name="DEVICE_TYPE" /> باستخدام هاتفك الذي يعمل بنظام التشغيل Android</translation>
@@ -1542,6 +1551,7 @@
 <translation id="3360297538363969800">تعذّرت الطباعة. يُرجى التحقق من الطابعة وإعادة المحاولة.</translation>
 <translation id="3364721542077212959">أدوات قلم الشاشة</translation>
 <translation id="3365598184818502391">‏يرجى استخدام مفتاح واحد فقط: Ctrl أو Alt.</translation>
+<translation id="3367047597842238025">يمكنك إعداد جهاز <ph name="DEVICE_TYPE" /> كما تريد تمامًا واكتشاف جميع الإمكانيات المذهلة في متناول يدك.</translation>
 <translation id="3368922792935385530">متصل</translation>
 <translation id="3369624026883419694">إثبات هوية المضيف...</translation>
 <translation id="337286756654493126">قراءة المجلدات التي تفتحها في التطبيق</translation>
@@ -1555,6 +1565,7 @@
 <translation id="3389312115541230716">انقر بزر الماوس الأيمن على رمز <ph name="SMALL_PRODUCT_LOGO" /> في شريط المهام</translation>
 <translation id="3391716558283801616">علامة التبويب 7</translation>
 <translation id="3396331542604645348">الطابعة المحددة غير متاحة أو لم يتم تثبيتها بشكل صحيح. تحقق من الطابعة أو جرّب تحديد طابعة أخرى.</translation>
+<translation id="3396800784455899911">‏بالنقر على الزر "قبول ومتابعة"، أنك توافق على المعالجة الموضّحة أعلاه لخدمات Google هذه.</translation>
 <translation id="3399432415385675819">سيتم إيقاف الإشعارات</translation>
 <translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />، <ph name="TIME_LEFT" /></translation>
 <translation id="3404065873681873169">لم يتم حفظ أي كلمات مرور لهذا الموقع</translation>
@@ -1783,10 +1794,13 @@
 <translation id="3726463242007121105">لا يمكن فتح الجهاز لأن نظام الملفات غير متوافق.</translation>
 <translation id="3727148787322499904">سيؤثر تغيير هذا الإعداد في جميع الشبكات المشتركة</translation>
 <translation id="3727187387656390258">فحص النوافذ المنبثقة</translation>
+<translation id="3729506734996624908">المواقع الإلكترونية المسموح بها</translation>
 <translation id="3732078975418297900">خطأ في السطر رقم <ph name="ERROR_LINE" /></translation>
 <translation id="3733127536501031542">‏خادم بروتوكول SSL (طبقة المقابس الآمنة) مع الترقية</translation>
+<translation id="3735740477244556633">ترتيب بحسب</translation>
 <translation id="3737274407993947948">‏حدث خطأ أثناء تثبيت نظام تشغيل Linux...</translation>
 <translation id="3737536731758327622">تظهر تنزيلاتك هنا</translation>
+<translation id="3738671331307774213">يساعد إثبات هويتك في حماية بياناتك الخاصة.</translation>
 <translation id="3738924763801731196"><ph name="OID" />:</translation>
 <translation id="3739254215541673094">هل ترغب في فتح <ph name="APPLICATION" />؟</translation>
 <translation id="3741158646617793859">سيظهر <ph name="DEVICE_NAME" /> الآن في وحدة تحكم المشرف</translation>
@@ -1871,6 +1885,7 @@
 <translation id="3846116211488856547">‏يمكنك الحصول على أدوات لتطوير المواقع الإلكترونية وتطبيقات Android والمزيد. سيؤدي تثبيت نظام التشغيل Linux إلى تنزيل <ph name="DOWNLOAD_SIZE" /> من البيانات.</translation>
 <translation id="385051799172605136">الرجوع إلى الوراء</translation>
 <translation id="3851428669031642514">تحميل النصوص البرمجية غير الآمنة</translation>
+<translation id="3854599674806204102">حدِّد خيارًا</translation>
 <translation id="3855441664322950881">إنشاء حزمة للإضافة</translation>
 <translation id="3855676282923585394">إشارات وإعدادات الاستيراد...</translation>
 <translation id="3856800405688283469">تحديد منطقة زمنية</translation>
@@ -2534,6 +2549,7 @@
 <translation id="4955814292505481804">سنوي</translation>
 <translation id="4957949153200969297">يمكنك تفعيل الميزات ذات الصلة بمزامنة <ph name="IDS_SHORT_PRODUCT_NAME" /> فقط.</translation>
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation>
+<translation id="4961000125720751066">يمكنك الاحتفاظ ببطاقاتك في مكانٍ واحد</translation>
 <translation id="496226124210045887">المجلد الذي حددته يشتمل على ملفات حساسة. فهل تريد بالتأكيد منح "$1" حق الدخول الدائم للقراءة في هذا المجلد؟</translation>
 <translation id="4964455510556214366">الترتيب</translation>
 <translation id="4964673849688379040">جارٍ التحقق...</translation>
@@ -2580,6 +2596,7 @@
 <translation id="5027562294707732951">تثبيت إضافة</translation>
 <translation id="5029568752722684782">محو النسخة</translation>
 <translation id="5030338702439866405">جهة الإصدار</translation>
+<translation id="503155457707535043">تنزيل التطبيقات</translation>
 <translation id="503498442187459473">يريد <ph name="HOST" /> استخدام الكاميرا والميكروفون.</translation>
 <translation id="5036662165765606524">عدم السماح لأي موقع بتنزيل عدة ملفات تلقائيًا</translation>
 <translation id="5037676449506322593">تحديد الكل</translation>
@@ -3094,6 +3111,7 @@
 <translation id="57838592816432529">كتم الصوت</translation>
 <translation id="5785583009707899920">‏أدوات المساعدة لملف Chrome</translation>
 <translation id="5787146423283493983">توافق المفاتيح</translation>
+<translation id="5788127256798019331">‏ملفات Play</translation>
 <translation id="5788367137662787332">عذرًا، تعذر تركيب جزء واحد على الأقل على الجهاز <ph name="DEVICE_LABEL" />.</translation>
 <translation id="5794414402486823030">افتح دائمًا باستخدام عرض النظام</translation>
 <translation id="5794786537412027208">‏إنهاء جميع تطبيقات Chrome</translation>
@@ -3347,6 +3365,7 @@
 <translation id="6178664161104547336">تحديد شهادة</translation>
 <translation id="6181431612547969857">تم حظر التنزيل</translation>
 <translation id="6185132558746749656">موقع الجهاز</translation>
+<translation id="6185617499004995178">‏مدقق CUPS IPP</translation>
 <translation id="6185696379715117369">صفحة لأعلى</translation>
 <translation id="6189273858858366896">إعداد مشاركات ملف الشبكة أو إدارتها.</translation>
 <translation id="6189412234224385711">فتح باستخدام <ph name="EXTENSION_NAME" /></translation>
@@ -3379,6 +3398,7 @@
 <translation id="6231881193380278751">‏أضف معلمة طلب بحث في عنوان URL لإجراء تحديث تلقائي لصفحة: chrome://device-log/?refresh=&lt;sec&gt;</translation>
 <translation id="6232017090690406397">البطارية</translation>
 <translation id="6232116551750539448">انقطع الاتصال بـ <ph name="NAME" /></translation>
+<translation id="6235700927623181151">تشارك علامة التبويب هذه محتوى سطح المكتب.</translation>
 <translation id="6237816943013845465">تسمح لك بضبط دقة الشاشة</translation>
 <translation id="6238923052227198598">إبقاء آخر ملاحظة على شاشة التأمين</translation>
 <translation id="6239558157302047471">إعادة تحميل الإطار</translation>
@@ -3523,6 +3543,7 @@
 <translation id="6451180435462401570">إدارة أجهزة الطباعة السحابية</translation>
 <translation id="6451689256222386810">إذا نسيت عبارة المرور أو رغبت في تغيير هذا الإعداد، يمكنك <ph name="BEGIN_LINK" />إعادة تعيين المزامنة<ph name="END_LINK" />.</translation>
 <translation id="6452181791372256707">رفض</translation>
+<translation id="6455264371803474013">على مواقع إلكترونية محددة</translation>
 <translation id="6455894534188563617">&amp;مجلد جديد</translation>
 <translation id="6456394469623773452">جيدة</translation>
 <translation id="6456631036739229488">‏تم تغيير هاتف Smart Lock. أدخل كلمة مرورك لتحديث Smart Lock. وفي المرة القادمة، سيلغي هاتفك قفل جهاز <ph name="DEVICE_TYPE" />. أوقف تشغيل Smart Lock في الإعدادات.</translation>
@@ -3600,6 +3621,7 @@
 <translation id="657402800789773160">إ&amp;عادة تحميل هذه الصفحة</translation>
 <translation id="6577284282025554716">تم إلغاء التنزيل: <ph name="FILE_NAME" /></translation>
 <translation id="6578664922716508575">‏تشفير كلمات المرور المتزامنة باستخدام اسم المستخدم وكلمة المرور لحساب Google</translation>
+<translation id="6579705087617859690"><ph name="WINDOW_TITLE" /> - تمت مشاركة محتوى سطح المكتب</translation>
 <translation id="6580151766480067746">‏إصدار ARC</translation>
 <translation id="6581162200855843583">‏رابط Google Drive</translation>
 <translation id="6582421931165117398">لحماية معلوماتك الشخصية، غيِّر كلمة مرورك الآن. قبل أن تتمكن من تغيير كلمة مرورك، سيُطلب منك تسجيل الدخول.</translation>
@@ -4066,6 +4088,7 @@
 <translation id="730289542559375723">{NUM_APPLICATIONS,plural, =1{‏قد يمنع هذا التطبيق تشغيل Chrome بشكلٍ صحيح.}zero{‏قد تمنع هذه التطبيقات تشغيل Chrome بشكلٍ صحيح.}two{‏قد يمنع هذان التطبيقان تشغيل Chrome بشكلٍ صحيح.}few{‏قد تمنع هذه التطبيقات تشغيل Chrome بشكلٍ صحيح.}many{‏قد تمنع هذه التطبيقات تشغيل Chrome بشكلٍ صحيح.}other{‏قد تمنع هذه التطبيقات تشغيل Chrome بشكلٍ صحيح.}}</translation>
 <translation id="7303900363563182677">تم حظر هذا الموقع من الاطلاع على النصوص والصور التي تم نسخها إلى الحافظة.</translation>
 <translation id="730515362922783851">تبادل البيانات مع أي جهاز على الشبكة المحلية أو الإنترنت</translation>
+<translation id="7307129035224081534">متوقف مؤقتًا</translation>
 <translation id="7308002049209013926">‏استخدم Launcher للوصول بسرعة إلى التطبيقات والأنشطة الجديدة. وللوصول إلى هنا من خلال لوحة المفاتيح، اضغط على Alt + Shift + L.</translation>
 <translation id="7309257895202129721">عرض &amp;عناصر التحكم</translation>
 <translation id="7310598146671372464">‏تعذّر تسجيل الدخول لأن الخادم لا يدعم أنواع تشفير Kerberos المحدَّدة. يُرجى الاتصال بمشرفك.</translation>
@@ -4155,6 +4178,7 @@
 <translation id="7465778193084373987">‏عنوان URL لإبطال شهادة Netscape</translation>
 <translation id="7469894403370665791">الاتصال بهذه الشبكة تلقائيًا</translation>
 <translation id="747114903913869239">خطأ: تعذر فك تشفير الإضافة</translation>
+<translation id="7473753388963818366">لنبدأ بإعداد الجهاز <ph name="DEVICE_TYPE" /> من أجلك</translation>
 <translation id="7473891865547856676">لا، شكرًا</translation>
 <translation id="747459581954555080">استرداد الكل</translation>
 <translation id="7475671414023905704">‏عنوان URL لكلمة المرور المفقودة في Netscape</translation>
@@ -4280,6 +4304,7 @@
 <translation id="7665369617277396874">إضافة حساب</translation>
 <translation id="7671130400130574146">استخدام شريط عناوين النظام والحدود</translation>
 <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، في <ph name="PAGE_TITLE" />.</translation>
+<translation id="7676867886086876795">‏يمكنك إرسال صوتك إلى Google للسماح بالإملاء في أي حقل نصي.</translation>
 <translation id="7681095912841365527">يمكن لموقع الويب استخدام البلوتوث.</translation>
 <translation id="7683373461016844951">للمتابعة، انقر على "موافقة" ثم انقر على "إضافة شخص" لإنشاء ملف شخصي جديد لعنوان بريدك الإلكتروني على النطاق <ph name="DOMAIN" />.</translation>
 <translation id="7684212569183643648">تم التثبيت من قبل مشرفك</translation>
@@ -4321,6 +4346,7 @@
 <translation id="7740996059027112821">قياسي</translation>
 <translation id="7748528009589593815">علامة التبويب السابقة</translation>
 <translation id="7748626145866214022">‏تتوفر مزيد من الخيارات على شريط الإجراءات. يُرجى الضغط على "Alt + A" لتركيز هذا الشريط.</translation>
+<translation id="7750228210027921155">نافذة ضمن النافذة</translation>
 <translation id="7751260505918304024">عرض الكل</translation>
 <translation id="7754704193130578113">السؤال عن مكان حفظ الملفّات قبل التحميل</translation>
 <translation id="7758143121000533418">Family Link</translation>
@@ -4429,6 +4455,7 @@
 <translation id="7857949311770343000">هل هذه هي صفحة علامة التبويب الجديدة التي كنت تتوقع ظهورها؟</translation>
 <translation id="786073089922909430">الخدمة: <ph name="ARC_PROCESS_NAME" /></translation>
 <translation id="7861215335140947162">ال&amp;تنزيلات</translation>
+<translation id="7868378670806575181">{NUM_COOKIES,plural, =1{ملف تعريف ارتباط واحد}zero{# ملف تعريف ارتباط}two{ملفي تعريف ارتباط (#)}few{# ملفات تعريف ارتباط}many{# ملف تعريف ارتباط}other{# ملف تعريف ارتباط}}</translation>
 <translation id="786957569166715433"><ph name="DEVICE_NAME" /> - تم الإقران</translation>
 <translation id="7870730066603611552">مراجعة خيارات المزامنة بعد الإعداد</translation>
 <translation id="7870790288828963061">‏لا توجد إصدارات أحدث لتطبيق Kiosk. لا يوجد شيء لتحديثه. يُرجى إزالة جهاز USB.</translation>
@@ -4750,6 +4777,7 @@
 <translation id="8373553483208508744">تجاهل علامات التبويب</translation>
 <translation id="8382913212082956454">نسخ عنوان البريد الإل&amp;كتروني</translation>
 <translation id="8386903983509584791">اكتملت عملية الفحص.</translation>
+<translation id="8389492867173948260">السماح لهذه الإضافة بقراءة جميع بياناتك وتغييرها على المواقع الإلكترونية التي تزورها:</translation>
 <translation id="8390449457866780408">الخادم غير متاح.</translation>
 <translation id="8391712576156218334">الصورة غير متاحة. يُرجى إعادة المحاولة لاحقًا.</translation>
 <translation id="8392234662362215700">‏انقر على Control-Shift-Space لتبديل تخطيط لوحة المفاتيح.</translation>
@@ -4781,6 +4809,7 @@
 <translation id="84297032718407999">سيتم تسجيل خروجك خلال <ph name="LOGOUT_TIME_LEFT" />.</translation>
 <translation id="8431909052837336408">‏تغيير رمز PIN لشريحة SIM</translation>
 <translation id="8434480141477525001">‏منفذ تصحيح أخطاء NaCl</translation>
+<translation id="8435395510592618362">إثبات هويتك من خلال <ph name="APP_NAME" /></translation>
 <translation id="843760761634048214">حفظ بطاقة الائتمان</translation>
 <translation id="8438328416656800239">التبديل إلى متصفح ذكي</translation>
 <translation id="8438566539970814960">تحسين عمليات البحث والتصفُّح</translation>
@@ -4807,6 +4836,7 @@
 <translation id="8465252176946159372">غير صالح</translation>
 <translation id="8465444703385715657">يتطلب تشغيل <ph name="PLUGIN_NAME" /> إذنًا منك</translation>
 <translation id="8466234950814670489">‏أرشيف Tar</translation>
+<translation id="8466417995783206254">تشغِّل علامة التبويب هذه فيديو في وضع "نافذة ضمن نافذة".</translation>
 <translation id="8468750959626135884">‏إلغاء قفل <ph name="DEVICE_TYPE" /> باستخدام هاتف Android.</translation>
 <translation id="8470028084415844044">لإضافة كل كلمات المرور على جميع أجهزتك، يُرجى تفعيل المزامنة.</translation>
 <translation id="8470513973197838199">كلمات المرور المحفوظة لـ <ph name="ORIGIN" /></translation>
@@ -4827,6 +4857,7 @@
 <translation id="8496717697661868878">تشغيل هذا المكون الإضافي</translation>
 <translation id="8497219075884839166">‏الأدوات المساعدة في Windows</translation>
 <translation id="8498214519255567734">يمكنك تسهيل النظر إلى الشاشة أو القراءة في الضوء الخافت</translation>
+<translation id="8498395510292172881">‏متابعة القراءة في Chrome</translation>
 <translation id="8503813439785031346">اسم المستخدم</translation>
 <translation id="850875081535031620">لم يتم العثور على أي برامج ضارة</translation>
 <translation id="8509646642152301857">تعذّر تنزيل قاموس التدقيق الإملائي.</translation>
@@ -5167,6 +5198,7 @@
 <translation id="9027459031423301635">فتح الرابط في &amp;علامة تبويب جديدة</translation>
 <translation id="9030515284705930323">‏لم تمكّن مؤسستك متجر Google Play لحسابك. اتصل بالمشرف للحصول على مزيد من المعلومات.</translation>
 <translation id="9033857511263905942">ل&amp;صق</translation>
+<translation id="9034924485347205037">‏ملفات نظام التشغيل Linux</translation>
 <translation id="9035012421917565900">لا يمكن نقل العناصر مرة أخرى إلى '<ph name="DESTINATION_NAME" />'، لذلك لن تتمكن من التراجع عن هذا الإجراء.</translation>
 <translation id="9037008143807155145">https://www.google.com/calendar/render?cid=%s</translation>
 <translation id="9037965129289936994">عرض الصفحة الأصلية</translation>
@@ -5267,6 +5299,7 @@
 <translation id="9173995187295789444">جارٍ البحث عن أجهزة بلوتوث...</translation>
 <translation id="9176611096776448349"><ph name="WINDOW_TITLE" /> - جهاز البلوتوث متصل</translation>
 <translation id="9177499212658576372">إنك متصل حاليًا بشبكة <ph name="NETWORK_TYPE" />.</translation>
+<translation id="9179734824669616955">‏إعداد نظام التشغيل Linux (الإصدار التجريبي) على جهاز <ph name="DEVICE_TYPE" /></translation>
 <translation id="9180281769944411366">‏قد تستغرق هذه العملية بضع دقائق. جارٍ بدء تشغيل حاوية نظام التشغيل Linux.</translation>
 <translation id="9180380851667544951">يمكن لموقع الويب مشاركة شاشتك.</translation>
 <translation id="9188441292293901223">‏يُرجى تحديث هاتفك إلى الإصدار الأحدث من Android لإلغاء قفل <ph name="DEVICE_TYPE" />.</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index b370cd1..a9c7067 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -298,6 +298,7 @@
 <translation id="1433811987160647649">অ্যাক্সেস করার আগে জিজ্ঞাসা করুন</translation>
 <translation id="1434696352799406980">এটি আপনার শুরুর পৃষ্ঠা, নতুন ট্যাব পৃষ্ঠা, সার্চ ইঞ্জিন, এবং পিন হওয়া ট্যাবগুলি আবার সেট করবে। এছাড়াও এটি সব কটি এক্সটেনশান অক্ষম করবে এবং  কুকিজের মতো অস্থায়ী ডেটা সাফ করবে। আপনার বুকমার্ক, ইতিহাস এবং সংরক্ষিত পাসওয়ার্ডগুলি সাফ করা হবে না।</translation>
 <translation id="1434886155212424586">হোমপেজ হল নতুন ট্যাব পৃষ্ঠা</translation>
+<translation id="1436671784520050284">সেট-আপ চালিয়ে যান</translation>
 <translation id="1436784010935106834">সরানো হয়েছে</translation>
 <translation id="1438632560381091872">ট্যাবগুলি সশব্দ করুন</translation>
 <translation id="1442392616396121389">রাউটিং প্রিফিক্স</translation>
@@ -317,6 +318,7 @@
 <translation id="1465827627707997754">পিৎজার টুকরা</translation>
 <translation id="1467432559032391204">বামে</translation>
 <translation id="1468571364034902819">এই প্রোফাইলটি ব্যবহার করা যাবে না</translation>
+<translation id="1470533772306424441">আমরা আপনার জন্য সেই অ্যাপগুলি ইনস্টল করব। Play স্টোরে আপনি আপনার ডিভাইসের জন্য আরও অ্যাপ খুঁজে পেতে পারেন।</translation>
 <translation id="1470811252759861213">আপনার সকল কম্পিউটারে আপনার এক্সটেনশানগুলি পেতে, <ph name="SIGN_IN_LINK" />।</translation>
 <translation id="1474339897586437869">"<ph name="FILENAME" />" আপলোড করা হয়নি। আপনার Google ড্রাইভে পর্যাপ্ত ফাঁকা স্থান নেই।</translation>
 <translation id="1475502736924165259">আপনার কাছে ফাইলে সেই শংসাপত্রগুলি আছে যা অন্য বিভাগগুলির একটিতেও মেলে না</translation>
@@ -787,6 +789,7 @@
 <translation id="2192505247865591433">এর থেকে:</translation>
 <translation id="2193365732679659387">বিশ্বস্ততার সেটিংস</translation>
 <translation id="2195729137168608510">ইমেল সুরক্ষা</translation>
+<translation id="2199298570273670671">সমস্যা</translation>
 <translation id="2200356397587687044">কাজটি চালিয়ে যাওয়ার জন্য Chrome কে অনুমতি দিতে হবে</translation>
 <translation id="220138918934036434">বোতাম লুকান</translation>
 <translation id="2202898655984161076">মুদ্রকগুলি তালিকাকরণে একটি সমস্যা ছিল৷ আপনার মুদ্রকগুলির মধ্যে কয়েকটি সফলভাবে <ph name="CLOUD_PRINT_NAME" />তে নিবন্ধীকৃত নাও থাকতে পারে৷</translation>
@@ -937,6 +940,7 @@
 <translation id="2440604414813129000">উ&amp;ত্স দেখুন</translation>
 <translation id="2445081178310039857">এক্সটেনশন রুট ডিরেক্টরি প্রয়োজন৷</translation>
 <translation id="2445484935443597917">একটি নতুন প্রোফাইল তৈরি করুন</translation>
+<translation id="2446585455334014596"><ph name="APP_NAME" /> আপনার পরিচয় যাচাই করতে চায়</translation>
 <translation id="2448312741937722512">প্রকার</translation>
 <translation id="2450223707519584812">Google API কীগুলি না থাকার কারণে আপনি ব্যবহারকারীদেরকে যোগ করতে পারবেন না। বিস্তারিত জানার জন্য <ph name="DETAILS_URL" /> দেখুন।</translation>
 <translation id="2450310832094867474">সিঙ্ক বন্ধ করে সাইন-আউট করবেন?</translation>
@@ -946,6 +950,7 @@
 <translation id="2453576648990281505">ফাইলটি ইতিমধ্যেই বিদ্যমান</translation>
 <translation id="2453860139492968684">সমাপ্ত করুন</translation>
 <translation id="2454247629720664989">মূলশব্দ</translation>
+<translation id="245661998428026871">ছবির-মধ্যে-ছবি মোডে ভিডিও চলা বন্ধ হয়ে যাবে।</translation>
 <translation id="2457246892030921239"><ph name="APP_NAME" /> <ph name="VOLUME_NAME" /> থেকে ফাইলসমূহ প্রতিলিপি করতে চায়৷</translation>
 <translation id="2462724976360937186">শংসাপত্র কর্তৃত্ব কী ID</translation>
 <translation id="2462752602710430187"><ph name="PRINTER_NAME" /> যোগ করা হয়েছে</translation>
@@ -1350,6 +1355,7 @@
 <translation id="304826556400666995">ট্যাবগুলি সশব্দ করুন</translation>
 <translation id="3053013834507634016">শংসাপত্র কী ব্যবহার</translation>
 <translation id="3057861065630527966">আপনার ফটো ও ভিডিওগুলির ব্যাকআপ নিন</translation>
+<translation id="3059313675706898490">Android মেসেজ</translation>
 <translation id="3060379269883947824">'বাছুন ও শুনুন' চালু করুন</translation>
 <translation id="3061707000357573562">প্যাচ পরিষেবা</translation>
 <translation id="3064410671692449875">অপর্যাপ্ত ডেটা</translation>
@@ -1397,6 +1403,7 @@
 <translation id="313205617302240621">পাসওয়ার্ড ভুলে গেছেন?</translation>
 <translation id="3132996321662585180">প্রতিদিন রিফ্রেশ করুন</translation>
 <translation id="3135204511829026971">স্ক্রিন ঘোরান</translation>
+<translation id="313638818480447860">আমরা আপনার অ্যাকাউন্টের সাথে কানেক্ট করা <ph name="NUMBER_OF_APPS" />টি অ্যাপ পেয়েছি যা এই ডিভাইসের জন্য অপ্টিমাইজ করা হয়েছে।</translation>
 <translation id="313963229645891001">ডাউনলোড হচ্ছে: <ph name="STATUS" /> বাকি</translation>
 <translation id="3139925690611372679">ডিফল্ট হলুদ রঙের অবতার</translation>
 <translation id="3140353188828248647">ফোকাস ঠিকানা দণ্ড</translation>
@@ -1427,6 +1434,7 @@
 <translation id="3182749001423093222">বানান পরীক্ষা</translation>
 <translation id="3183139917765991655">প্রোফাইল আমদানিকারক</translation>
 <translation id="3184560914950696195">$1এ সংরক্ষণ করা যাবে না৷ সম্পাদিত ছবি ডাউনলোডসমূহ ফোল্ডারে সংরক্ষিত হবে৷</translation>
+<translation id="3188257591659621405">আমার ফাইল</translation>
 <translation id="3188465121994729530">সরানোর গড়</translation>
 <translation id="3190558889382726167">পাসওয়ার্ড সংরক্ষিত</translation>
 <translation id="3192947282887913208">অডিও ফাইলসমূহ</translation>
@@ -1511,6 +1519,7 @@
 <translation id="3326821416087822643"><ph name="FILE_NAME" /> জিপ করা হচ্ছে...</translation>
 <translation id="3331321258768829690">(<ph name="UTCOFFSET" />) <ph name="LONGTZNAME" /> (<ph name="EXEMPLARCITY" />)</translation>
 <translation id="3331974543021145906">অ্যাপ্লিকেশানের তথ্য</translation>
+<translation id="3334632933872291866"><ph name="WINDOW_TITLE" /> - ভিডিওটি ছবির-মধ্যে-ছবি মোডে চালানো হচ্ছে</translation>
 <translation id="3335337277364016868">যে বছর রেকর্ড করা হয়েছে</translation>
 <translation id="3335947283844343239">বন্ধ হওয়া ট্যাব আবার খুলুন</translation>
 <translation id="3336664756920573711">আপনার Android ফোন ব্যবহার করে <ph name="DEVICE_TYPE" /> আনলক করুন</translation>
@@ -1530,6 +1539,7 @@
 <translation id="3360297538363969800">প্রিন্ট করা গেল না৷ দয়া করে আপনার মুদ্রকটি পরীক্ষা করে আবার চেষ্টা করুন৷</translation>
 <translation id="3364721542077212959">লেখনী টুল</translation>
 <translation id="3365598184818502391">Ctrl অথবা Alt ব্যবহার করুন</translation>
+<translation id="3367047597842238025">আপনার পছন্দ অনুযায়ী <ph name="DEVICE_TYPE" /> সেট-আপ করুন এবং অসাধারণ সমস্ত বৈশিষ্ট্য উপভোগ করুন।</translation>
 <translation id="3368922792935385530">সংযুক্ত</translation>
 <translation id="3369624026883419694">হোস্ট স্থির করা হচ্ছে...</translation>
 <translation id="337286756654493126">আপনি অ্যাপ্লিকেশানটিতে খোলেন এমন ফোল্ডারগুলি পড়ে</translation>
@@ -1543,6 +1553,7 @@
 <translation id="3389312115541230716">কার্যদণ্ডে <ph name="SMALL_PRODUCT_LOGO" /> আইকনে ডান ক্লিক করুন</translation>
 <translation id="3391716558283801616">ট্যাব ৭</translation>
 <translation id="3396331542604645348">নির্বাচিত প্রিন্টারটি উপলব্ধ নেই বা সঠিকভাবে ইনস্টল হওয়া নেই৷ আপনার প্রিন্টারটি পরীক্ষা করুন বা অন্য একটি প্রিন্টার নির্বাচনের চেষ্টা করুন৷</translation>
+<translation id="3396800784455899911">'গ্রহণ করুন এবং চালিয়ে যান' বোতামে ক্লিক করার অর্থ এই Google পরিষেবাগুলির জন্য উপরোক্ত বর্ণিত প্রক্রিয়াগুলিতে আপনি সম্মতি দেন।</translation>
 <translation id="3399432415385675819">বিজ্ঞপ্তি অক্ষম করা হবে</translation>
 <translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
 <translation id="3404065873681873169">এই সাইটের জন্য কোনও পাসওয়ার্ড সেভ করা হয়নি</translation>
@@ -1771,10 +1782,13 @@
 <translation id="3726463242007121105">এই ডিভাইসটি ফাইল সিস্টেমটি সমর্থিত না হওয়ার কারণে খুলতে পারা যায়না৷</translation>
 <translation id="3727148787322499904">এই সেটিং পরিবর্তন করা হলে শেয়ার করা সব নেটওয়ার্ক প্রভাবিত হবে</translation>
 <translation id="3727187387656390258">পপআপ সংবীক্ষণ</translation>
+<translation id="3729506734996624908">অনুমোদিত সাইট</translation>
 <translation id="3732078975418297900"><ph name="ERROR_LINE" /> নম্বর লাইনে কোনও ভুল আছে</translation>
 <translation id="3733127536501031542">স্টেপ-আপ সহ SSL সার্ভার</translation>
+<translation id="3735740477244556633">এই অনুসারে সাজান</translation>
 <translation id="3737274407993947948">Linux ইনস্টল করার সময় সমস্যা হচ্ছে...</translation>
 <translation id="3737536731758327622">আপনার ডাউনলোডগুলি এখানে দেখা যাবে</translation>
+<translation id="3738671331307774213">আপনার পরিচয় যাচাই করলে তা আপনার ব্যক্তিগত ডেটা রক্ষা করতে সহায়তা করে</translation>
 <translation id="3738924763801731196"><ph name="OID" />:</translation>
 <translation id="3739254215541673094"><ph name="APPLICATION" /> খুলবেন?</translation>
 <translation id="3741158646617793859"><ph name="DEVICE_NAME" /> এখন অ্যাডমিন কনসোলে প্রদর্শিত হবে</translation>
@@ -1858,6 +1872,7 @@
 <translation id="3842552989725514455">Serif হরফ</translation>
 <translation id="385051799172605136">ফিরুন</translation>
 <translation id="3851428669031642514">অনিরাপদ স্ক্রিপ্টগুলি লোড করুন</translation>
+<translation id="3854599674806204102">একটি বিকল্প বেছে নিন</translation>
 <translation id="3855441664322950881">প্যাক এক্সটেনশান</translation>
 <translation id="3855676282923585394">বুকমার্কস এবং সেটিংস আমদানি করুন...</translation>
 <translation id="3856800405688283469">সময় অঞ্চল বেছে নিন</translation>
@@ -2520,6 +2535,7 @@
 <translation id="4955814292505481804">বার্ষিক</translation>
 <translation id="4957949153200969297">শুধুমাত্র <ph name="IDS_SHORT_PRODUCT_NAME" /> সিঙ্ক সম্পর্কিত বৈশিষ্ট্যগুলি চালু করুন</translation>
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation>
+<translation id="4961000125720751066">আপনার সমস্ত কার্ড এক জায়গায় করুন</translation>
 <translation id="496226124210045887">আপনার নির্বাচিত ফোল্ডারে সংবেদনশীল ফাইল রয়েছে৷ "$1" কে এই ফোল্ডারে স্থায়ী পড়ার অ্যাক্সেস মঞ্জুর করার ব্যাপারে আপনি কি নিশ্চিত?</translation>
 <translation id="4964455510556214366">সাজানোর ব্যবস্থা</translation>
 <translation id="4964673849688379040">চেক করা হচ্ছে...</translation>
@@ -2566,6 +2582,7 @@
 <translation id="5027562294707732951">এক্সটেনশান যোগ করুন</translation>
 <translation id="5029568752722684782">প্রতিলিপি সাফ করুন</translation>
 <translation id="5030338702439866405">দ্বারা ইস্যু করা</translation>
+<translation id="503155457707535043">অ্যাপ ডাউনলোড করা হচ্ছে</translation>
 <translation id="503498442187459473"><ph name="HOST" /> আপনার ক্যামেরা ও মাইক্রোফোন ব্যবহার করতে চায়</translation>
 <translation id="5036662165765606524">কোনো সাইটকে স্বয়ংক্রিয়ভাবে একাধিক ফাইল ডাউনলোড করার জন্য মঞ্জুরি দেবেন না</translation>
 <translation id="5037676449506322593">সকল বেছে নিন</translation>
@@ -3078,6 +3095,7 @@
 <translation id="57838592816432529">নিঃশব্দ করুন</translation>
 <translation id="5785583009707899920">Chrome ফাইল ইউটিলিটি</translation>
 <translation id="5787146423283493983">কী চুক্তি</translation>
+<translation id="5788127256798019331">Play ফাইল</translation>
 <translation id="5788367137662787332">দুঃখিত, <ph name="DEVICE_LABEL" /> ডিভাইসটির কমপক্ষে একটি ভাগ আটকানো যায়নি৷</translation>
 <translation id="5794414402486823030">সর্বদা সিস্টেম নিরীক্ষকের সাথে খুলুন</translation>
 <translation id="5794786537412027208">সব Chrome অ্যাপ্লিকেশান বন্ধ করুন</translation>
@@ -3327,6 +3345,7 @@
 <translation id="6178664161104547336">একটি শংসাপত্র বেছে নিন</translation>
 <translation id="6181431612547969857">ডাউনলোড অবরুদ্ধ রয়েছে</translation>
 <translation id="6185132558746749656">ডিভাইসের লোকেশন</translation>
+<translation id="6185617499004995178">CUPS IPP যাচাইকারী</translation>
 <translation id="6185696379715117369">পৃষ্ঠায় উপরের দিকে যান</translation>
 <translation id="6189273858858366896">নেটওয়ার্ক ফাইল শেয়ার সেট-আপ বা পরিচালনা করুন।</translation>
 <translation id="6189412234224385711"><ph name="EXTENSION_NAME" /> এর মাধ্যমে খুলুন</translation>
@@ -3359,6 +3378,7 @@
 <translation id="6231881193380278751">পৃষ্ঠাটি অটো-রিফ্রেশ করতে URL এ কোনো ক্যোয়ারী পারাম যোগ করুন: chrome://device-log/?refresh=&lt;sec&gt;</translation>
 <translation id="6232017090690406397">ব্যাটারি: %</translation>
 <translation id="6232116551750539448"><ph name="NAME" /> এর সাথে সংযোগ বিচ্ছিন্ন হয়েছে</translation>
+<translation id="6235700927623181151">এই ট্যাবটি আপনার ডেস্কটপ কন্টেন্ট শেয়ার করছে।</translation>
 <translation id="6237816943013845465">আপনাকে আপনার স্ক্রিন রেজোলিউশন পরিবর্তন করতে অনুমতি দেয়</translation>
 <translation id="6238923052227198598">লেটেস্ট নোটটি লক স্ক্রিনে রাখুন</translation>
 <translation id="6239558157302047471">আবার লোড করার &amp;ফ্রেম</translation>
@@ -3501,6 +3521,7 @@
 <translation id="6451180435462401570">ক্লাউড প্রিন্ট ডিভাইস পরিচালনা করুন</translation>
 <translation id="6451689256222386810">আপনি যদি আপনার পাসফ্রেজ ভুলে যান বা এই সেটিং পরিবর্তন করতে চান, তাহলে <ph name="BEGIN_LINK" />সিঙ্ক পুনরায় সেট করুন<ph name="END_LINK" />।</translation>
 <translation id="6452181791372256707">প্রত্যাখ্যান</translation>
+<translation id="6455264371803474013">নির্দিষ্ট সাইটগুলিতে</translation>
 <translation id="6455894534188563617">&amp;নতুন ফোল্ডার</translation>
 <translation id="6456394469623773452">ভাল</translation>
 <translation id="6456631036739229488">Smart Lock ফোন পরিবর্তিত হয়েছে। Smart Lock আপডেট করতে আপনার পাসওয়ার্ড লিখুন। পরের বার আপনার ফোন আপনার <ph name="DEVICE_TYPE" /> আনলক করবে। সেটিংসে গিয়ে Smart Lock বন্ধ করুন।</translation>
@@ -3578,6 +3599,7 @@
 <translation id="657402800789773160">&amp;Reload This Page</translation>
 <translation id="6577284282025554716">ডাউনলোড বাতিল হয়েছে: <ph name="FILE_NAME" /></translation>
 <translation id="6578664922716508575">আপনার Google ইউজারনেম ও পাসওয়ার্ড দিয়ে সিঙ্ক করা পাসওয়ার্ডগুলি এনক্রিপ্ট করুন</translation>
+<translation id="6579705087617859690"><ph name="WINDOW_TITLE" /> - ডেস্কটপ কন্টেন্ট শেয়ার করেছে</translation>
 <translation id="6580151766480067746">ARC সংস্করণ</translation>
 <translation id="6581162200855843583">Google ড্রাইভ লিঙ্ক</translation>
 <translation id="6582421931165117398">আপনার ব্যক্তিগত তথ্য রক্ষা করতে, এখনই এখনই আপনার পাসওয়ার্ড পরিবর্তন করুন। আপনার পাসওয়ার্ড পরিবর্তন করার আগে, আপনাকে সাইন ইন করতে বলা হবে।</translation>
@@ -4043,6 +4065,7 @@
 <translation id="730289542559375723">{NUM_APPLICATIONS,plural, =1{এই অ্যাপ্লিকেশনটি Chrome-কে সঠিকভাবে কাজ করতে বাধা দিতে পারে।}one{এই অ্যাপ্লিকেশনগুলি Chrome-কে সঠিকভাবে কাজ করতে বাধা দিতে পারে।}other{এই অ্যাপ্লিকেশনগুলি Chrome-কে সঠিকভাবে কাজ করতে বাধা দিতে পারে।}}</translation>
 <translation id="7303900363563182677">ক্লিপবোর্ডে কপি করা টেক্সট এবং ছবি দেখা থেকে এই সাইটটিকে ব্লক করা হয়েছে</translation>
 <translation id="730515362922783851">স্থানীয় নেটওয়ার্ক বা ইন্টারনেটে যে কোনো ডিভাইসের সাথে ডেটা বিনিময় করুন</translation>
+<translation id="7307129035224081534">থামানো হয়েছে</translation>
 <translation id="7308002049209013926">নতুন অ্যাপ এবং কার্যকলাপগুলি দ্রুত চালু করতে লঞ্চার ব্যবহার করুন। কীবোর্ডের সাহায্যে এখানে পেতে Alt + Shift + L বোতামটি টিপুন।</translation>
 <translation id="7309257895202129721">&amp;নিয়ন্ত্রণগুলি দেখান</translation>
 <translation id="7310598146671372464">লগ-ইন করা সম্ভব হয়নি। সার্ভারটি নির্দিষ্ট Kerberos এনক্রিপশনের ধরনগুলি সমর্থন করে না। আপনার অ্যাডমিনিস্ট্রেটরের সাথে যোগাযোগ করুন।</translation>
@@ -4132,6 +4155,7 @@
 <translation id="7465778193084373987">Netscape শংসাপত্র রদকরণ  URL</translation>
 <translation id="7469894403370665791">স্বয়ংক্রিয়ভাবে এই নেটওয়ার্কে সংযোগ করুন</translation>
 <translation id="747114903913869239">ত্রুটি: এক্সটেনশানের অর্থোদ্ধার করতে ব্যর্থ</translation>
+<translation id="7473753388963818366">আপনার জন্য <ph name="DEVICE_TYPE" /> তৈরি করা যাক।</translation>
 <translation id="7473891865547856676">না থাক</translation>
 <translation id="747459581954555080">সকল পুনরুদ্ধার করুন</translation>
 <translation id="7475671414023905704">Netscape পাসওয়ার্ড URL হারিয়েছে</translation>
@@ -4256,6 +4280,7 @@
 <translation id="7665369617277396874">অ্যাকাউন্ট যোগ করুন</translation>
 <translation id="7671130400130574146">সিস্টেম শিরোনাম দণ্ড ও সীমানাগুলি ব্যবহার করুন</translation>
 <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> এ।</translation>
+<translation id="7676867886086876795">যেকোনও টেক্সট ক্ষেত্রে ডিকটেশনের অনুমতি দেওয়ার জন্য Google-কে আপনার ভয়েস পাঠান।</translation>
 <translation id="7681095912841365527">সাইটটি ব্লুটুথ ব্যবহার করতে পারে</translation>
 <translation id="7683373461016844951">চালিয়ে যেতে 'ঠিক আছে' বোতামে ক্লিক করুন, তারপর আপনার <ph name="DOMAIN" /> ইমেল আইডির জন্য নতুন প্রোফাইল তৈরি করতে 'কাউকে যোগ করুন' বোতামে ক্লিক করুন।</translation>
 <translation id="7684212569183643648">আপনার প্রশাসক দ্বারা ইনস্টল করা হয়েছে</translation>
@@ -4296,6 +4321,7 @@
 <translation id="7740996059027112821">মানক</translation>
 <translation id="7748528009589593815">পূর্ববর্তী ট্যাব</translation>
 <translation id="7748626145866214022">অ্যাকশন বারেও আরও বিকল্প উপলভ্য। অ্যাকশন বারে ফোকাস করতে Alt + A প্রেস করুন।</translation>
+<translation id="7750228210027921155">ছবির-মধ্যে-ছবি</translation>
 <translation id="7751260505918304024">সকল দেখান</translation>
 <translation id="7754704193130578113">প্রতিটি ফাইল ডাউনলোড করার আগে তা কোথায় সংরক্ষণ করতে হবে জিজ্ঞাসা করুন</translation>
 <translation id="7758143121000533418">Family Link</translation>
@@ -4403,6 +4429,7 @@
 <translation id="7857949311770343000">আপনি কি এই পৃষ্ঠাটিকে নতুন ট্যাব পৃষ্ঠা হিসাবে আশা করছিলেন?</translation>
 <translation id="786073089922909430">পরিষেবা: <ph name="ARC_PROCESS_NAME" /></translation>
 <translation id="7861215335140947162">&amp;ডাউনলোড করা</translation>
+<translation id="7868378670806575181">{NUM_COOKIES,plural, =1{১টি কুকি}one{#টি কুকি}other{#টি কুকি}}</translation>
 <translation id="786957569166715433"><ph name="DEVICE_NAME" /> - যুক্ত করা হয়েছে</translation>
 <translation id="7870730066603611552">সেট-আপের পর সিঙ্কের বিকল্পগুলির রিভিউ</translation>
 <translation id="7870790288828963061">এর থেকে আরও নতুন সংস্করণের ওনো কিয়স্ক অ্যাপ্লিকেশান পাওয়া যায়নি৷ দয়া করে USB স্টিক সরান৷</translation>
@@ -4722,6 +4749,7 @@
 <translation id="8373553483208508744">ট্যাবগুলি নিঃশব্দ করুন</translation>
 <translation id="8382913212082956454">&amp;ইমেল ঠিকানা কপি করুন</translation>
 <translation id="8386903983509584791">স্ক্যান করা সম্পন্ন হয়েছে</translation>
+<translation id="8389492867173948260">আপনার দেখা ওয়েবসাইটে আপনার সমস্ত ডেটা পড়ার এবং পরিবর্তন করার জন্য এই এক্সটেনশনটিকে অনুমতি দিন:</translation>
 <translation id="8390449457866780408">সার্ভার অনুপলব্ধ৷</translation>
 <translation id="8391712576156218334">ইমেজ এখন উপলভ্য নয়। পরে আবার চেষ্টা করুন।</translation>
 <translation id="8392234662362215700">কীবোর্ড লেআউট স্যুইচ করতে Control-Shift-Space</translation>
@@ -4753,6 +4781,7 @@
 <translation id="84297032718407999">আপনি <ph name="LOGOUT_TIME_LEFT" />-এ সাইন-আউট হয়ে যাবেন</translation>
 <translation id="8431909052837336408">সিম পিন পরিবর্তন করুন</translation>
 <translation id="8434480141477525001">NaCl ত্রুটিমুক্ত পোর্ট</translation>
+<translation id="8435395510592618362"><ph name="APP_NAME" /> ব্যবহার করে আপনার পরিচয় যাচাই করুন</translation>
 <translation id="843760761634048214">ক্রেডিট কার্ড সেভ করুন</translation>
 <translation id="8438328416656800239">একটি স্মার্ট ব্রাউজারে স্যুইচ করুন</translation>
 <translation id="8439506636278576865">এই ভাষাতে পৃষ্ঠাগুলি অনুবাদ করার প্রস্তাব করে</translation>
@@ -4778,6 +4807,7 @@
 <translation id="8465252176946159372">বৈধ না</translation>
 <translation id="8465444703385715657"><ph name="PLUGIN_NAME" /> চালানোর জন্য আপনার অনুমতি প্রয়োজন</translation>
 <translation id="8466234950814670489">Tar আর্কাইভ</translation>
+<translation id="8466417995783206254">এই ট্যাবটি ছবির-মধ্যে-ছবি মোডে ভিডিওটি চালাচ্ছে।</translation>
 <translation id="8468750959626135884">আপনার Android ফোন দিয়ে আপনার <ph name="DEVICE_TYPE" /> আনলক করুন।</translation>
 <translation id="8470028084415844044">সব ডিভাইসে আপনার পাসওয়ার্ড পেতে, সিঙ্ক চালু করুন।</translation>
 <translation id="8470513973197838199"><ph name="ORIGIN" /> এর জন্য সেভ করা পাসওয়ার্ডগুলি</translation>
@@ -4798,6 +4828,7 @@
 <translation id="8496717697661868878">এই প্লাগ ইনটি চালান</translation>
 <translation id="8497219075884839166">Windows ইউটিলিটি</translation>
 <translation id="8498214519255567734">এটি ব্যবহার করলে আপনি কম আলোতেও স্বচ্ছন্দে স্ক্রিনের দিকে তাকাতে বা পড়তে পারবেন</translation>
+<translation id="8498395510292172881">Chrome-এ পড়া চালিয়ে যান</translation>
 <translation id="8503813439785031346">ইউজারনেম</translation>
 <translation id="850875081535031620">কোনও ক্ষতিকর সফ্টওয়্যার খুঁজে পাওয়া যায়নি</translation>
 <translation id="8509646642152301857">বানান পরীক্ষক অভিধান ডাউনলোড ব্যর্থ হয়েছে৷</translation>
@@ -5137,6 +5168,7 @@
 <translation id="9027459031423301635">নতুন &amp;ট্যাবে লিঙ্ক খুলুন</translation>
 <translation id="9030515284705930323">আপনার প্রতিষ্ঠান আপনার অ্যাকাউন্টের জন্য Google Play স্টোর সক্ষম করেনি। আরও তথ্যের জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন।</translation>
 <translation id="9033857511263905942">&amp;প্রতিলেপন</translation>
+<translation id="9034924485347205037">Linux ফাইল</translation>
 <translation id="9035012421917565900">আইটেমগুলিকে '<ph name="DESTINATION_NAME" />' এ ফিরিয়ে নেওয়া যাবে না, তাই আপনি এই কাজটি আর পূর্বাবস্থায় ফেরাতে পারবেন না।</translation>
 <translation id="9037008143807155145">https://www.google.com/calendar/render?cid=%s</translation>
 <translation id="9037965129289936994">প্রকৃত রূপ দেখান</translation>
@@ -5237,6 +5269,7 @@
 <translation id="9173995187295789444">ব্লুটুথ ডিভাইসগুলির জন্য স্ক্যান করা হচ্ছে...</translation>
 <translation id="9176611096776448349"><ph name="WINDOW_TITLE" /> - ব্লুটুথ ডিভাইস সংযুক্ত হয়েছে</translation>
 <translation id="9177499212658576372">আপনি বর্তমানে <ph name="NETWORK_TYPE" /> নেটওয়ার্কের সাথে সংযুক্ত৷</translation>
+<translation id="9179734824669616955">আপনার <ph name="DEVICE_TYPE" />-এ Linux (বিটা) সেট-আপ করুন</translation>
 <translation id="9180281769944411366">এতে কয়েক মিনিট সময় লাগতে পারে। Linux কন্টেনার শুরু করা হচ্ছে।</translation>
 <translation id="9180380851667544951">সাইটটি আপনার স্ক্রিন শেয়ার করতে পারে</translation>
 <translation id="9188441292293901223">এই <ph name="DEVICE_TYPE" /> আনলক করতে দয়া করে আপনার ফোনকে একটি আরও নতুন সংস্করণের Android এ আপডেট করুন৷</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index ad70a022..c7cea0e 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -96,7 +96,7 @@
 <translation id="1145292499998999162">Plug-in blockiert</translation>
 <translation id="1145532888383813076">Durchsuchen Sie Ihr Gerät, Ihre Apps und das Web.</translation>
 <translation id="1146204723345436916">Lesezeichen aus HTML-Datei importieren...</translation>
-<translation id="114721135501989771">Chrome intelligent nutzen mit Google</translation>
+<translation id="114721135501989771">Chrome cleverer nutzen – dank Google</translation>
 <translation id="1148097584170732637"><ph name="FILE_COUNT" /> gefunden.
     <ph name="LINE_BREAK1" />
     Nicht genügend Platz im lokalen Speicher. Zusätzlich <ph name="FILE_SIZE" /> erforderlich.
@@ -188,7 +188,7 @@
 <translation id="1260451001046713751">Pop-ups und Weiterleitungen von <ph name="HOST" /> immer zulassen</translation>
 <translation id="126710816202626562">Zielsprache:</translation>
 <translation id="126768002343224824">16-fach</translation>
-<translation id="127138278192656016">Synchronisierung und alle Dienste verwenden</translation>
+<translation id="127138278192656016">Synchronisierung und alle Dienste nutzen</translation>
 <translation id="1272079795634619415">Stopp</translation>
 <translation id="1272242203003205253">Google-Partner arbeiten mit Assistant zusammen, um Ihnen im Alltag zu helfen</translation>
 <translation id="1272978324304772054">Dieses Nutzerkonto gehört nicht zu der Domain, in der das Gerät angemeldet ist. Wenn Sie sich in einer anderen Domain anmelden möchten, müssen Sie zunächst eine Gerätewiederherstellung durchführen.</translation>
@@ -248,7 +248,7 @@
 <translation id="1367951781824006909">Datei auswählen</translation>
 <translation id="1368265273904755308">Problem melden</translation>
 <translation id="1370553626198299309">Das Chromebook muss mit dem Internet verbunden und die Bluetooth-Funktion des Smartphones an sein</translation>
-<translation id="1371301976177520732">Lesezeichen, Passwörter, der Verlauf und andere Inhalte auf allen Ihren Geräten</translation>
+<translation id="1371301976177520732">Lesezeichen, Passwörter, der Verlauf und andere Funktionen auf all Ihren Geräten</translation>
 <translation id="1372681413396468867">{NUM_ITEMS,plural, =1{1 zu entfernendes Element}other{# zu entfernende Elemente}}</translation>
 <translation id="1372841398847029212">Mit meinem Konto synchronisieren</translation>
 <translation id="1374844444528092021">Das vom Netzwerk "<ph name="NETWORK_NAME" />" benötigte Zertifikat ist entweder nicht installiert oder nicht mehr gültig. Bitte fordern Sie ein neues Zertifikat an und versuchen Sie es erneut.</translation>
@@ -1766,7 +1766,7 @@
 <translation id="3688507211863392146">In Dateien und Ordner schreiben, die Sie in der Anwendung öffnen</translation>
 <translation id="3688526734140524629">Kanal ändern</translation>
 <translation id="3688578402379768763">Auf dem neusten Stand</translation>
-<translation id="3691214267321877444">Zahlungsmethoden und Adressen mit Google Pay.</translation>
+<translation id="3691214267321877444">Zahlungsmethoden und Adressen bei Google Pay.</translation>
 <translation id="3691231116639905343">Tastatur-Apps</translation>
 <translation id="3691267899302886494"><ph name="HOST" /> möchte Ihren Bildschirm freigeben</translation>
 <translation id="3693415264595406141">Passwort:</translation>
@@ -2237,7 +2237,7 @@
 <translation id="4462159676511157176">Benutzerdefinierte Nameserver</translation>
 <translation id="4467100756425880649">Chrome Web Store-Galerie</translation>
 <translation id="4467101674048705704"><ph name="FOLDER_NAME" /> maximieren</translation>
-<translation id="447252321002412580">Ich möchte dabei helfen, die Funktionen und die Leistung von Chrome zu verbessern</translation>
+<translation id="447252321002412580">Helfen, die Funktionen und die Leistung von Chrome zu verbessern</translation>
 <translation id="4472575034687746823">Jetzt starten</translation>
 <translation id="4474155171896946103">Alle Tabs als Lesezeichen speichern...</translation>
 <translation id="4475552974751346499">In Downloads suchen</translation>
@@ -4124,7 +4124,7 @@
 <translation id="7366415735885268578">Website hinzufügen</translation>
 <translation id="7366909168761621528">Browserdaten</translation>
 <translation id="7371006317849674875">Startzeit</translation>
-<translation id="737439367876257440">Verbessern Sie Chrome und die Sicherheit, indem Sie System- und Nutzungsdaten an Google senden</translation>
+<translation id="737439367876257440">System- und Nutzungsdaten an Google senden, um Chrome noch besser und sicherer zu machen</translation>
 <translation id="7374989181012106167">Ihr Chromebook wird noch besser, wenn Sie Ihr Smartphone damit verbinden. <ph name="LINK_BEGIN" />Weitere Informationen<ph name="LINK_END" /></translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7376553024552204454">Mauszeiger bei Bewegung hervorheben</translation>
@@ -5050,7 +5050,7 @@
 <translation id="8784626084144195648">Gruppendurchschnitt</translation>
 <translation id="8785622406424941542">Eingabestift</translation>
 <translation id="8787254343425541995">Proxys für freigegebene Netzwerke zulassen</translation>
-<translation id="8791534160414513928">Mit Browserzugriffen eine "Do Not Track"-Anforderung senden</translation>
+<translation id="8791534160414513928">Bei Browserzugriffen eine "Do Not Track"-Anforderung mitsenden</translation>
 <translation id="8794025342371547160">IP eingeschränkt</translation>
 <translation id="879413103056696865">Während der Hotspot aktiviert ist, wird Ihr <ph name="PHONE_NAME" /> Folgendes tun:</translation>
 <translation id="8795916974678578410">Neues Fenster</translation>
@@ -5165,7 +5165,7 @@
 <translation id="8978154919215542464">An – alles synchronisieren</translation>
 <translation id="897939795688207351">Auf <ph name="ORIGIN" /></translation>
 <translation id="8980951173413349704"><ph name="WINDOW_TITLE" /> – abgestürzt</translation>
-<translation id="8983677657449185470">Ich möchte bei der Optimierung von Safe Browsing helfen</translation>
+<translation id="8983677657449185470">Bei der Optimierung von Safe Browsing helfen</translation>
 <translation id="8984654317541110628">Dateifreigabe-URL</translation>
 <translation id="8984872292925913496">Sie finden die sechsstellige PIN auf der Rückseite Ihres Schlüssels</translation>
 <translation id="8986362086234534611">Entfernen</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index 2bf333a..32d467e7 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -96,7 +96,7 @@
 <translation id="1145292499998999162">Complemento bloqueado</translation>
 <translation id="1145532888383813076">Busca en tu dispositivo, la Web y las apps.</translation>
 <translation id="1146204723345436916">Importar favoritos de un archivo HTML...</translation>
-<translation id="114721135501989771">Obtener las funciones inteligentes de Google en Chrome</translation>
+<translation id="114721135501989771">Obtén las mejores funciones de Google en Chrome</translation>
 <translation id="1148097584170732637">Se encontró un total de <ph name="FILE_COUNT" />.
     <ph name="LINE_BREAK1" />
     No hay suficiente espacio en el almacenamiento local. Se necesita un espacio adicional de <ph name="FILE_SIZE" />.
@@ -248,7 +248,7 @@
 <translation id="1367951781824006909">Selecciona un archivo</translation>
 <translation id="1368265273904755308">Informar un problema</translation>
 <translation id="1370553626198299309">Asegúrate de que tu Chromebook esté conectada a Internet y la conexión Bluetooth del teléfono esté activada</translation>
-<translation id="1371301976177520732">Tus favoritos, contraseñas, historial y más en todos tus dispositivos</translation>
+<translation id="1371301976177520732">Tus favoritos, las contraseñas, el historial y mucho más en todos tus dispositivos</translation>
 <translation id="1372681413396468867">{NUM_ITEMS,plural, =1{Se quitará 1 elemento}other{Se quitarán # elementos}}</translation>
 <translation id="1372841398847029212">Sincronizar con tu cuenta</translation>
 <translation id="1374844444528092021">El certificado que requiere la red "<ph name="NETWORK_NAME" />" no está instalado o ya no es válido. Obtén un nuevo certificado e intenta volver a conectarte.</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index af48259..65bb50f 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -96,7 +96,7 @@
 <translation id="1145292499998999162">Plugin diblokir</translation>
 <translation id="1145532888383813076">Telusuri perangkat, aplikasi, dan web.</translation>
 <translation id="1146204723345436916">Impor bookmark dari file HTML...</translation>
-<translation id="114721135501989771">Dapatkan perangkat smart Google di Chrome</translation>
+<translation id="114721135501989771">Dapatkan kecanggihan Google di Chrome</translation>
 <translation id="1148097584170732637"><ph name="FILE_COUNT" /> ditemukan.
     <ph name="LINE_BREAK1" />
     Tidak cukup ruang yang tersedia di penyimpanan lokal. Perlu tambahan <ph name="FILE_SIZE" />.
@@ -188,7 +188,7 @@
 <translation id="1260451001046713751">Selalu izinkan pop-up dan pengalihan dari <ph name="HOST" /></translation>
 <translation id="126710816202626562">Bahasa terjemahan:</translation>
 <translation id="126768002343224824">16x</translation>
-<translation id="127138278192656016">Menggunakan sinkronisasi dan semua layanan</translation>
+<translation id="127138278192656016">Gunakan sinkronisasi dan semua layanan</translation>
 <translation id="1272079795634619415">Berhenti</translation>
 <translation id="1272242203003205253">Google Partners berfungsi dengan Asisten untuk membantu Anda</translation>
 <translation id="1272978324304772054">Akun pengguna ini tidak berada di domain tempat perangkat mendaftar.  Jika Anda ingin mendaftar ke domain lain, Anda perlu melakukan pemulihan perangkat terlebih dulu.</translation>
@@ -418,7 +418,7 @@
 <translation id="1616298854599875024">Tidak dapat mengimpor ekstensi "<ph name="IMPORT_NAME" />" karena bukan modul yang dibagikan</translation>
 <translation id="161707228174452095">Sidik jari ditambahkan!</translation>
 <translation id="1618268899808219593">Pusat Bantuan</translation>
-<translation id="162035744160882748">Mengaktifkan sinkronisasi, personalisasi, dan layanan Google lainnya</translation>
+<translation id="162035744160882748">Aktifkan sinkronisasi, personalisasi, dan layanan Google lainnya</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1624026626836496796">Hal ini hanya akan terjadi sekali, dan kredensial Anda tidak akan disimpan.</translation>
 <translation id="1627276047960621195">Deskriptor File</translation>
@@ -625,7 +625,7 @@
 <translation id="1919345977826869612">Iklan</translation>
 <translation id="1919814239594435008">Plugin yang tidak dimasukkan sandbox diizinkan</translation>
 <translation id="1921584744613111023"><ph name="DPI" /> dpi</translation>
-<translation id="1924559387127953748">Dapatkan perangkat smart Google di <ph name="IDS_SHORT_PRODUCT_NAME" /></translation>
+<translation id="1924559387127953748">Dapatkan kecanggihan Google di <ph name="IDS_SHORT_PRODUCT_NAME" /></translation>
 <translation id="192494336144674234">Buka dengan</translation>
 <translation id="1925021887439448749">Masukkan alamat web khusus</translation>
 <translation id="1926339101652878330">Setelan ini dikontrol oleh kebijakan perusahaan. Hubungi administrator Anda untuk informasi selengkapnya.</translation>
@@ -3707,7 +3707,7 @@
 <translation id="6690565918367819723"><ph name="PROFILE_NAME" /> Beralih orang</translation>
 <translation id="6690659332373509948">Tidak dapat mengurai file: <ph name="FILE_NAME" /></translation>
 <translation id="6690751852586194791">Pilih pengguna yang dilindungi untuk ditambahkan ke perangkat ini.</translation>
-<translation id="6691331417640343772">Mengelola data yang disinkronkan pada Google Dasbor</translation>
+<translation id="6691331417640343772">Kelola data yang disinkronkan pada Google Dasbor</translation>
 <translation id="6691936601825168937">&amp;Maju</translation>
 <translation id="6697492270171225480">Tampilkan saran untuk halaman yang serupa jika halaman tidak dapat ditemukan</translation>
 <translation id="6698810901424468597">Membaca dan mengubah data Anda di <ph name="WEBSITE_1" /> dan <ph name="WEBSITE_2" /></translation>
@@ -3804,7 +3804,7 @@
 <translation id="6841186874966388268">Kesalahan</translation>
 <translation id="6843725295806269523">bisukan</translation>
 <translation id="6845038076637626672">Buka yang Dimaksimalkan</translation>
-<translation id="685040365210406336">Tidak melakukan perubahan</translation>
+<translation id="685040365210406336">Jangan lakukan perubahan</translation>
 <translation id="6851497530878285708">Aplikasi Diaktifkan</translation>
 <translation id="6853388645642883916">Updater dalam mode tidur</translation>
 <translation id="68541483639528434">Tutup tab lain</translation>
@@ -4324,7 +4324,7 @@
 <translation id="7701869757853594372">Penangan PENGGUNA</translation>
 <translation id="7702907602086592255">Domain</translation>
 <translation id="7704305437604973648">Tugas</translation>
-<translation id="7704317875155739195">Melengkapi otomatis penelusuran dan URL</translation>
+<translation id="7704317875155739195">Lengkapi otomatis penelusuran dan URL</translation>
 <translation id="7704521324619958564">Buka Play Store</translation>
 <translation id="7705276765467986571">Tidak dapat memuat model bookmark.</translation>
 <translation id="7705524343798198388">VPN</translation>
@@ -4544,7 +4544,7 @@
 <translation id="7982789257301363584">Jaringan</translation>
 <translation id="7984068253310542383">Cerminkan <ph name="DISPLAY_NAME" /></translation>
 <translation id="7986295104073916105">Membaca dan mengubah setelan sandi yang tersimpan</translation>
-<translation id="7987764905897278458">Dapatkan perangkat smart Google lainnya</translation>
+<translation id="7987764905897278458">Dapatkan kecanggihan Google lainnya</translation>
 <translation id="7988355189918024273">Aktifkan fitur aksesibilitas</translation>
 <translation id="7994702968232966508">Metode EAP</translation>
 <translation id="799547531016638432">Hapus pintasan</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 8e7781182..848d66f 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -2093,7 +2093,7 @@
 <translation id="4181602000363099176">20 倍</translation>
 <translation id="4181841719683918333">言語</translation>
 <translation id="4184885522552335684">ディスプレイをドラッグして移動</translation>
-<translation id="4192273449750167573">次の画面で設定を確認</translation>
+<translation id="4192273449750167573">次の画面で設定を確認する</translation>
 <translation id="4193154014135846272">Google ドキュメント</translation>
 <translation id="4194570336751258953">タップによるクリックを有効にする</translation>
 <translation id="4195643157523330669">新しいタブで開く</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index 6a4b516e..6a5810e6 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -96,7 +96,7 @@
 <translation id="1145292499998999162">Plug-in bloqueado</translation>
 <translation id="1145532888383813076">Pesquisar seu dispositivo, apps e Web.</translation>
 <translation id="1146204723345436916">Importar favoritos de arquivo HTML...</translation>
-<translation id="114721135501989771">Use a tecnologia do Google no Chrome</translation>
+<translation id="114721135501989771">A tecnologia Google no Chrome</translation>
 <translation id="1148097584170732637">Arquivos encontrados: <ph name="FILE_COUNT" />.
     <ph name="LINE_BREAK1" />
     Não há espaço suficiente disponível no armazenamento local. Você precisa de espaço adicional: <ph name="FILE_SIZE" />.
@@ -599,7 +599,7 @@
 <translation id="1875312262568496299">Começar</translation>
 <translation id="1875387611427697908">Esse item só por ser adicionado a partir da <ph name="CHROME_WEB_STORE" /></translation>
 <translation id="1877520246462554164">Falha ao receber o token de autenticação. Saia e faça login novamente para tentar mais uma vez.</translation>
-<translation id="1878302395768190018">Você pode personalizar isso a qualquer momento nas configurações do Chrome</translation>
+<translation id="1878302395768190018">Você pode alterar isso a qualquer momento nas configurações do Chrome</translation>
 <translation id="1880905663253319515">Tem certeza que deseja excluir o certificado "<ph name="CERTIFICATE_NAME" />"?</translation>
 <translation id="1886996562706621347">Permitir que os sites peçam para se tornar manipuladores padrão de protocolos (recomendado)</translation>
 <translation id="1887442540531652736">Erro de login</translation>
@@ -720,7 +720,7 @@
 <translation id="2085470240340828803">Já existe um arquivo chamado "<ph name="FILENAME" />". O que você quer fazer?</translation>
 <translation id="2085483813371386023">Acesse <ph name="LINK_BEGIN" />Configurações<ph name="LINK_END" /> para ver suas opções do "Better Together"</translation>
 <translation id="208586643495776849">Tente novamente</translation>
-<translation id="2087822576218954668">Impressão: <ph name="PRINT_NAME" /></translation>
+<translation id="2087822576218954668">Imprimir: <ph name="PRINT_NAME" /></translation>
 <translation id="2089566709556890888">Navegue com segurança com o Google Chrome</translation>
 <translation id="2089795179672254991">Perguntar quando um site quiser ver os textos e imagens copiados para a área de transferência (recomendado)</translation>
 <translation id="2090165459409185032">Para recuperar informações da sua conta, acesse: google.com.br/accounts/recovery</translation>
@@ -1612,7 +1612,7 @@
 <translation id="3453612417627951340">Requer autorização</translation>
 <translation id="3454157711543303649">Ativação concluída</translation>
 <translation id="345693547134384690">Abrir &amp;imagem em uma nova guia</translation>
-<translation id="3459509316159669723">Impressão</translation>
+<translation id="3459509316159669723">Imprimir</translation>
 <translation id="3459697287128633276">Para ativar sua conta para acessar a Google Play Store, autentique com seu Provedor de identidade.</translation>
 <translation id="3459774175445953971">Última modificação:</translation>
 <translation id="3461266716147554923"><ph name="URL" /> quer ver os textos e imagens copiados para a área de transferência</translation>
@@ -2075,7 +2075,7 @@
 <translation id="4144218403971135344">Tenha uma melhor qualidade de vídeo e economize bateria. Os vídeos serão reproduzidos apenas na tela compatível com Cast.</translation>
 <translation id="414599683948988413">Usar sua chave de segurança com o USB</translation>
 <translation id="4146026355784316281">Sempre abrir com visualizador do sistema</translation>
-<translation id="4146785383423576110">Redefina e limpe</translation>
+<translation id="4146785383423576110">Redefinir e limpar</translation>
 <translation id="4147897805161313378">Google Fotos</translation>
 <translation id="4150201353443180367">Exibição</translation>
 <translation id="4152670763139331043">{NUM_TABS,plural, =1{1 guia}one{# guias}other{# guias}}</translation>
@@ -2093,7 +2093,7 @@
 <translation id="4181602000363099176">20x</translation>
 <translation id="4181841719683918333">Idiomas</translation>
 <translation id="4184885522552335684">Arraste para mover uma tela</translation>
-<translation id="4192273449750167573">Revise suas configurações na próxima tela</translation>
+<translation id="4192273449750167573">Revisar as configurações na próxima tela</translation>
 <translation id="4193154014135846272">Documento do Google</translation>
 <translation id="4194570336751258953">Ativar toque para clicar</translation>
 <translation id="4195643157523330669">Abrir em uma nova guia</translation>
@@ -2214,7 +2214,7 @@
 <translation id="4415748029120993980">Curva elíptica SECG secp384r1 (também conhecida como NIST P-384)</translation>
 <translation id="4416582610654027550">Digite um URL válido</translation>
 <translation id="4419409365248380979">Sempre permitir que <ph name="HOST" /> configure cookies</translation>
-<translation id="4419556793104466535">Controlar sincronização, personalização e muito mais</translation>
+<translation id="4419556793104466535">Controle a sincronização, personalização e muito mais</translation>
 <translation id="4421932782753506458">Pelúcia</translation>
 <translation id="4422347585044846479">Editar favorito para esta página</translation>
 <translation id="4423376891418188461">Restaurar configurações</translation>
@@ -3941,7 +3941,7 @@
 <translation id="7072010813301522126">Nome do atalho</translation>
 <translation id="707392107419594760">Selecione seu teclado:</translation>
 <translation id="7075513071073410194">PKCS #1 MD5 com criptografia RSA</translation>
-<translation id="7075625805486468288">Gerencie configurações e certificados HTTPS/SSL</translation>
+<translation id="7075625805486468288">Gerencia configurações e certificados HTTPS/SSL</translation>
 <translation id="7076293881109082629">Como fazer login</translation>
 <translation id="7077829361966535409">Houve uma falha no carregamento da página de login usando as configurações de proxy atuais. <ph name="GAIA_RELOAD_LINK_START" />Tente fazer login novamente<ph name="GAIA_RELOAD_LINK_END" /> ou use <ph name="PROXY_SETTINGS_LINK_START" />configurações de proxy<ph name="PROXY_SETTINGS_LINK_END" /> diferentes.</translation>
 <translation id="7078120482318506217">Todas as redes</translation>
@@ -4130,7 +4130,7 @@
 <translation id="7366415735885268578">Adicionar um site</translation>
 <translation id="7366909168761621528">Dados de navegação</translation>
 <translation id="7371006317849674875">Horário de início</translation>
-<translation id="737439367876257440">Aprimore o Chrome e a segurança dele enviando informações de uso e do sistema para o Google</translation>
+<translation id="737439367876257440">Ajude a aprimorar o Chrome e a segurança do app enviando informações de uso e do sistema para o Google</translation>
 <translation id="7374989181012106167">O Chromebook funciona ainda melhor com seu smartphone. <ph name="LINK_BEGIN" />Saiba mais<ph name="LINK_END" />.</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7376553024552204454">Destacar o cursor do mouse quando ele estiver se movendo</translation>
@@ -4570,7 +4570,7 @@
 <translation id="8016266267177410919">Armazenamento temporário</translation>
 <translation id="8017335670460187064"><ph name="LABEL" /></translation>
 <translation id="8017679124341497925">Atalho editado</translation>
-<translation id="8018313076035239964">Controle quais informações os websites podem usar e quais conteúdos eles podem mostrar</translation>
+<translation id="8018313076035239964">Controla quais informações os sites podem usar e quais conteúdos eles podem mostrar</translation>
 <translation id="8023801379949507775">Atualizar extensões agora</translation>
 <translation id="8024483450737722621">Os apps dos quais você fez o download no Google Play serão excluídos deste Chromebook.
       <ph name="LINE_BREAKS1" />
@@ -5056,7 +5056,7 @@
 <translation id="8784626084144195648">Média de pré-processamento</translation>
 <translation id="8785622406424941542">Stylus</translation>
 <translation id="8787254343425541995">Permitir proxies para redes compartilhadas</translation>
-<translation id="8791534160414513928">Enviar uma solicitação "Não rastrear" com seu tráfego de navegação</translation>
+<translation id="8791534160414513928">Enviar a observação "Não rastrear" em seu tráfego de navegação</translation>
 <translation id="8794025342371547160">IP restrito</translation>
 <translation id="879413103056696865">Enquanto o ponto de acesso estiver ativado, seu <ph name="PHONE_NAME" /> vai:</translation>
 <translation id="8795916974678578410">Nova janela</translation>
@@ -5175,7 +5175,7 @@
 <translation id="8984654317541110628">URL de compartilhamento de arquivos</translation>
 <translation id="8984872292925913496">Localize o PIN de seis dígitos na parte de trás da sua chave</translation>
 <translation id="8986362086234534611">Esquecer</translation>
-<translation id="8986494364107987395">Enviar estatísticas de uso e relatórios de erros ao Google automaticamente</translation>
+<translation id="8986494364107987395">Envia estatísticas de uso e relatórios de erros ao Google automaticamente</translation>
 <translation id="8987927404178983737">Mês</translation>
 <translation id="8991520179165052608">O site pode usar seu microfone</translation>
 <translation id="899403249577094719">URL base do certificado do Netscape</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index c339d8a..caa738c7f 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -19,7 +19,7 @@
 <translation id="1029317248976101138">Zoom</translation>
 <translation id="1030706264415084469"><ph name="URL" /> pretende armazenar permanentemente dados de grandes dimensões no seu dispositivo.</translation>
 <translation id="1031362278801463162">A carregar a pré-visualização</translation>
-<translation id="103279545524624934">Liberte espaço em disco para iniciar as aplicações Android.</translation>
+<translation id="103279545524624934">Liberte espaço em disco para iniciar as aplicações para Android.</translation>
 <translation id="1033780634303702874">Aceder aos dispositivos de série</translation>
 <translation id="1035094536595558507">Vista de diapositivos</translation>
 <translation id="1035590878859356651">Adicionar esta página aos marcadores...</translation>
@@ -656,7 +656,7 @@
 <translation id="197560921582345123">Pode editar</translation>
 <translation id="1975841812214822307">Remover...</translation>
 <translation id="1976150099241323601">Iniciar sessão no Dispositivo de segurança</translation>
-<translation id="1976315108329706992">Já pode utilizar aplicações Android.</translation>
+<translation id="1976315108329706992">Já pode utilizar aplicações para Android.</translation>
 <translation id="1976323404609382849">Foram bloqueados cookies de vários sites.</translation>
 <translation id="1977965994116744507">Aproxime o telemóvel para desbloquear o <ph name="DEVICE_TYPE" />.</translation>
 <translation id="1979280758666859181">Está a mudar para um canal com uma versão mais antiga do <ph name="PRODUCT_NAME" />. A alteração de canal será aplicada quando a versão do canal corresponder à versão atualmente instalada no seu dispositivo.</translation>
@@ -874,7 +874,7 @@
 <translation id="2316129865977710310">Não, obrigado</translation>
 <translation id="2317842250900878657"><ph name="PROGRESS_PERCENT" />% concluída</translation>
 <translation id="2318143611928805047">Tamanho do papel</translation>
-<translation id="2318817390901984578">Para utilizar aplicações Android, carregue e atualize o seu <ph name="DEVICE_TYPE" />.</translation>
+<translation id="2318817390901984578">Para utilizar aplicações para Android, carregue e atualize o seu <ph name="DEVICE_TYPE" />.</translation>
 <translation id="2318923050469484167">Sessão no modo de navegação anónima atual (<ph name="EMBEDDING" />)</translation>
 <translation id="2321482478556590128">Utilizar a Chave de segurança com a aplicação <ph name="APP_NAME" /></translation>
 <translation id="2322193970951063277">Cabeçalhos e rodapés</translation>
@@ -1196,7 +1196,7 @@
 <translation id="2788135150614412178">+</translation>
 <translation id="2789486458103222910">Ok</translation>
 <translation id="2791952154587244007">Ocorreu um erro. A aplicação Quiosque não poderá ser iniciada automaticamente neste dispositivo.</translation>
-<translation id="2792290659606763004">Remover aplicações Android?</translation>
+<translation id="2792290659606763004">Remover aplicações para Android?</translation>
 <translation id="2796424461616874739">A autenticação excedeu o tempo limite ao ligar a "<ph name="DEVICE_NAME" />".</translation>
 <translation id="2796740370559399562">Continuar a permitir cookies</translation>
 <translation id="2799223571221894425">Reiniciar</translation>
@@ -1885,7 +1885,7 @@
 <translation id="3839516600093027468">Impedir sempre <ph name="HOST" /> de ver a área de transferência</translation>
 <translation id="3840053866656739575">A ligação ao Chromebox foi perdida. Aproxime-se ou verifique o dispositivo enquanto tentamos restabelecer a ligação.</translation>
 <translation id="3842552989725514455">Tipo de letra Serif</translation>
-<translation id="3846116211488856547">Obtenha ferramentas para programar Websites, aplicações Android e muito mais. A instalação do Linux vai transferir <ph name="DOWNLOAD_SIZE" /> de dados.</translation>
+<translation id="3846116211488856547">Obtenha ferramentas para programar Websites, aplicações para Android e muito mais. A instalação do Linux vai transferir <ph name="DOWNLOAD_SIZE" /> de dados.</translation>
 <translation id="385051799172605136">Anterior</translation>
 <translation id="3851428669031642514">Carregar scripts não seguros</translation>
 <translation id="3854599674806204102">Escolha uma opção</translation>
@@ -2534,7 +2534,7 @@
 <translation id="4918086044614829423">Aceitar</translation>
 <translation id="4920350943031252905">Execute ferramentas, editores e IDEs do Linux no seu Chromebook.</translation>
 <translation id="4920887663447894854">Os sites seguintes foram bloqueados de monitorizar a sua localização nesta página:</translation>
-<translation id="492299503953721473">Remover aplicações Android</translation>
+<translation id="492299503953721473">Remover aplicações para Android</translation>
 <translation id="4923279099980110923">Sim, quero ajudar</translation>
 <translation id="4924352752174756392">12x</translation>
 <translation id="4924638091161556692">Corrigida</translation>
@@ -2648,7 +2648,7 @@
 <translation id="5101042277149003567">Abrir todos os marcadores</translation>
 <translation id="5104546332954397226">Utilizar o telemóvel como Chave de segurança</translation>
 <translation id="5105855035535475848">Fixar separadores</translation>
-<translation id="5108967062857032718">Definições – Remover aplicações Android</translation>
+<translation id="5108967062857032718">Definições – Remover aplicações para Android</translation>
 <translation id="5109044022078737958">Mia</translation>
 <translation id="5111692334209731439">&amp;Gestor de Marcadores</translation>
 <translation id="5112577000029535889">Ferramentas &amp;do programador</translation>
@@ -2764,7 +2764,7 @@
 <translation id="527605719918376753">Desativar som do separador</translation>
 <translation id="527605982717517565">Permitir sempre JavaScript em <ph name="HOST" /></translation>
 <translation id="5280426389926346830">Pretende criar um atalho?</translation>
-<translation id="528208740344463258">Para transferir e utilizar aplicações Android, tem de instalar primeiro esta atualização obrigatória. Enquanto o seu <ph name="DEVICE_TYPE" /> estiver a ser atualizado, não o pode utilizar. Quando a instalação estiver concluída, o <ph name="DEVICE_TYPE" /> será reiniciado.</translation>
+<translation id="528208740344463258">Para transferir e utilizar aplicações para Android, tem de instalar primeiro esta atualização obrigatória. Enquanto o seu <ph name="DEVICE_TYPE" /> estiver a ser atualizado, não o pode utilizar. Quando a instalação estiver concluída, o <ph name="DEVICE_TYPE" /> será reiniciado.</translation>
 <translation id="5282733140964383898">Se ativar a funcionalidade "Não Monitorizar", será incluído um pedido no seu tráfego de navegação. Os possíveis efeitos dependerão da resposta ao pedido por parte de um Website e da forma como o pedido é interpretado. Por exemplo, alguns Sites poderão mostrar anúncios que não sejam baseados noutros Sites visitados por si como resposta a este pedido. Muitos Sites continuarão a recolher e utilizar os seus dados de navegação com o objetivo de melhorar a segurança, fornecer conteúdos, serviços, anúncios e recomendações nos seus Sites e gerar estatísticas de relatórios. <ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /></translation>
 <translation id="5283677936944177147">Ups! O sistema não conseguiu determinar o modelo ou o número de série do dispositivo.</translation>
 <translation id="5284445933715251131">Continuar a transferir</translation>
@@ -3448,7 +3448,7 @@
 <translation id="6291953229176937411">Mo&amp;strar no Finder</translation>
 <translation id="6295158916970320988">Todos os sites</translation>
 <translation id="6295855836753816081">A guardar...</translation>
-<translation id="6298962879096096191">Utilizar o Google Play para instalar aplicações Android</translation>
+<translation id="6298962879096096191">Utilizar o Google Play para instalar aplicações para Android</translation>
 <translation id="630065524203833229">&amp;Sair</translation>
 <translation id="6305607932814307878">Política Global:</translation>
 <translation id="6307990684951724544">Sistema ocupado</translation>
@@ -4268,7 +4268,7 @@
 <translation id="7589461650300748890">Pare. Tenha cuidado.</translation>
 <translation id="7589661784326793847">Aguarde um momento</translation>
 <translation id="7591957897535945411">Esta página foi traduzida.</translation>
-<translation id="7595453277607160340">Para utilizar aplicações Android e manter o <ph name="DEVICE_TYPE" /> a funcionar corretamente, volte a iniciar sessão e proceda à atualização.</translation>
+<translation id="7595453277607160340">Para utilizar aplicações para Android e manter o <ph name="DEVICE_TYPE" /> a funcionar corretamente, volte a iniciar sessão e proceda à atualização.</translation>
 <translation id="7595547011743502844"><ph name="ERROR" /> (código de erro <ph name="ERROR_CODE" />).</translation>
 <translation id="7598466960084663009">Reiniciar computador</translation>
 <translation id="7599527631045201165">O nome do dispositivo é demasiado longo. Introduza um nome mais curto e tente novamente.</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index bc42461..a1363c21 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -106,7 +106,7 @@
 <translation id="1151917987301063366">Всегда разрешать сайту <ph name="HOST" /> использовать датчики</translation>
 <translation id="1153356358378277386">Сопряженные устройства</translation>
 <translation id="1156488781945104845">Текущее время</translation>
-<translation id="1157102636231978136">Данные о работе в браузере и о ваших действиях, синхронизированные с аккаунтом Google</translation>
+<translation id="1157102636231978136">Данные о работе в браузере и ваших действиях, связанных с аккаунтом Google</translation>
 <translation id="1161575384898972166">Чтобы экспортировать сертификат клиента, войдите в <ph name="TOKEN_NAME" />.</translation>
 <translation id="1163931534039071049">&amp;Просмотр кода фрейма</translation>
 <translation id="1164674268730883318">Отключить Smart Lock для устройства <ph name="DEVICE_TYPE" />?</translation>
@@ -248,7 +248,7 @@
 <translation id="1367951781824006909">Выберите файл</translation>
 <translation id="1368265273904755308">Сообщить о проблеме</translation>
 <translation id="1370553626198299309">Убедитесь, что устройство Chromebook подключено к Интернету и на телефоне включена функция Bluetooth.</translation>
-<translation id="1371301976177520732">Вы можете синхронизировать закладки, пароли, историю и другие данные на всех ваших устройствах.</translation>
+<translation id="1371301976177520732">Синхронизируйте закладки, пароли, историю и другие данные на всех ваших устройствах.</translation>
 <translation id="1372681413396468867">{NUM_ITEMS,plural, =1{Будет удален один объект}one{Будет удален # объект}few{Будет удалено # объекта}many{Будет удалено # объектов}other{Будет удалено # объекта}}</translation>
 <translation id="1372841398847029212">Синхронизировать с моим аккаунтом</translation>
 <translation id="1374844444528092021">Сертификат, запрашиваемый сетью <ph name="NETWORK_NAME" />, не установлен или уже не действителен. Получите новый и попробуйте подключиться еще раз.</translation>
@@ -269,7 +269,7 @@
 <translation id="1395730723686586365">Программа обновлений запущена</translation>
 <translation id="1396139853388185343">Не удалось настроить принтер</translation>
 <translation id="1396963298126346194">Неправильное имя пользователя или пароль</translation>
-<translation id="1397854323885047133">Синхронизировать и настроить</translation>
+<translation id="1397854323885047133">Настройки синхронизации и персонализации</translation>
 <translation id="1398853756734560583">Развернуть</translation>
 <translation id="1399511500114202393">Не использовать сертификат пользователя</translation>
 <translation id="140250605646987970">Телефон обнаружен. К сожалению, функция Smart Lock доступна только на устройствах с Android 5.0 и следующих версий. &lt;a&gt;Подробнее…&lt;/a&gt;</translation>
@@ -299,6 +299,7 @@
 <translation id="1433811987160647649">Запрашивать разрешение на доступ</translation>
 <translation id="1434696352799406980">Будут сброшены настройки главной страницы, страницы быстрого доступа и поисковой системы, а также откреплены все вкладки. Кроме того, система отключит все расширения и удалит все временные данные, такие как файлы cookie. Ваши закладки, история просмотров и пароли будут сохранены.</translation>
 <translation id="1434886155212424586">В качестве главной страницы установлена страница быстрого доступа.</translation>
+<translation id="1436671784520050284">Продолжить настройку</translation>
 <translation id="1436784010935106834">Удалено</translation>
 <translation id="1438632560381091872">Включить звук на вкладках</translation>
 <translation id="1442392616396121389">Префикс маршрутизации</translation>
@@ -318,6 +319,7 @@
 <translation id="1465827627707997754">Кусок пиццы</translation>
 <translation id="1467432559032391204">Слева</translation>
 <translation id="1468571364034902819">Нельзя использовать этот профиль</translation>
+<translation id="1470533772306424441">Эти приложения мы установим на ваше устройство. Другие продукты можно найти в Google Play.</translation>
 <translation id="1470811252759861213">Чтобы получить доступ к расширениям на всех ваших устройствах, <ph name="SIGN_IN_LINK" />.</translation>
 <translation id="1474339897586437869">Не удалось загрузить <ph name="FILENAME" />. Не хватает пространства на Google Диске.</translation>
 <translation id="1475502736924165259">У вас имеются сертификаты, которые не попадают ни в одну из других категорий</translation>
@@ -791,6 +793,7 @@
 <translation id="2192505247865591433">Из:</translation>
 <translation id="2193365732679659387">Настройки доверия</translation>
 <translation id="2195729137168608510">Защита электронной почты</translation>
+<translation id="2199298570273670671">Ошибка</translation>
 <translation id="2200356397587687044">Браузеру Chrome требуется разрешение</translation>
 <translation id="220138918934036434">Скрыть кнопку</translation>
 <translation id="2202898655984161076">Возникла проблема с перечнем принтеров. Возможно, некоторые принтеры не удалось зарегистрировать при помощи <ph name="CLOUD_PRINT_NAME" />.</translation>
@@ -943,6 +946,7 @@
 <translation id="2440604414813129000">Просмотреть и&amp;сходный код</translation>
 <translation id="2445081178310039857">Требуется корневой каталог расширения.</translation>
 <translation id="2445484935443597917">Создать профиль</translation>
+<translation id="2446585455334014596">Приложение "<ph name="APP_NAME" />" запрашивает подтверждение вашей личности</translation>
 <translation id="2448312741937722512">Тип</translation>
 <translation id="2450223707519584812">Отсутствуют ключи API Google. Вы не сможете добавлять пользователей. Подробная информация: <ph name="DETAILS_URL" />.</translation>
 <translation id="2450310832094867474">Отключить синхронизацию и выйти из аккаунта?</translation>
@@ -952,6 +956,7 @@
 <translation id="2453576648990281505">Файл уже существует</translation>
 <translation id="2453860139492968684">Закрыть</translation>
 <translation id="2454247629720664989">Ключевое слово</translation>
+<translation id="245661998428026871">Воспроизведение видео в режиме "Картинка в картинке" прекратится.</translation>
 <translation id="2457246892030921239"><ph name="APP_NAME" /> запрашивает разрешение на копирование файлов из тома "<ph name="VOLUME_NAME" />".</translation>
 <translation id="2462724976360937186">Идентификатор ключа ЦС</translation>
 <translation id="2462752602710430187">Добавлен принтер <ph name="PRINTER_NAME" /></translation>
@@ -1199,7 +1204,7 @@
 <translation id="2800760947029405028">Загрузить изображение</translation>
 <translation id="2803375539583399270">Введите PIN-код</translation>
 <translation id="2805646850212350655">Зашифрованная файловая система (EFS) Microsoft</translation>
-<translation id="2805756323405976993">Сервисы</translation>
+<translation id="2805756323405976993">Приложения</translation>
 <translation id="2807517655263062534">Скачанные файлы появятся здесь</translation>
 <translation id="2809586584051668049">и ещё <ph name="NUMBER_ADDITIONAL_DISABLED" /></translation>
 <translation id="281133045296806353">В текущем сеансе браузера создано новое окно.</translation>
@@ -1361,6 +1366,7 @@
 <translation id="304826556400666995">Включить звук на вкладках</translation>
 <translation id="3053013834507634016">Использование ключа сертификата</translation>
 <translation id="3057861065630527966">Создать резервные копии фото и видео</translation>
+<translation id="3059313675706898490">Android Сообщения</translation>
 <translation id="3060379269883947824">Включить озвучивание при нажатии</translation>
 <translation id="3061707000357573562">Исправление сервиса</translation>
 <translation id="3064410671692449875">Недостаточно данных</translation>
@@ -1409,6 +1415,7 @@
 <translation id="313205617302240621">Забыли пароль?</translation>
 <translation id="3132996321662585180">Обновлять ежедневно</translation>
 <translation id="3135204511829026971">Повернуть экран</translation>
+<translation id="313638818480447860">С вашим аккаунтом связано несколько приложений (<ph name="NUMBER_OF_APPS" />), оптимизированных для этого устройства.</translation>
 <translation id="313963229645891001">Скачивание: <ph name="STATUS" /></translation>
 <translation id="3139925690611372679">Аватар по умолчанию (желтый)</translation>
 <translation id="3140353188828248647">Курсор в адресную строку</translation>
@@ -1439,6 +1446,7 @@
 <translation id="3182749001423093222">Проверка правописания</translation>
 <translation id="3183139917765991655">Импорт профилей</translation>
 <translation id="3184560914950696195">Не удается сохранить файлы в $1. Измененные изображения будут сохранены в папку "Загрузки".</translation>
+<translation id="3188257591659621405">Мои файлы</translation>
 <translation id="3188465121994729530">Скользящее среднее</translation>
 <translation id="3190558889382726167">Пароль сохранен</translation>
 <translation id="3192947282887913208">Аудиофайлы</translation>
@@ -1526,6 +1534,7 @@
 <translation id="3326821416087822643">Файл "<ph name="FILE_NAME" />" архивируется…</translation>
 <translation id="3331321258768829690">(<ph name="UTCOFFSET" />) <ph name="LONGTZNAME" /> (<ph name="EXEMPLARCITY" />)</translation>
 <translation id="3331974543021145906">О приложении</translation>
+<translation id="3334632933872291866"><ph name="WINDOW_TITLE" />: видео воспроизводится в режиме "Картинка в картинке"</translation>
 <translation id="3335337277364016868">Год записи</translation>
 <translation id="3335947283844343239">Открыть закрытую вкладку</translation>
 <translation id="3336664756920573711">Снимать блокировку <ph name="DEVICE_TYPE" /> с помощью телефона Android</translation>
@@ -1545,6 +1554,7 @@
 <translation id="3360297538363969800">Не удалось распечатать документ. Проверьте, всё ли в порядке с принтером, и повторите попытку.</translation>
 <translation id="3364721542077212959">Инструменты стилуса</translation>
 <translation id="3365598184818502391">Необходимо использовать Ctrl или Alt</translation>
+<translation id="3367047597842238025">Настройте устройство <ph name="DEVICE_TYPE" /> по своему вкусу и оцените его удивительные возможности.</translation>
 <translation id="3368922792935385530">Подключено</translation>
 <translation id="3369624026883419694">Определение хоста...</translation>
 <translation id="337286756654493126">Чтение данных в файлах и каталогах, открытых в приложении</translation>
@@ -1558,6 +1568,7 @@
 <translation id="3389312115541230716">Правой кнопкой мыши выберите <ph name="SMALL_PRODUCT_LOGO" /> на панели задач</translation>
 <translation id="3391716558283801616">Вкладка 7</translation>
 <translation id="3396331542604645348">Принтер недоступен или установлен неправильно. Проверьте его или выберите другой.</translation>
+<translation id="3396800784455899911">Нажимая кнопку "Принять условия и продолжить", вы соглашаетесь с Условиями использования сервисов Google, описанными выше.</translation>
 <translation id="3399432415385675819">Уведомления будут отключены</translation>
 <translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
 <translation id="3404065873681873169">Для этого сайта нет сохраненных паролей</translation>
@@ -1760,7 +1771,7 @@
 <translation id="3688507211863392146">Запись данных в файлы и каталоги, открытые в приложении</translation>
 <translation id="3688526734140524629">Выбрать другую версию</translation>
 <translation id="3688578402379768763">Обновление не требуется</translation>
-<translation id="3691214267321877444">Способы оплаты и адреса из Google Pay</translation>
+<translation id="3691214267321877444">Способы оплаты и адреса из Google Pay.</translation>
 <translation id="3691231116639905343">Клавиатуры</translation>
 <translation id="3691267899302886494">Сайт <ph name="HOST" /> запрашивает доступ к вашему экрану.</translation>
 <translation id="3693415264595406141">Пароль:</translation>
@@ -1786,10 +1797,13 @@
 <translation id="3726463242007121105">Невозможно получить доступ к устройству, так как его файловая система не поддерживается.</translation>
 <translation id="3727148787322499904">Изменение этого параметра повлияет на все общие сети</translation>
 <translation id="3727187387656390258">Просмотреть всплывающее окно</translation>
+<translation id="3729506734996624908">Разрешенные сайты</translation>
 <translation id="3732078975418297900">Ошибка в строке <ph name="ERROR_LINE" /></translation>
 <translation id="3733127536501031542">SSL-сервер с повышением</translation>
+<translation id="3735740477244556633">Сортировать по:</translation>
 <translation id="3737274407993947948">Ошибка при установке Linux</translation>
 <translation id="3737536731758327622">Здесь появятся скачанные файлы.</translation>
+<translation id="3738671331307774213">Подтвердив свою личность, вы защитите конфиденциальные данные.</translation>
 <translation id="3738924763801731196"><ph name="OID" />:</translation>
 <translation id="3739254215541673094">Открыть приложение "<ph name="APPLICATION" />"?</translation>
 <translation id="3741158646617793859"><ph name="DEVICE_NAME" /> появится в консоли администратора</translation>
@@ -1874,6 +1888,7 @@
 <translation id="3846116211488856547">Разрабатывайте сайты, приложения для Android и другие программы с помощью удобных инструментов. При установке Linux будут скачаны данные объемом <ph name="DOWNLOAD_SIZE" />.</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3851428669031642514">Загрузить небезопасные скрипты</translation>
+<translation id="3854599674806204102">Выберите нужный вариант.</translation>
 <translation id="3855441664322950881">Упаковать расширение</translation>
 <translation id="3855676282923585394">Импорт закладок и настроек...</translation>
 <translation id="3856800405688283469">Выберите часовой пояс</translation>
@@ -2227,7 +2242,7 @@
 <translation id="4462159676511157176">Другие серверы имен</translation>
 <translation id="4467100756425880649">Галерея Интернет-магазина Chrome</translation>
 <translation id="4467101674048705704">Развернуть папку <ph name="FOLDER_NAME" /></translation>
-<translation id="447252321002412580">Помогите улучшить Chrome и его функции</translation>
+<translation id="447252321002412580">Помогать повышать производительность Chrome и улучшать функции</translation>
 <translation id="4472575034687746823">Начало работы</translation>
 <translation id="4474155171896946103">Добавить все вкладки в закладки…</translation>
 <translation id="4475552974751346499">Искать в скачанных файлах</translation>
@@ -2484,7 +2499,7 @@
 <translation id="4880827082731008257">Искать в истории</translation>
 <translation id="4881695831933465202">Открыть</translation>
 <translation id="4882473678324857464">Активировать закладки</translation>
-<translation id="4882831918239250449">Выберите параметры истории просмотров для персонализации Поиска, рекламы и т. д.</translation>
+<translation id="4882831918239250449">Использование данных о посещенных страницах для персонализации Поиска, рекламы и т. д.</translation>
 <translation id="4883178195103750615">Экспортировать закладки в файл HTML...</translation>
 <translation id="4883436287898674711">Все сайты <ph name="WEBSITE_1" /></translation>
 <translation id="48838266408104654">Диспетчер задач</translation>
@@ -2540,6 +2555,7 @@
 <translation id="4955814292505481804">Годовая</translation>
 <translation id="4957949153200969297">Включите функции <ph name="IDS_SHORT_PRODUCT_NAME" />, связанные только с синхронизацией.</translation>
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> (<ph name="PROFILE_NAME" />)</translation>
+<translation id="4961000125720751066">Карты всегда под рукой</translation>
 <translation id="496226124210045887">Выбранный каталог содержит конфиденциальные файлы. Предоставить пользователю "$1" постоянный доступ на чтение данных в этом каталоге?</translation>
 <translation id="4964455510556214366">Расположение</translation>
 <translation id="4964673849688379040">Проверка...</translation>
@@ -2587,6 +2603,7 @@
 <translation id="5027562294707732951">Установить расширение</translation>
 <translation id="5029568752722684782">Удалить данные</translation>
 <translation id="5030338702439866405">Выдан:</translation>
+<translation id="503155457707535043">Скачивание приложений</translation>
 <translation id="503498442187459473">Сайт <ph name="HOST" /> запрашивает доступ к камере и микрофону.</translation>
 <translation id="5036662165765606524">Запретить сайтам автоматически скачивать более одного файла</translation>
 <translation id="5037676449506322593">Выделить все</translation>
@@ -3061,7 +3078,7 @@
 <translation id="5723508132121499792">Нет приложений, работающих в фоновом режиме</translation>
 <translation id="5727728807527375859">Расширения и темы могут причинить вред вашему компьютеру. Продолжить?</translation>
 <translation id="5729712731028706266">&amp;Вид</translation>
-<translation id="5731185123186077399">Персонализированные сервисы Google, например Google Pay</translation>
+<translation id="5731185123186077399">Пользуйтесь персонализированными сервисами Google, например Google Pay.</translation>
 <translation id="5731247495086897348">Вс&amp;тавить из буфера и перейти</translation>
 <translation id="5731409020711461763">новых фото: 1</translation>
 <translation id="5734362860645681824">Оборудование</translation>
@@ -3101,6 +3118,7 @@
 <translation id="57838592816432529">Отключить звук</translation>
 <translation id="5785583009707899920">Файловые утилиты Chrome</translation>
 <translation id="5787146423283493983">Согласование ключей</translation>
+<translation id="5788127256798019331">Файлы Google Play</translation>
 <translation id="5788367137662787332">Не удалось добавить один или несколько разделов устройства <ph name="DEVICE_LABEL" />.</translation>
 <translation id="5794414402486823030">Всегда открывать в программе просмотра по умолчанию</translation>
 <translation id="5794786537412027208">Закрыть все приложения Chrome</translation>
@@ -3353,6 +3371,7 @@
 <translation id="6178664161104547336">Выбор сертификата</translation>
 <translation id="6181431612547969857">Скачивание запрещено</translation>
 <translation id="6185132558746749656">Местоположение устройства</translation>
+<translation id="6185617499004995178">Валидатор CUPS IPP</translation>
 <translation id="6185696379715117369">На страницу вверх</translation>
 <translation id="6189273858858366896">Настройка совместного доступа к файлам в сети.</translation>
 <translation id="6189412234224385711">Открыть с помощью расширения "<ph name="EXTENSION_NAME" />"</translation>
@@ -3385,6 +3404,7 @@
 <translation id="6231881193380278751">Добавьте в URL параметр запроса для автоматического обновления страницы: chrome://device-log/?refresh=&lt;sec&gt;</translation>
 <translation id="6232017090690406397">Аккумулятор</translation>
 <translation id="6232116551750539448">Соединение с <ph name="NAME" /> прервано</translation>
+<translation id="6235700927623181151">На этой вкладке транслируется содержимое вашего рабочего стола.</translation>
 <translation id="6237816943013845465">Позволяет настроить разрешение экрана</translation>
 <translation id="6238923052227198598">Показывать последнюю заметку на заблокированном экране</translation>
 <translation id="6239558157302047471">Перезагрузить &amp;фрейм</translation>
@@ -3529,6 +3549,7 @@
 <translation id="6451180435462401570">Управление устройствами с поддержкой виртуальной печати</translation>
 <translation id="6451689256222386810">Если вы забыли кодовую фразу или хотите изменить эту настройку, <ph name="BEGIN_LINK" />сбросьте параметры синхронизации<ph name="END_LINK" />.</translation>
 <translation id="6452181791372256707">Отклонить</translation>
+<translation id="6455264371803474013">На выбранных сайтах</translation>
 <translation id="6455894534188563617">&amp;Новая папка</translation>
 <translation id="6456394469623773452">Хороший</translation>
 <translation id="6456631036739229488">Телефон для снятия блокировки был изменен. Чтобы обновить Smart Lock, введите пароль. После этого вы сможете снимать блокировку устройства <ph name="DEVICE_TYPE" /> с помощью телефона. Чтобы выключить Smart Lock, перейдите в настройки.</translation>
@@ -3606,6 +3627,7 @@
 <translation id="657402800789773160">&amp;Обновить страницу</translation>
 <translation id="6577284282025554716">Скачивание файла <ph name="FILE_NAME" /> отменено</translation>
 <translation id="6578664922716508575">Шифровать синхронизированные пароли с помощью имени пользователя Google и пароля</translation>
+<translation id="6579705087617859690"><ph name="WINDOW_TITLE" />: доступ к содержимому рабочего стола открыт</translation>
 <translation id="6580151766480067746">Версия ARC</translation>
 <translation id="6581162200855843583">Ссылка на Google Диск</translation>
 <translation id="6582421931165117398">Чтобы защитить свои личные данные, смените пароль прямо сейчас. Перед этим нужно будет войти в аккаунт.</translation>
@@ -4072,6 +4094,7 @@
 <translation id="730289542559375723">{NUM_APPLICATIONS,plural, =1{Это приложение может помешать работе Google Chrome.}one{Эти приложения могут помешать работе Google Chrome.}few{Эти приложения могут помешать работе Google Chrome.}many{Эти приложения могут помешать работе Google Chrome.}other{Эти приложения могут помешать работе Google Chrome.}}</translation>
 <translation id="7303900363563182677">У этого сайта нет доступа к тексту и изображениям, скопированным в буфер обмена</translation>
 <translation id="730515362922783851">Обмен данными с любыми устройствами в локальной сети и Интернете</translation>
+<translation id="7307129035224081534">Приостановлена</translation>
 <translation id="7308002049209013926">Используйте панель запуска для быстрого перехода к приложениям и действиям. Для этого нажмите Alt + Shift + L.</translation>
 <translation id="7309257895202129721">Показать &amp;элементы управления</translation>
 <translation id="7310598146671372464">Не удалось выполнить вход. Сервер не поддерживает выбранные типы шифрования Kerberos. Обратитесь к администратору.</translation>
@@ -4161,6 +4184,7 @@
 <translation id="7465778193084373987">URL отзыва сертификатов Netscape</translation>
 <translation id="7469894403370665791">Автоматически подключаться к этой сети</translation>
 <translation id="747114903913869239">Ошибка: не удается расшифровать расширение</translation>
+<translation id="7473753388963818366">Давайте настроим устройство <ph name="DEVICE_TYPE" /></translation>
 <translation id="7473891865547856676">Пропустить</translation>
 <translation id="747459581954555080">Восстановить все</translation>
 <translation id="7475671414023905704">URL потерянных паролей Netscape</translation>
@@ -4285,6 +4309,7 @@
 <translation id="7665369617277396874">Добавить аккаунт</translation>
 <translation id="7671130400130574146">Использовать системные рамки и строку заголовка</translation>
 <translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> на странице <ph name="PAGE_TITLE" />.</translation>
+<translation id="7676867886086876795">Запись вашего голоса отправляется в Google. Это позволяет использовать голосовой набор для любого текстового поля.</translation>
 <translation id="7681095912841365527">Сайт может использовать Bluetooth</translation>
 <translation id="7683373461016844951">Чтобы продолжить, нажмите "OK". Затем создайте другой профиль для своего электронного адреса в домене <ph name="DOMAIN" />, выбрав "Добавить пользователя".</translation>
 <translation id="7684212569183643648">Установлено администратором</translation>
@@ -4326,6 +4351,7 @@
 <translation id="7740996059027112821">Стандартный</translation>
 <translation id="7748528009589593815">Предыдущая вкладка</translation>
 <translation id="7748626145866214022">Больше возможностей доступно на панели действий. Чтобы перейти на нее, нажмите клавиши Alt + A.</translation>
+<translation id="7750228210027921155">Картинка в картинке</translation>
 <translation id="7751260505918304024">Показать все</translation>
 <translation id="7754704193130578113">Всегда указывать место для скачивания</translation>
 <translation id="7758143121000533418">Family Link</translation>
@@ -4434,6 +4460,7 @@
 <translation id="7857949311770343000">Другая страница быстрого доступа?</translation>
 <translation id="786073089922909430">Сервис: <ph name="ARC_PROCESS_NAME" /></translation>
 <translation id="7861215335140947162">&amp;Загрузки</translation>
+<translation id="7868378670806575181">{NUM_COOKIES,plural, =1{1 файл cookie}one{# файл cookie}few{# файла cookie}many{# файлов cookie}other{# файла cookie}}</translation>
 <translation id="786957569166715433">Подключено устройство: <ph name="DEVICE_NAME" /></translation>
 <translation id="7870730066603611552">Проверять параметры синхронизации после начала сеанса</translation>
 <translation id="7870790288828963061">Новых версий киоск-приложений нет. Обновление не требуется. Извлеките USB-накопитель.</translation>
@@ -4512,7 +4539,7 @@
 <translation id="7978412674231730200">Закрытый ключ</translation>
 <translation id="7979036127916589816">Ошибка синхронизации</translation>
 <translation id="7980084013673500153">Идентификатор объекта: <ph name="ASSET_ID" /></translation>
-<translation id="7981313251711023384">Разрешить предварительную настройку страниц для повышения скорости работы и поиска</translation>
+<translation id="7981313251711023384">Разрешить предзагрузку страниц для повышения скорости работы браузера и поиска</translation>
 <translation id="7982083145464587921">Для устранения ошибки перезагрузите устройство.</translation>
 <translation id="7982283708762922719">Высота</translation>
 <translation id="7982789257301363584">Сеть</translation>
@@ -4542,7 +4569,7 @@
 <translation id="8016266267177410919">Папка для временного хранения</translation>
 <translation id="8017335670460187064"><ph name="LABEL" /></translation>
 <translation id="8017679124341497925">Ярлык изменен</translation>
-<translation id="8018313076035239964">Выберите, какие данные отправлять сайтам и какой контент показывать на веб-страницах</translation>
+<translation id="8018313076035239964">Выбрать, какие данные отправлять сайтам и какой контент показывать на веб-страницах</translation>
 <translation id="8023801379949507775">Обновить расширения</translation>
 <translation id="8024483450737722621">Приложения, скачанные в Google Play, будут удалены с этого устройства Chromebook.
       <ph name="LINE_BREAKS1" />
@@ -4755,6 +4782,7 @@
 <translation id="8373553483208508744">Отключить звук на вкладках</translation>
 <translation id="8382913212082956454">Копировать &amp;адрес электронной почты</translation>
 <translation id="8386903983509584791">Поиск завершен</translation>
+<translation id="8389492867173948260">Разрешить расширению просмотр и изменение ваших данных на посещаемых сайтах</translation>
 <translation id="8390449457866780408">Сервер недоступен.</translation>
 <translation id="8391712576156218334">Фоновое изображение недоступно. Повторите попытку позже.</translation>
 <translation id="8392234662362215700">Нажмите Ctrl + Shift + ПРОБЕЛ, чтобы переключить раскладку клавиатуры.</translation>
@@ -4786,9 +4814,10 @@
 <translation id="84297032718407999">Выход из системы произойдет через <ph name="LOGOUT_TIME_LEFT" /></translation>
 <translation id="8431909052837336408">Изменение PIN-кода SIM-карты</translation>
 <translation id="8434480141477525001">Порт отладки NaCl</translation>
+<translation id="8435395510592618362">Подтверждение личности для приложения "<ph name="APP_NAME" />"</translation>
 <translation id="843760761634048214">Сохранить кредитную карту</translation>
 <translation id="8438328416656800239">Перейдите на умный браузер</translation>
-<translation id="8438566539970814960">Улучшить поиск и просмотр страниц</translation>
+<translation id="8438566539970814960">Помогать улучшить просмотр страниц и поиск</translation>
 <translation id="8439506636278576865">Предлагать перевести страницы на этом языке</translation>
 <translation id="8446884382197647889">Подробнее...</translation>
 <translation id="8447409163267621480">Сочетание должно начинаться с клавиши Ctrl или Alt</translation>
@@ -4812,6 +4841,7 @@
 <translation id="8465252176946159372">Недопустимо</translation>
 <translation id="8465444703385715657">Для работы плагина <ph name="PLUGIN_NAME" /> необходимо разрешение</translation>
 <translation id="8466234950814670489">Архив TAR</translation>
+<translation id="8466417995783206254">На этой вкладке воспроизводится видео в режиме "Картинка в картинке".</translation>
 <translation id="8468750959626135884">Снимайте блокировку устройства <ph name="DEVICE_TYPE" /> с помощью телефона Android.</translation>
 <translation id="8470028084415844044">Чтобы получить доступ к паролям на всех своих устройствах, включите синхронизацию.</translation>
 <translation id="8470513973197838199">Сохраненные пароли для <ph name="ORIGIN" /></translation>
@@ -4832,6 +4862,7 @@
 <translation id="8496717697661868878">Запустить подключаемый модуль</translation>
 <translation id="8497219075884839166">Утилиты Windows</translation>
 <translation id="8498214519255567734">Этот режим помогает снизить напряжение глаз при тусклом свете</translation>
+<translation id="8498395510292172881">Продолжить чтение в Chrome</translation>
 <translation id="8503813439785031346">Имя пользователя</translation>
 <translation id="850875081535031620">Вредоносных программ не найдено.</translation>
 <translation id="8509646642152301857">Не удалось скачать словарь проверки правописания</translation>
@@ -5138,7 +5169,7 @@
 <translation id="8978154919215542464">Включено (синхронизировать все)</translation>
 <translation id="897939795688207351"><ph name="ORIGIN" />: вкл.</translation>
 <translation id="8980951173413349704"><ph name="WINDOW_TITLE" />: произошел сбой</translation>
-<translation id="8983677657449185470">Помогите улучшить режим Безопасного просмотра</translation>
+<translation id="8983677657449185470">Помогать улучшить режим Безопасного просмотра</translation>
 <translation id="8984654317541110628">URL для совместного доступа к файлу</translation>
 <translation id="8984872292925913496">Найдите на обратной стороне ключа шестизначный PIN-код.</translation>
 <translation id="8986362086234534611">Удалить</translation>
@@ -5172,6 +5203,7 @@
 <translation id="9027459031423301635">Открыть ссылку в новой вкладке</translation>
 <translation id="9030515284705930323">Приложение "Play Маркет" отключено для вашего аккаунта. За дополнительными сведениями обратитесь к администратору.</translation>
 <translation id="9033857511263905942">&amp;Вставить</translation>
+<translation id="9034924485347205037">Файлы Linux</translation>
 <translation id="9035012421917565900">Объекты нельзя переместить обратно на общий диск "<ph name="DESTINATION_NAME" />", поэтому вы не сможете отменить это действие.</translation>
 <translation id="9037008143807155145">https://www.google.com/calendar/render?cid=%s</translation>
 <translation id="9037965129289936994">Показать оригинал</translation>
@@ -5183,7 +5215,7 @@
 <translation id="9042893549633094279">Конфиденциальность и безопасность</translation>
 <translation id="904451693890288097">Введите пароль для устройства "<ph name="DEVICE_NAME" />":</translation>
 <translation id="9044646465488564462">Не удалось подключиться к сети: <ph name="DETAILS" /></translation>
-<translation id="9045430190527754450">Отправлять в Google адреса веб-страниц, которые вы пытаетесь открыть.</translation>
+<translation id="9045430190527754450">Отправлять в Google адреса веб-страниц, которые вы пытаетесь открыть</translation>
 <translation id="9046895021617826162">Сбой подключения</translation>
 <translation id="9050666287014529139">Кодовая фраза</translation>
 <translation id="9052208328806230490">Вы зарегистрировали принтеры в <ph name="CLOUD_PRINT_NAME" /> с использованием аккаунта <ph name="EMAIL" /></translation>
@@ -5272,6 +5304,7 @@
 <translation id="9173995187295789444">Поиск устройств Bluetooth…</translation>
 <translation id="9176611096776448349"><ph name="WINDOW_TITLE" />: подключено устройство Bluetooth</translation>
 <translation id="9177499212658576372">Вы подключены к сети <ph name="NETWORK_TYPE" />.</translation>
+<translation id="9179734824669616955">Установка Linux (бета) на устройстве <ph name="DEVICE_TYPE" /></translation>
 <translation id="9180281769944411366">Подождите несколько минут. Запуск контейнера Linux…</translation>
 <translation id="9180380851667544951">Сайт может открыть доступ к вашему экрану</translation>
 <translation id="9188441292293901223">Чтобы разблокировать <ph name="DEVICE_TYPE" />, установите последнюю версию Android на телефоне.</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 624b2df..40864e7d 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -2475,7 +2475,7 @@
 <translation id="4863769717153320198">有效分辨率:<ph name="WIDTH" /> x <ph name="HEIGHT" />(默认)</translation>
 <translation id="4864369630010738180">正在登录…</translation>
 <translation id="486635084936119914">下载特定类型的文件后自动将其打开</translation>
-<translation id="4869142322204669043">Google 可能会根据您所访问的网站中的内容、您的浏览活动和互动行为对 <ph name="IDS_SHORT_PRODUCT_NAME" /> 以及其他 Google 服务(例如翻译、搜索和广告)进行个性化设置。您随时可在“设置”中自定义此设置。</translation>
+<translation id="4869142322204669043">Google 可能会根据您访问的网站上的内容、您的浏览活动和互动行为,为您提供个性化的 <ph name="IDS_SHORT_PRODUCT_NAME" /> 体验和其他 Google 服务体验(例如翻译、搜索和广告)。您随时可在“设置”中自定义此设置。</translation>
 <translation id="48704129375571883">添加其他功能</translation>
 <translation id="4870903493621965035">没有已配对的设备</translation>
 <translation id="4871210892959306034">$1 KB</translation>
@@ -4114,7 +4114,7 @@
 <translation id="7366415735885268578">添加网站</translation>
 <translation id="7366909168761621528">浏览数据</translation>
 <translation id="7371006317849674875">开始时间</translation>
-<translation id="737439367876257440">通过将系统信息和使用情况信息发送给 Google 来改进 Chrome 并提高其安全性</translation>
+<translation id="737439367876257440">将系统信息和使用情况信息发送给 Google,帮助改进 Chrome 并提高其安全性</translation>
 <translation id="7374989181012106167">将您的 Chromebook 连接到手机,可获得更好的体验。<ph name="LINK_BEGIN" />了解详情<ph name="LINK_END" />。</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7376553024552204454">在移动鼠标光标时突出显示光标</translation>
@@ -4139,7 +4139,7 @@
 <translation id="7407430846095439694">导入并绑定</translation>
 <translation id="7409836189476010449">运行 Flash</translation>
 <translation id="7410344089573941623"><ph name="HOST" /> 想要使用摄像头和麦克风时询问我是否同意</translation>
-<translation id="741204030948306876">确认</translation>
+<translation id="741204030948306876">立即启用</translation>
 <translation id="7412226954991670867">GPU 内存</translation>
 <translation id="7413455776853560343">自定义背景</translation>
 <translation id="7414464185801331860">18 倍</translation>
@@ -4418,7 +4418,7 @@
 <translation id="7831491651892296503">配置网络时出错</translation>
 <translation id="7831754656372780761">“<ph name="TAB_TITLE" />”<ph name="EMOJI_MUTING" /></translation>
 <translation id="7832084384634357321">结束时间</translation>
-<translation id="7832327313660264358">您同步到 Google 中的数据和您使用的功能将保持不变</translation>
+<translation id="7832327313660264358">您同步到 Google 的数据和您使用的功能不会改变</translation>
 <translation id="7833720883933317473">已保存的自定义字词将显示在这里</translation>
 <translation id="7837307963048806839">•  $1</translation>
 <translation id="7837776265184002579">您的主页已改为 <ph name="URL" />。</translation>
@@ -4548,7 +4548,7 @@
 <translation id="8012382203418782830">此网页内容已经过翻译。</translation>
 <translation id="8014154204619229810">更新程序正在运行,请稍后刷新并再次查看。</translation>
 <translation id="8014206674403687691"><ph name="IDS_SHORT_PRODUCT_NAME" />无法还原到之前安装的版本。请重新尝试对您的设备执行 Powerwash 操作。</translation>
-<translation id="8014210335923519270">通过将系统信息和使用情况数据发送给 Google 来改进 <ph name="IDS_SHORT_PRODUCT_NAME" /> 并提高其安全性</translation>
+<translation id="8014210335923519270">将系统信息和使用情况数据发送给 Google,帮助改进 <ph name="IDS_SHORT_PRODUCT_NAME" /> 并提高其安全性</translation>
 <translation id="8016266267177410919">临时存储</translation>
 <translation id="8017335670460187064"><ph name="LABEL" /></translation>
 <translation id="8017679124341497925">已修改快捷方式</translation>
diff --git a/chrome/app/resources/google_chrome_strings_ar.xtb b/chrome/app/resources/google_chrome_strings_ar.xtb
index c51845a..35f3c66 100644
--- a/chrome/app/resources/google_chrome_strings_ar.xtb
+++ b/chrome/app/resources/google_chrome_strings_ar.xtb
@@ -132,6 +132,7 @@
 <translation id="4561051373932531560">‏يتيح لك Google Chrome النقر على رقم هاتف على الويب والاتصال به باستخدام Skype!</translation>
 <translation id="4567424176335768812">لقد سجلت دخولك باعتبارك <ph name="USER_EMAIL_ADDRESS" />. ويُمكنك الآن الاستمتاع بالدخول إلى الإشارات المرجعية، والسجلّ، والإعدادات الأخرى على جميع الأجهزة التي تسجّل الدخول إليها.</translation>
 <translation id="4571503333518166079">‏الانتقال إلى إعدادات الإشعارات في Chrome</translation>
+<translation id="459622048091363950">‏بعد حصول Chrome على إمكانية الوصول، ستتمكن المواقع الإلكترونية من مطالبتك بإمكانية الوصول.</translation>
 <translation id="4600710005438004015">‏تعذّر تحديث Chrome إلى آخر إصدار، لذلك قد تفوتك الميزات وعمليات إصلاح الأمان الجديدة.</translation>
 <translation id="4631713731678262610">‏الإخفاء في قائمة Chrome</translation>
 <translation id="4633000520311261472">‏لجعل Chrome أكثر أمانًا، تم إيقاف بعض الإضافات غير المدرجة في <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> والتي ربما تمت إضافتها بدون علمك.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_bn.xtb b/chrome/app/resources/google_chrome_strings_bn.xtb
index 9d64652a5..690bb60 100644
--- a/chrome/app/resources/google_chrome_strings_bn.xtb
+++ b/chrome/app/resources/google_chrome_strings_bn.xtb
@@ -132,6 +132,7 @@
 <translation id="4561051373932531560">Google Chrome আপনাকে ওয়েবে কোনো ফোন নম্বরে ক্লিক করতে এবং Skype-এর মাধ্যমে সেটিতে কল করতে দেয়!</translation>
 <translation id="4567424176335768812">আপনি <ph name="USER_EMAIL_ADDRESS" /> হিসাবে প্রবেশ করেছেন৷ এখন আপনি আপনার সমস্ত প্রবেশ করা ডিভাইসে আপনার বুকমার্ক, ইতিহাস এবং অন্যান্য সেটিংস অ্যাক্সেস করতে পারেন৷</translation>
 <translation id="4571503333518166079">Chrome বিজ্ঞপ্তি সেটিংসে যান</translation>
+<translation id="459622048091363950">একবার Chrome অ্যাক্সেস করার পরে, ওয়েবসাইটগুলি অ্যাক্সেস চাইতে পারে।</translation>
 <translation id="4600710005438004015">Chrom লেটেস্ট ভার্সনে আপডেট করা যাচ্ছে না, তাই আপনি নতুন বৈশিষ্ট্য এবং সুরক্ষা সমাধানগুলি পাচ্ছেন না।</translation>
 <translation id="4631713731678262610">Chromium মেনুর মধ্যে লুকান</translation>
 <translation id="4633000520311261472">Chrome কে আরও নিরাপদ করতে, আমরা কিছু এক্সটেনশান অক্ষম করেছি যা <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> এ তালিকাবদ্ধ করা হয়নি এবং হয়ত আপনাকে না জানিয়ে যোগ করা হয়েছে৷</translation>
diff --git a/chrome/app/resources/google_chrome_strings_de.xtb b/chrome/app/resources/google_chrome_strings_de.xtb
index 3c414af..379aff9 100644
--- a/chrome/app/resources/google_chrome_strings_de.xtb
+++ b/chrome/app/resources/google_chrome_strings_de.xtb
@@ -57,7 +57,7 @@
 <translation id="2348335408836342058">Chrome benötigt für diese Website die Berechtigung, auf Ihre Kamera und Ihr Mikrofon zuzugreifen</translation>
 <translation id="2397416548179033562">Chrome-Menü anzeigen</translation>
 <translation id="2429317896000329049">Google Chrome konnte Ihre Daten nicht synchronisieren, da die Synchronisierung für Ihre Domain nicht zur Verfügung steht.</translation>
-<translation id="2436117022029368436">Mit Google kommunizieren, um das Surferlebnis und Chrome zu verbessern</translation>
+<translation id="2436117022029368436">Funktionen nutzen, die helfen, Chrome für Sie noch besser zu machen</translation>
 <translation id="2467438592969358367">Google Chrome möchte Ihre Passwörter exportieren. Wenn Sie dies zulassen möchten, geben Sie Ihr Windows-Passwort ein.</translation>
 <translation id="2485422356828889247">Deinstallieren</translation>
 <translation id="2534507159460261402">Google Pay (in Chrome kopiert)</translation>
@@ -114,7 +114,7 @@
 <translation id="4028693306634653894">Schneller Zugriff auf Chrome</translation>
 <translation id="4050175100176540509">Wichtige Sicherheitsverbesserungen und neue Funktionen sind in der aktuellen Version verfügbar.</translation>
 <translation id="4053720452172726777">Google Chrome anpassen und einstellen</translation>
-<translation id="4143243756087420366">Chrome-Name und -Bild</translation>
+<translation id="4143243756087420366">Profilname und -bild in Chrome</translation>
 <translation id="4147555960264124640">Sie melden sich mit einem verwalteten Konto an und ermöglichen dessen Administrator Zugriff auf Ihr Google Chrome-Profil. Ihre Chrome-Daten, wie Apps, Lesezeichen, Verlauf, Passwörter und andere Einstellungen, werden dauerhaft mit <ph name="USER_NAME" /> verknüpft. Sie können diese Daten über das Google Konten-Dashboard löschen, aber nicht mit einem anderen Konto verknüpfen. <ph name="LEARN_MORE" /></translation>
 <translation id="4149882025268051530">Das Installationsprogramm konnte das Archiv nicht dekomprimieren. Laden Sie Google Chrome erneut herunter.</translation>
 <translation id="424864128008805179">Von Chrome abmelden?</translation>
diff --git a/chrome/app/resources/google_chrome_strings_ru.xtb b/chrome/app/resources/google_chrome_strings_ru.xtb
index 119691b..f4663b3 100644
--- a/chrome/app/resources/google_chrome_strings_ru.xtb
+++ b/chrome/app/resources/google_chrome_strings_ru.xtb
@@ -57,7 +57,7 @@
 <translation id="2348335408836342058">Для этого сайта Chrome запрашивает доступ к камере и микрофону.</translation>
 <translation id="2397416548179033562">Отображение меню Chrome</translation>
 <translation id="2429317896000329049">Google Chrome не удалось синхронизировать данные, поскольку служба Sync недоступна для вашего домена.</translation>
-<translation id="2436117022029368436">Обмен информацией с Google для улучшения работы Chrome</translation>
+<translation id="2436117022029368436">Отправка данных в Google для улучшения работы Chrome</translation>
 <translation id="2467438592969358367">Чтобы экспортировать пароли из Google Chrome, введите пароль своего аккаунта Windows.</translation>
 <translation id="2485422356828889247">Удалить</translation>
 <translation id="2534507159460261402">Google Pay (скопирована в Chrome)</translation>
@@ -114,7 +114,7 @@
 <translation id="4028693306634653894">Открывайте Chrome ещё быстрее</translation>
 <translation id="4050175100176540509">В последней версии улучшена защита и добавлены новые функции.</translation>
 <translation id="4053720452172726777">Настройка и управление Google Chrome</translation>
-<translation id="4143243756087420366">Имя и изображение профиля Chrome</translation>
+<translation id="4143243756087420366">Имя и фото профиля Chrome</translation>
 <translation id="4147555960264124640">Выполнив вход в управляемый аккаунт, вы предоставляете администратору право контролировать настройки вашего профиля Google Chrome. Ваши данные Chrome (приложения, закладки, история, пароли и другие настройки) будут временно связаны с аккаунтом <ph name="USER_NAME" />. Эти данные можно удалить в Личном кабинете Google, но их нельзя связать с другим аккаунтом. <ph name="LEARN_MORE" /></translation>
 <translation id="4149882025268051530">Не удалось извлечь файлы из архива. Скачайте Google Chrome заново.</translation>
 <translation id="424864128008805179">Выйти из Chrome?</translation>
@@ -130,6 +130,7 @@
 <translation id="4561051373932531560">В Google Chrome вы можете нажать на любой номер телефона и позвонить на него через Skype!</translation>
 <translation id="4567424176335768812">Вы вошли с помощью аккаунта <ph name="USER_EMAIL_ADDRESS" />. Ваши закладки, история и другие настройки теперь доступны на всех устройствах, где вы используете этот аккаунт.</translation>
 <translation id="4571503333518166079">Открыть настройки уведомлений Chrome</translation>
+<translation id="459622048091363950">Когда вы предоставите доступ Chrome, веб-сайты также смогут запрашивать у вас доступ.</translation>
 <translation id="4600710005438004015">Не удалось установить последнюю версию Chrome, в которой добавлены новые функции и обновления системы безопасности.</translation>
 <translation id="4631713731678262610">Не показывать в меню Google Chrome</translation>
 <translation id="4633000520311261472">Чтобы обеспечить безопасность ваших данных, некоторые расширения Chrome были отключены, так как <ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> не содержит сведений о них, то есть эти компоненты могли быть установлены без вашего ведома.</translation>
@@ -239,7 +240,7 @@
 <translation id="8286862437124483331">Чтобы просмотреть пароли, введите пароль своего аккаунта Windows.</translation>
 <translation id="8290100596633877290">Произошел сбой Google Chrome. Перезапустить?</translation>
 <translation id="8342675569599923794">Chrome заблокировал этот файл как опасный.</translation>
-<translation id="8380166467911888159">Для проверки правописания Chrome отправляет введенный вами текст в Google.</translation>
+<translation id="8380166467911888159">Отправлять введенный вами текст в Google для проверки правописания</translation>
 <translation id="840084489713044809">Вы собираетесь экспортировать пароли из Google Chrome.</translation>
 <translation id="8406086379114794905">Помогите сделать Chrome безопаснее</translation>
 <translation id="8455999171311319804">Автоматически отправлять статистику использования и данные диагностики в Google, чтобы помочь улучшить Chrome OS (необязательно)</translation>
diff --git a/chrome/app/resources/google_chrome_strings_zh-CN.xtb b/chrome/app/resources/google_chrome_strings_zh-CN.xtb
index 99f46cf..98b72ea 100644
--- a/chrome/app/resources/google_chrome_strings_zh-CN.xtb
+++ b/chrome/app/resources/google_chrome_strings_zh-CN.xtb
@@ -251,7 +251,7 @@
 <translation id="8547799825197623713">Chrome 应用启动器 Canary</translation>
 <translation id="8556340503434111824">Google Chrome 浏览器现已推出速度更快的新版本。</translation>
 <translation id="8568392309447938879">您需要先登录Chrome,再使用各项应用。这样,Chrome就可以在各个设备上同步您的应用、书签、历史记录、密码和其他设置。</translation>
-<translation id="8606668294522778825">Google Chrome可能会使用网络服务来改善您的浏览体验。不过,您可以选择停用这些服务。<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
+<translation id="8606668294522778825">Google Chrome 可能会使用网络服务来改善您的浏览体验。不过,您可以选择停用这些服务。<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
 <translation id="8614913330719544658">Google Chrome 未响应。是否立即重新启动?</translation>
 <translation id="8667808506758191620">您的 <ph name="DEVICE_TYPE" /> 是最新版本。</translation>
 <translation id="8669527147644353129">Google Chrome 浏览器帮助程序</translation>
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 8b4a11a7..c51096e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1106,6 +1106,9 @@
     "login/screens/network_error.cc",
     "login/screens/network_error.h",
     "login/screens/network_error_view.h",
+    "login/screens/network_screen.cc",
+    "login/screens/network_screen.h",
+    "login/screens/network_screen_view.h",
     "login/screens/recommend_apps_screen.cc",
     "login/screens/recommend_apps_screen.h",
     "login/screens/recommend_apps_screen_view.h",
@@ -1874,6 +1877,8 @@
     "login/screens/mock_error_screen.h",
     "login/screens/mock_model_view_channel.cc",
     "login/screens/mock_model_view_channel.h",
+    "login/screens/mock_network_screen.cc",
+    "login/screens/mock_network_screen.h",
     "login/screens/mock_update_screen.cc",
     "login/screens/mock_update_screen.h",
     "login/screens/mock_welcome_screen.cc",
@@ -2078,8 +2083,8 @@
     "login/quick_unlock/pin_storage_prefs_unittest.cc",
     "login/quick_unlock/quick_unlock_storage_unittest.cc",
     "login/saml/saml_offline_signin_limiter_unittest.cc",
+    "login/screens/network_screen_unittest.cc",
     "login/screens/update_screen_unittest.cc",
-    "login/screens/welcome_screen_unittest.cc",
     "login/signin/merge_session_navigation_throttle_unittest.cc",
     "login/signin_partition_manager_unittest.cc",
     "login/supervised/supervised_user_authentication_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index c06eb17..8a99220 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -578,12 +578,16 @@
   arc_session_manager()->Shutdown();
 }
 
-TEST_F(ArcSessionManagerTest, RegularToChildTransition_Default) {
+TEST_F(ArcSessionManagerTest, RegularToChildTransition_FlagOn) {
   // Emulate the situation where a regular user has transitioned to a child
   // account.
   profile()->GetPrefs()->SetInteger(
       prefs::kArcSupervisionTransition,
       static_cast<int>(ArcSupervisionTransition::REGULAR_TO_CHILD));
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      kCleanArcDataOnRegularToChildTransitionFeature);
+
   arc_session_manager()->SetProfile(profile());
   arc_session_manager()->Initialize();
   EXPECT_TRUE(
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc
index 98bad8a3..f9a172a 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc
@@ -529,6 +529,9 @@
 }
 
 TEST_F(ShouldCreateDemoExtensionsExternalLoaderTest, NotDemoMode) {
+  DemoSession::SetDemoModeEnrollmentTypeForTesting(
+      DemoSession::EnrollmentType::kUnenrolled);
+
   // This should be no-op, given that the default demo session enrollment state
   // is not-enrolled.
   DemoSession::StartIfInDemoMode();
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
index b0acd5a1..43e00e2 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -8,6 +8,11 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/settings/install_attributes.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/image_loader_client.h"
 #include "content/public/browser/browser_thread.h"
@@ -19,7 +24,7 @@
 // Global DemoSession instance.
 DemoSession* g_demo_session = nullptr;
 
-// Whether the demo mode was forced on for tests.
+// Type of demo setup forced on for tests.
 DemoSession::EnrollmentType g_force_enrollment_type =
     DemoSession::EnrollmentType::kNone;
 
@@ -43,8 +48,8 @@
 bool IsDemoModeOfflineEnrolled() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(DemoSession::IsDeviceInDemoMode());
-  // TODO(tbarzic): Implement this.
-  return g_force_enrollment_type == DemoSession::EnrollmentType::kOffline;
+  return DemoSession::GetEnrollmentType() ==
+         DemoSession::EnrollmentType::kOffline;
 }
 
 }  // namespace
@@ -52,8 +57,21 @@
 // static
 bool DemoSession::IsDeviceInDemoMode() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  // TODO(tbarzic): Implement this.
-  return g_force_enrollment_type != DemoSession::EnrollmentType::kNone;
+  const EnrollmentType enrollment_type = GetEnrollmentType();
+  return enrollment_type != EnrollmentType::kNone &&
+         enrollment_type != EnrollmentType::kUnenrolled;
+}
+
+// static
+DemoSession::EnrollmentType DemoSession::GetEnrollmentType() {
+  if (g_force_enrollment_type != EnrollmentType::kNone)
+    return g_force_enrollment_type;
+
+  const policy::BrowserPolicyConnectorChromeOS* const connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  bool enrolled = connector->GetInstallAttributes()->GetDomain() ==
+                  DemoSetupController::kDemoModeDomain;
+  return enrolled ? EnrollmentType::kOnline : EnrollmentType::kUnenrolled;
 }
 
 // static
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.h b/chrome/browser/chromeos/login/demo_mode/demo_session.h
index cc9dd2a..800cf46 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_session.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session.h
@@ -20,9 +20,12 @@
 class DemoSession {
  public:
   enum class EnrollmentType {
-    // Device was not enrolled into demo mode
+    // Demo mode enrollment unset/unknown.
     kNone,
 
+    // Device was not enrolled into demo mode.
+    kUnenrolled,
+
     // Device was enrolled into demo mode using online enrollment flow.
     kOnline,
 
@@ -34,6 +37,9 @@
   // Whether the device is set up to run demo sessions.
   static bool IsDeviceInDemoMode();
 
+  // Returns the type of demo mode setup.
+  static EnrollmentType GetEnrollmentType();
+
   static void SetDemoModeEnrollmentTypeForTesting(
       EnrollmentType enrollment_type);
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc
new file mode 100644
index 0000000..2c8d74a
--- /dev/null
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc
@@ -0,0 +1,124 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
+#include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
+
+namespace chromeos {
+
+namespace {
+
+constexpr char kFakeDeviceId[] = "device_id";
+constexpr char kNonDemoDomain[] = "non-demo-mode.com";
+
+}  // namespace
+
+class DemoSessionDemoEnrolledDeviceTest : public LoginManagerTest {
+ public:
+  DemoSessionDemoEnrolledDeviceTest()
+      : LoginManagerTest(true /*should_launch_browser*/),
+        install_attributes_(ScopedStubInstallAttributes::CreateCloudManaged(
+            DemoSetupController::kDemoModeDomain,
+            kFakeDeviceId)) {}
+  ~DemoSessionDemoEnrolledDeviceTest() override = default;
+
+ private:
+  const ScopedStubInstallAttributes install_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoSessionDemoEnrolledDeviceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoSessionDemoEnrolledDeviceTest, IsDemoMode) {
+  EXPECT_TRUE(DemoSession::IsDeviceInDemoMode());
+  EXPECT_EQ(DemoSession::EnrollmentType::kOnline,
+            DemoSession::GetEnrollmentType());
+}
+
+class DemoSessionNonDemoEnrolledDeviceTest : public LoginManagerTest {
+ public:
+  DemoSessionNonDemoEnrolledDeviceTest()
+      : LoginManagerTest(true /*should_launch_browser*/),
+        install_attributes_(
+            ScopedStubInstallAttributes::CreateCloudManaged(kNonDemoDomain,
+                                                            kFakeDeviceId)) {}
+  ~DemoSessionNonDemoEnrolledDeviceTest() override = default;
+
+ private:
+  ScopedStubInstallAttributes install_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoSessionNonDemoEnrolledDeviceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoSessionNonDemoEnrolledDeviceTest, NotDemoMode) {
+  EXPECT_FALSE(DemoSession::IsDeviceInDemoMode());
+  EXPECT_EQ(DemoSession::EnrollmentType::kUnenrolled,
+            DemoSession::GetEnrollmentType());
+}
+
+class DemoSessionConsumerDeviceTest : public LoginManagerTest {
+ public:
+  DemoSessionConsumerDeviceTest()
+      : LoginManagerTest(true /*should_launch_browser*/),
+        install_attributes_(
+            ScopedStubInstallAttributes::CreateConsumerOwned()) {}
+  ~DemoSessionConsumerDeviceTest() override = default;
+
+ private:
+  ScopedStubInstallAttributes install_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoSessionConsumerDeviceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoSessionConsumerDeviceTest, NotDemoMode) {
+  EXPECT_FALSE(DemoSession::IsDeviceInDemoMode());
+  EXPECT_EQ(DemoSession::EnrollmentType::kUnenrolled,
+            DemoSession::GetEnrollmentType());
+}
+
+class DemoSessionUnownedDeviceTest : public LoginManagerTest {
+ public:
+  DemoSessionUnownedDeviceTest()
+      : LoginManagerTest(true /*should_launch_browser*/),
+        install_attributes_(ScopedStubInstallAttributes::CreateUnset()) {}
+  ~DemoSessionUnownedDeviceTest() override = default;
+
+ private:
+  ScopedStubInstallAttributes install_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoSessionUnownedDeviceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoSessionUnownedDeviceTest, NotDemoMode) {
+  EXPECT_FALSE(DemoSession::IsDeviceInDemoMode());
+  EXPECT_EQ(DemoSession::EnrollmentType::kUnenrolled,
+            DemoSession::GetEnrollmentType());
+}
+
+class DemoSessionActiveDirectoryDeviceTest : public LoginManagerTest {
+ public:
+  DemoSessionActiveDirectoryDeviceTest()
+      : LoginManagerTest(true /*should_launch_browser*/),
+        install_attributes_(
+            ScopedStubInstallAttributes::CreateActiveDirectoryManaged(
+                DemoSetupController::kDemoModeDomain,
+                kFakeDeviceId)) {}
+  ~DemoSessionActiveDirectoryDeviceTest() override = default;
+
+ private:
+  ScopedStubInstallAttributes install_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoSessionActiveDirectoryDeviceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoSessionActiveDirectoryDeviceTest, NotDemoMode) {
+  EXPECT_FALSE(DemoSession::IsDeviceInDemoMode());
+  EXPECT_EQ(DemoSession::EnrollmentType::kUnenrolled,
+            DemoSession::GetEnrollmentType());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
index 21eec985..7c82d275 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
@@ -185,7 +185,7 @@
 
 TEST_F(DemoSessionTest, StartForDemoDeviceNotInDemoMode) {
   DemoSession::SetDemoModeEnrollmentTypeForTesting(
-      DemoSession::EnrollmentType::kNone);
+      DemoSession::EnrollmentType::kUnenrolled);
   EXPECT_FALSE(DemoSession::Get());
   EXPECT_FALSE(DemoSession::StartIfInDemoMode());
   EXPECT_FALSE(DemoSession::Get());
@@ -236,7 +236,7 @@
 
 TEST_F(DemoSessionTest, PreloadOfflineResourcesIfNotInDemoMode) {
   DemoSession::SetDemoModeEnrollmentTypeForTesting(
-      DemoSession::EnrollmentType::kNone);
+      DemoSession::EnrollmentType::kUnenrolled);
   DemoSession::PreloadOfflineResourcesIfInDemoMode();
   EXPECT_FALSE(DemoSession::Get());
   EXPECT_EQ(std::list<std::string>(), image_loader_client_->pending_loads());
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
index c5c45ae..f9f7c5f 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
@@ -20,10 +20,9 @@
 
 namespace {
 
-constexpr const char kDemoDomain[] = "cros-demo-mode.com";
-constexpr const char kDemoRequisition[] = "cros-demo-mode";
-constexpr const char kOfflineDevicePolicyFileName[] = "device_policy";
-constexpr const char kOfflineDeviceLocalAccountPolicyFileName[] =
+constexpr char kDemoRequisition[] = "cros-demo-mode";
+constexpr char kOfflineDevicePolicyFileName[] = "device_policy";
+constexpr char kOfflineDeviceLocalAccountPolicyFileName[] =
     "local_account_policy";
 
 bool CheckOfflinePolicyFilesExist(const base::FilePath& policy_dir,
@@ -86,6 +85,9 @@
 
 namespace chromeos {
 
+// static
+constexpr char DemoSetupController::kDemoModeDomain[];
+
 DemoSetupController::DemoSetupController(Delegate* delegate)
     : delegate_(delegate), weak_ptr_factory_(this) {
   DCHECK(delegate_);
@@ -106,10 +108,10 @@
   policy::EnrollmentConfig config;
   config.mode = policy::EnrollmentConfig::MODE_ATTESTATION;
   mode_ = config.mode;
-  config.management_domain = kDemoDomain;
+  config.management_domain = DemoSetupController::kDemoModeDomain;
 
-  enrollment_helper_ =
-      EnterpriseEnrollmentHelper::Create(this, nullptr, config, kDemoDomain);
+  enrollment_helper_ = EnterpriseEnrollmentHelper::Create(
+      this, nullptr, config, DemoSetupController::kDemoModeDomain);
   enrollment_helper_->EnrollUsingAttestation();
 }
 
@@ -141,11 +143,12 @@
 
   policy::EnrollmentConfig config;
   config.mode = mode_;
-  config.management_domain = kDemoDomain;
+  config.management_domain = DemoSetupController::kDemoModeDomain;
   config.offline_policy_path =
       policy_dir_.AppendASCII(kOfflineDevicePolicyFileName);
   enrollment_helper_ = EnterpriseEnrollmentHelper::Create(
-      this, nullptr /* ad_join_delegate */, config, kDemoDomain);
+      this, nullptr /* ad_join_delegate */, config,
+      DemoSetupController::kDemoModeDomain);
   enrollment_helper_->EnrollForOfflineDemo();
 }
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h
index 5ff7322b..c3b45c7d 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h
@@ -20,6 +20,9 @@
     : public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer,
       public policy::CloudPolicyStore::Observer {
  public:
+  // Domain that demo mode devices are enrolled into.
+  static constexpr char kDemoModeDomain[] = "cros-demo-mode.com";
+
   // Delegate that will be notified about result of setup flow when it is
   // finished.
   class Delegate {
diff --git a/chrome/browser/chromeos/login/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_setup_browsertest.cc
index 1a3e3ac..7cc2a20 100644
--- a/chrome/browser/chromeos/login/demo_setup_browsertest.cc
+++ b/chrome/browser/chromeos/login/demo_setup_browsertest.cc
@@ -8,15 +8,27 @@
 #include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/timer/timer.h"
+#include "base/values.h"
 #include "chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/mock_network_state_helper.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h"
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
+#include "chrome/browser/chromeos/login/screens/screen_exit_code.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "content/public/test/browser_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 
 using chromeos::test::DemoModeSetupResult;
 using chromeos::test::MockDemoModeOfflineEnrollmentHelperCreator;
@@ -30,6 +42,7 @@
     "!document.querySelector('.cr-dialog-container') || "
     "!!document.querySelector('.cr-dialog-container').hidden";
 
+constexpr char kDefaultNetworkServicePath[] = "/service/eth1";
 constexpr base::TimeDelta kJsConditionCheckFrequency =
     base::TimeDelta::FromMilliseconds(200);
 
@@ -40,7 +53,7 @@
 enum class OobeButton { kBack, kNext, kText };
 
 // Dialogs that are a part of Demo Mode setup screens.
-enum class DemoSetupDialog { kEula, kSettings, kProgress, kError };
+enum class DemoSetupDialog { kNetwork, kEula, kSettings, kProgress, kError };
 
 // Returns js id of the given |button| type.
 std::string ButtonToStringId(OobeButton button) {
@@ -59,6 +72,8 @@
 // Returns js id of the given |dialog|.
 std::string DialogToStringId(DemoSetupDialog dialog) {
   switch (dialog) {
+    case DemoSetupDialog::kNetwork:
+      return "networkDialog";
     case DemoSetupDialog::kEula:
       return "eulaDialog";
     case DemoSetupDialog::kSettings:
@@ -78,10 +93,14 @@
   switch (screen) {
     case OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES:
       return "$('demo-preferences-content')";
+    case OobeScreen::SCREEN_OOBE_NETWORK:
+      return "$('oobe-network-md')";
     case OobeScreen::SCREEN_OOBE_EULA:
       return "$('oobe-eula-md')";
     case OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE:
       return "$('arc-tos-root')";
+    case OobeScreen::SCREEN_OOBE_UPDATE:
+      return "$('oobe-update-md')";
     case OobeScreen::SCREEN_OOBE_DEMO_SETUP:
       return "$('demo-setup-content')";
     default: {
@@ -146,6 +165,8 @@
   void SetUpOnMainThread() override {
     LoginManagerTest::SetUpOnMainThread();
     DisableConfirmationDialogAnimations();
+    WizardController::default_controller()->is_official_build_ = true;
+    DisconnectAllNetworks();
   }
 
   bool IsScreenShown(OobeScreen screen) {
@@ -178,6 +199,17 @@
     return js_checker().GetBool(query);
   }
 
+  bool IsScreenDialogElementEnabled(OobeScreen screen,
+                                    DemoSetupDialog dialog,
+                                    const std::string& element) {
+    const std::string element_selector = base::StrCat(
+        {ScreenToContentQuery(screen), ".$.", DialogToStringId(dialog),
+         ".querySelector('", element, "')"});
+    const std::string query = base::StrCat(
+        {"!!", element_selector, " && !", element_selector, ".disabled"});
+    return js_checker().GetBool(query);
+  }
+
   void SetPlayStoreTermsForTesting() {
     EXPECT_TRUE(
         JSExecute("login.ArcTermsOfServiceScreen.setTosForTesting('Test "
@@ -249,8 +281,9 @@
   void SkipToDialog(DemoSetupDialog dialog) {
     InvokeDemoMode();
     ClickOkOnConfirmationDialog();
-    WizardController::default_controller()->AdvanceToScreen(
-        OobeScreen::SCREEN_OOBE_DEMO_SETUP);
+    auto* const wizard_controller = WizardController::default_controller();
+    wizard_controller->SimulateDemoModeSetupForTesting();
+    wizard_controller->AdvanceToScreen(OobeScreen::SCREEN_OOBE_DEMO_SETUP);
 
     OobeScreenWaiter(OobeScreen::SCREEN_OOBE_DEMO_SETUP).Wait();
     EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP));
@@ -262,12 +295,59 @@
     EXPECT_TRUE(IsDialogShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP, dialog));
   }
 
+  void SkipToScreen(OobeScreen screen) {
+    auto* const wizard_controller = WizardController::default_controller();
+    wizard_controller->SimulateDemoModeSetupForTesting();
+    wizard_controller->AdvanceToScreen(screen);
+
+    OobeScreenWaiter(screen).Wait();
+    EXPECT_TRUE(IsScreenShown(screen));
+  }
+
   DemoSetupScreen* GetDemoSetupScreen() {
     return static_cast<DemoSetupScreen*>(
         WizardController::default_controller()->screen_manager()->GetScreen(
             OobeScreen::SCREEN_OOBE_DEMO_SETUP));
   }
 
+  // Simulates device being connected to the network.
+  void SimulateNetworkConnected() {
+    ShillServiceClient::TestInterface* service =
+        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
+    service->SetServiceProperty(kDefaultNetworkServicePath,
+                                shill::kStateProperty,
+                                base::Value(shill::kStateOnline));
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // Simulates device being disconnected from the network.
+  void SimulateNetworkDisconnected() {
+    ShillServiceClient::TestInterface* service =
+        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
+    service->SetServiceProperty(kDefaultNetworkServicePath,
+                                shill::kStateProperty,
+                                base::Value(shill::kStateIdle));
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // Sets all network services into idle state.
+  void DisconnectAllNetworks() {
+    NetworkStateHandler::NetworkStateList networks;
+    NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
+        NetworkTypePattern::Default(),
+        true,   // configured_only
+        false,  // visible_only,
+        0,      // no limit to number of results
+        &networks);
+    ShillServiceClient::TestInterface* service =
+        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
+    for (const auto* const network : networks) {
+      service->SetServiceProperty(network->path(), shill::kStateProperty,
+                                  base::Value(shill::kStateIdle));
+    }
+    base::RunLoop().RunUntilIdle();
+  }
+
  private:
   void DisableConfirmationDialogAnimations() {
     EXPECT_TRUE(
@@ -313,6 +393,7 @@
   // Simulate successful online setup.
   EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
       &MockDemoModeOnlineEnrollmentHelperCreator<DemoModeSetupResult::SUCCESS>);
+  SimulateNetworkConnected();
 
   InvokeDemoMode();
   ClickOkOnConfirmationDialog();
@@ -323,6 +404,15 @@
   ClickOobeButton(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES, OobeButton::kText,
                   JSExecution::kAsync);
 
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
+  EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_NETWORK));
+  EXPECT_TRUE(IsScreenDialogElementEnabled(
+      OobeScreen::SCREEN_OOBE_NETWORK, DemoSetupDialog::kNetwork,
+      ButtonToStringId(OobeButton::kNext)));
+
+  ClickOobeButton(OobeScreen::SCREEN_OOBE_NETWORK, OobeButton::kNext,
+                  JSExecution::kAsync);
+
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_EULA).Wait();
   EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_EULA));
 
@@ -338,6 +428,8 @@
   ClickOobeButtonWithId(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE,
                         "#arc-tos-accept-button", JSExecution::kAsync);
 
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_UPDATE).Wait();
+
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_DEMO_SETUP).Wait();
   EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP));
   EXPECT_TRUE(IsDialogShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
@@ -357,6 +449,7 @@
   // Simulate online setup failure.
   EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
       &MockDemoModeOnlineEnrollmentHelperCreator<DemoModeSetupResult::ERROR>);
+  SimulateNetworkConnected();
 
   InvokeDemoMode();
   ClickOkOnConfirmationDialog();
@@ -367,6 +460,15 @@
   ClickOobeButton(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES, OobeButton::kText,
                   JSExecution::kAsync);
 
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
+  EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_NETWORK));
+  EXPECT_TRUE(IsScreenDialogElementEnabled(
+      OobeScreen::SCREEN_OOBE_NETWORK, DemoSetupDialog::kNetwork,
+      ButtonToStringId(OobeButton::kNext)));
+
+  ClickOobeButton(OobeScreen::SCREEN_OOBE_NETWORK, OobeButton::kNext,
+                  JSExecution::kAsync);
+
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_EULA).Wait();
   EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_EULA));
 
@@ -382,6 +484,8 @@
   ClickOobeButtonWithId(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE,
                         "#arc-tos-accept-button", JSExecution::kAsync);
 
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_UPDATE).Wait();
+
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_DEMO_SETUP).Wait();
   EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP));
   EXPECT_TRUE(IsDialogShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
@@ -393,10 +497,6 @@
   EXPECT_TRUE(IsDialogShown(OobeScreen::SCREEN_OOBE_DEMO_SETUP,
                             DemoSetupDialog::kProgress));
 
-  // Simulate online setup failure.
-  EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
-      &MockDemoModeOnlineEnrollmentHelperCreator<DemoModeSetupResult::ERROR>);
-
   // Wait for progress dialog to be hidden.
   const std::string progress_dialog_hidden_query = base::StrCat(
       {"!!", ScreenToContentQuery(OobeScreen::SCREEN_OOBE_DEMO_SETUP), ".$.",
@@ -412,6 +512,32 @@
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_WELCOME).Wait();
 }
 
+IN_PROC_BROWSER_TEST_F(DemoSetupTest, NextDisabledOnNetworkScreen) {
+  SimulateNetworkDisconnected();
+  SkipToScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+
+  EXPECT_FALSE(IsScreenDialogElementEnabled(
+      OobeScreen::SCREEN_OOBE_NETWORK, DemoSetupDialog::kNetwork,
+      ButtonToStringId(OobeButton::kNext)));
+
+  ClickOobeButton(OobeScreen::SCREEN_OOBE_NETWORK, OobeButton::kNext,
+                  JSExecution::kSync);
+
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
+  EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_NETWORK));
+}
+
+IN_PROC_BROWSER_TEST_F(DemoSetupTest, BackOnNetworkScreen) {
+  SimulateNetworkConnected();
+  SkipToScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+
+  ClickOobeButton(OobeScreen::SCREEN_OOBE_NETWORK, OobeButton::kBack,
+                  JSExecution::kAsync);
+
+  OobeScreenWaiter(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES).Wait();
+  EXPECT_TRUE(IsScreenShown(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES));
+}
+
 IN_PROC_BROWSER_TEST_F(DemoSetupTest, BackOnSettingsScreen) {
   SkipToDialog(DemoSetupDialog::kSettings);
 
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
index 400c1dc..29b027b 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -81,9 +81,10 @@
 void ViewsScreenLocker::Init() {
   lock_time_ = base::TimeTicks::Now();
   user_selection_screen_->Init(screen_locker_->users());
-  LoginScreenClient::Get()->login_screen()->LoadUsers(
-      user_selection_screen_->UpdateAndReturnUserListForMojo(),
-      false /* show_guests */);
+  LoginScreenClient::Get()->login_screen()->SetUserList(
+      user_selection_screen_->UpdateAndReturnUserListForMojo());
+  LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(
+      false /*show_guest*/);
   if (!ime_state_.get())
     ime_state_ = input_method::InputMethodManager::Get()->GetActiveIMEState();
 
diff --git a/chrome/browser/chromeos/login/oobe_screen.cc b/chrome/browser/chromeos/login/oobe_screen.cc
index 05d04dd..593a27b 100644
--- a/chrome/browser/chromeos/login/oobe_screen.cc
+++ b/chrome/browser/chromeos/login/oobe_screen.cc
@@ -19,6 +19,7 @@
 const char* kScreenNames[] = {
     "hid-detection",                   // SCREEN_OOBE_HID_DETECTION
     "connect",                         // SCREEN_OOBE_WELCOME
+    "network-selection",               // SCREEN_OOBE_NETWORK
     "eula",                            // SCREEN_OOBE_EULA
     "update",                          // SCREEN_OOBE_UPDATE
     "debugging",                       // SCREEN_OOBE_ENABLE_DEBUGGING
diff --git a/chrome/browser/chromeos/login/oobe_screen.h b/chrome/browser/chromeos/login/oobe_screen.h
index c54cdfae..2b8afbd3 100644
--- a/chrome/browser/chromeos/login/oobe_screen.h
+++ b/chrome/browser/chromeos/login/oobe_screen.h
@@ -17,6 +17,7 @@
 enum class OobeScreen : unsigned int {
   SCREEN_OOBE_HID_DETECTION = 0,
   SCREEN_OOBE_WELCOME,
+  SCREEN_OOBE_NETWORK,
   SCREEN_OOBE_EULA,
   SCREEN_OOBE_UPDATE,
   SCREEN_OOBE_ENABLE_DEBUGGING,
diff --git a/chrome/browser/chromeos/login/screens/base_screen.h b/chrome/browser/chromeos/login/screens/base_screen.h
index 00a2353..58bc9a9 100644
--- a/chrome/browser/chromeos/login/screens/base_screen.h
+++ b/chrome/browser/chromeos/login/screens/base_screen.h
@@ -149,7 +149,7 @@
   FRIEND_TEST_ALL_PREFIXES(HandsOffWelcomeScreenTest, ContinueClickedOnlyOnce);
 
   friend class BaseWebUIHandler;
-  friend class WelcomeScreenTest;
+  friend class NetworkScreenTest;
   friend class ScreenEditor;
   friend class ScreenManager;
   friend class UpdateScreenTest;
diff --git a/chrome/browser/chromeos/login/screens/mock_network_screen.cc b/chrome/browser/chromeos/login/screens/mock_network_screen.cc
new file mode 100644
index 0000000..9e06e24
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/mock_network_screen.cc
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/mock_network_screen.h"
+
+namespace chromeos {
+
+using ::testing::AtLeast;
+using ::testing::_;
+
+MockNetworkScreen::MockNetworkScreen(BaseScreenDelegate* base_screen_delegate,
+                                     NetworkScreenView* view)
+    : NetworkScreen(base_screen_delegate, view) {}
+
+MockNetworkScreen::~MockNetworkScreen() = default;
+
+MockNetworkScreenView::MockNetworkScreenView() {
+  EXPECT_CALL(*this, MockBind(_)).Times(AtLeast(1));
+}
+
+MockNetworkScreenView::~MockNetworkScreenView() {
+  if (screen_)
+    screen_->OnViewDestroyed(this);
+}
+
+void MockNetworkScreenView::Bind(NetworkScreen* screen) {
+  screen_ = screen;
+  MockBind(screen);
+}
+
+void MockNetworkScreenView::Unbind() {
+  screen_ = nullptr;
+  MockUnbind();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/mock_network_screen.h b/chrome/browser/chromeos/login/screens/mock_network_screen.h
new file mode 100644
index 0000000..502d10a
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/mock_network_screen.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_NETWORK_SCREEN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_NETWORK_SCREEN_H_
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
+#include "chrome/browser/chromeos/login/screens/network_screen_view.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromeos {
+
+class MockNetworkScreen : public NetworkScreen {
+ public:
+  MockNetworkScreen(BaseScreenDelegate* base_screen_delegate,
+                    NetworkScreenView* view);
+  ~MockNetworkScreen() override;
+
+  MOCK_METHOD0(Show, void());
+  MOCK_METHOD0(Hide, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockNetworkScreen);
+};
+
+class MockNetworkScreenView : public NetworkScreenView {
+ public:
+  MockNetworkScreenView();
+  ~MockNetworkScreenView() override;
+
+  void Bind(NetworkScreen* screen) override;
+  void Unbind() override;
+
+  MOCK_METHOD1(MockBind, void(NetworkScreen* screen));
+  MOCK_METHOD0(MockUnbind, void());
+  MOCK_METHOD0(Show, void());
+  MOCK_METHOD0(Hide, void());
+  MOCK_METHOD1(ShowError, void(const base::string16& message));
+  MOCK_METHOD0(ClearErrors, void());
+  MOCK_METHOD2(ShowConnectingStatus,
+               void(bool connecting, const base::string16& network_id));
+
+ private:
+  NetworkScreen* screen_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(MockNetworkScreenView);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_NETWORK_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc b/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
index c6b336e..439143d 100644
--- a/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
                                      WelcomeView* view)
     : WelcomeScreen(base_screen_delegate, delegate, view) {}
 
-MockWelcomeScreen::~MockWelcomeScreen() {}
+MockWelcomeScreen::~MockWelcomeScreen() = default;
 
 MockWelcomeView::MockWelcomeView() {
   EXPECT_CALL(*this, MockBind(_)).Times(AtLeast(1));
diff --git a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
index e3a2198..db3f0a629 100644
--- a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
+++ b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
@@ -1,11 +1,11 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_WELCOME_SCREEN_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_WELCOME_SCREEN_H_
 
-#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "base/macros.h"
 #include "chrome/browser/chromeos/login/screens/welcome_screen.h"
 #include "chrome/browser/chromeos/login/screens/welcome_view.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -22,6 +22,9 @@
   MOCK_METHOD0(Show, void());
   MOCK_METHOD0(Hide, void());
   MOCK_METHOD2(SetConfiguration, void(base::Value* configuration, bool notify));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockWelcomeScreen);
 };
 
 class MockWelcomeView : public WelcomeView {
@@ -36,16 +39,13 @@
   MOCK_METHOD0(MockUnbind, void());
   MOCK_METHOD0(Show, void());
   MOCK_METHOD0(Hide, void());
-  MOCK_METHOD1(ShowError, void(const base::string16& message));
-  MOCK_METHOD0(ClearErrors, void());
   MOCK_METHOD0(StopDemoModeDetection, void());
-  MOCK_METHOD2(ShowConnectingStatus,
-               void(bool connecting, const base::string16& network_id));
-  MOCK_METHOD1(EnableContinue, void(bool enabled));
   MOCK_METHOD0(ReloadLocalizedContent, void());
 
  private:
   WelcomeScreen* screen_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(MockWelcomeView);
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc
new file mode 100644
index 0000000..26721be
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -0,0 +1,204 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
+
+#include "base/location.h"
+#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+#include "chrome/browser/chromeos/login/screen_manager.h"
+#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/network_screen_view.h"
+#include "chrome/browser/chromeos/login/screens/screen_exit_code.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+constexpr base::TimeDelta kConnectionTimeout = base::TimeDelta::FromSeconds(40);
+
+constexpr char kUserActionBackButtonClicked[] = "back";
+constexpr char kUserActionContinueButtonClicked[] = "continue";
+
+}  // namespace
+
+namespace chromeos {
+
+// static
+NetworkScreen* NetworkScreen::Get(ScreenManager* manager) {
+  return static_cast<NetworkScreen*>(
+      manager->GetScreen(OobeScreen::SCREEN_OOBE_NETWORK));
+}
+
+NetworkScreen::NetworkScreen(BaseScreenDelegate* base_screen_delegate,
+                             NetworkScreenView* view)
+    : BaseScreen(base_screen_delegate, OobeScreen::SCREEN_OOBE_NETWORK),
+      view_(view),
+      network_state_helper_(std::make_unique<login::NetworkStateHelper>()) {
+  if (view_)
+    view_->Bind(this);
+}
+
+NetworkScreen::~NetworkScreen() {
+  if (view_)
+    view_->Unbind();
+  connection_timer_.Stop();
+  UnsubscribeNetworkNotification();
+}
+
+void NetworkScreen::OnViewDestroyed(NetworkScreenView* view) {
+  if (view_ == view) {
+    view_ = nullptr;
+    // Ownership of NetworkScreen is complicated; ensure that we remove
+    // this as a NetworkStateHandler observer when the view is destroyed.
+    UnsubscribeNetworkNotification();
+  }
+}
+
+void NetworkScreen::Show() {
+  Refresh();
+  if (view_)
+    view_->Show();
+}
+
+void NetworkScreen::Hide() {
+  if (view_)
+    view_->Hide();
+}
+
+void NetworkScreen::OnUserAction(const std::string& action_id) {
+  if (action_id == kUserActionContinueButtonClicked) {
+    OnContinueButtonClicked();
+  } else if (action_id == kUserActionBackButtonClicked) {
+    OnBackButtonClicked();
+  } else {
+    BaseScreen::OnUserAction(action_id);
+  }
+}
+
+void NetworkScreen::NetworkConnectionStateChanged(const NetworkState* network) {
+  UpdateStatus();
+}
+
+void NetworkScreen::DefaultNetworkChanged(const NetworkState* network) {
+  UpdateStatus();
+}
+
+void NetworkScreen::Refresh() {
+  SubscribeNetworkNotification();
+  UpdateStatus();
+}
+
+void NetworkScreen::SetNetworkStateHelperForTest(
+    login::NetworkStateHelper* helper) {
+  network_state_helper_.reset(helper);
+}
+
+void NetworkScreen::SubscribeNetworkNotification() {
+  if (!is_network_subscribed_) {
+    is_network_subscribed_ = true;
+    NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+                                                                FROM_HERE);
+  }
+}
+
+void NetworkScreen::UnsubscribeNetworkNotification() {
+  if (is_network_subscribed_) {
+    is_network_subscribed_ = false;
+    NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+                                                                   FROM_HERE);
+  }
+}
+
+void NetworkScreen::NotifyOnConnection() {
+  // TODO(nkostylev): Check network connectivity.
+  UnsubscribeNetworkNotification();
+  connection_timer_.Stop();
+  Finish(ScreenExitCode::NETWORK_CONNECTED);
+}
+
+void NetworkScreen::OnConnectionTimeout() {
+  StopWaitingForConnection(network_id_);
+  if (!network_state_helper_->IsConnected() && view_) {
+    // Show error bubble.
+    view_->ShowError(l10n_util::GetStringFUTF16(
+        IDS_NETWORK_SELECTION_ERROR,
+        l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME), network_id_));
+  }
+}
+
+void NetworkScreen::UpdateStatus() {
+  if (!view_)
+    return;
+
+  bool is_connected = network_state_helper_->IsConnected();
+  if (is_connected)
+    view_->ClearErrors();
+
+  base::string16 network_name = network_state_helper_->GetCurrentNetworkName();
+  if (is_connected)
+    StopWaitingForConnection(network_name);
+  else if (network_state_helper_->IsConnecting())
+    WaitForConnection(network_name);
+  else
+    StopWaitingForConnection(network_id_);
+}
+
+void NetworkScreen::StopWaitingForConnection(const base::string16& network_id) {
+  bool is_connected = network_state_helper_->IsConnected();
+  if (is_connected && continue_pressed_) {
+    NotifyOnConnection();
+    return;
+  }
+
+  continue_pressed_ = false;
+  connection_timer_.Stop();
+
+  network_id_ = network_id;
+  if (view_)
+    view_->ShowConnectingStatus(false, network_id_);
+
+  // Automatically continue if we are using Hands-Off Enrollment.
+  if (is_connected && continue_attempts_ == 0 &&
+      WizardController::UsingHandsOffEnrollment()) {
+    OnContinueButtonClicked();
+  }
+}
+
+void NetworkScreen::WaitForConnection(const base::string16& network_id) {
+  if (network_id_ != network_id || !connection_timer_.IsRunning()) {
+    connection_timer_.Stop();
+    connection_timer_.Start(FROM_HERE, kConnectionTimeout, this,
+                            &NetworkScreen::OnConnectionTimeout);
+  }
+
+  network_id_ = network_id;
+  if (view_)
+    view_->ShowConnectingStatus(continue_pressed_, network_id_);
+}
+
+void NetworkScreen::OnBackButtonClicked() {
+  if (view_)
+    view_->ClearErrors();
+  Finish(ScreenExitCode::NETWORK_BACK);
+}
+
+void NetworkScreen::OnContinueButtonClicked() {
+  ++continue_attempts_;
+  if (view_)
+    view_->ClearErrors();
+
+  if (network_state_helper_->IsConnected()) {
+    NotifyOnConnection();
+  } else {
+    continue_pressed_ = true;
+    WaitForConnection(network_id_);
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h
new file mode 100644
index 0000000..26a90c89
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -0,0 +1,121 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_H_
+
+#include <memory>
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/chromeos/login/screens/base_screen.h"
+#include "chromeos/network/network_state_handler_observer.h"
+
+namespace chromeos {
+
+class NetworkScreenView;
+class ScreenManager;
+
+namespace login {
+class NetworkStateHelper;
+}  // namespace login
+
+// Controls network selection screen shown during OOBE.
+class NetworkScreen : public BaseScreen, public NetworkStateHandlerObserver {
+ public:
+  NetworkScreen(BaseScreenDelegate* base_screen_delegate,
+                NetworkScreenView* view);
+  ~NetworkScreen() override;
+
+  // Returns instance of NetworkScreen.
+  static NetworkScreen* Get(ScreenManager* manager);
+
+  // Called when |view| has been destroyed. If this instance is destroyed before
+  // the |view| it should call view->Unbind().
+  void OnViewDestroyed(NetworkScreenView* view);
+
+ private:
+  friend class NetworkScreenTest;
+  friend class NetworkScreenUnitTest;
+  friend class DemoSetupTest;
+  FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, CanConnect);
+  FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, Timeout);
+  FRIEND_TEST_ALL_PREFIXES(NetworkScreenUnitTest, ContinuesAutomatically);
+  FRIEND_TEST_ALL_PREFIXES(NetworkScreenUnitTest, ContinuesOnlyOnce);
+
+  // BaseScreen:
+  void Show() override;
+  void Hide() override;
+  void OnUserAction(const std::string& action_id) override;
+
+  // NetworkStateHandlerObserver:
+  void NetworkConnectionStateChanged(const NetworkState* network) override;
+  void DefaultNetworkChanged(const NetworkState* network) override;
+
+  // Subscribes NetworkScreen to the network change notification, forces refresh
+  // of current network state.
+  void Refresh();
+
+  // Sets the NetworkStateHelper for use in tests. This class will take
+  // ownership of the pointed object.
+  void SetNetworkStateHelperForTest(login::NetworkStateHelper* helper);
+
+  // Subscribes to network change notifications.
+  void SubscribeNetworkNotification();
+
+  // Unsubscribes from network change notifications.
+  void UnsubscribeNetworkNotification();
+
+  // Notifies wizard on successful connection.
+  void NotifyOnConnection();
+
+  // Called by |connection_timer_| when connection to the network timed out.
+  void OnConnectionTimeout();
+
+  // Updates UI based on current network status.
+  void UpdateStatus();
+
+  // Stops waiting for network to connect.
+  void StopWaitingForConnection(const base::string16& network_id);
+
+  // Starts waiting for network connection. Shows spinner.
+  void WaitForConnection(const base::string16& network_id);
+
+  // Called when back button is clicked.
+  void OnBackButtonClicked();
+
+  // Called when continue button is clicked.
+  void OnContinueButtonClicked();
+
+  // True if subscribed to network change notification.
+  bool is_network_subscribed_ = false;
+
+  // ID of the network that we are waiting for.
+  base::string16 network_id_;
+
+  // Keeps track of the number of times OnContinueButtonClicked was called.
+  // OnContinueButtonClicked is called either in response to the user pressing
+  // the continue button, or automatically during hands-off enrollment after a
+  // network connection is established.
+  int continue_attempts_ = 0;
+
+  // True if the user pressed the continue button in the UI.
+  // Indicates that we should proceed with OOBE as soon as we are connected.
+  bool continue_pressed_ = false;
+
+  // Timer for connection timeout.
+  base::OneShotTimer connection_timer_;
+
+  NetworkScreenView* view_ = nullptr;
+  std::unique_ptr<login::NetworkStateHelper> network_state_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkScreen);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
similarity index 74%
rename from chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
rename to chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
index 382beca..e66e860 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
@@ -1,13 +1,14 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/login/screens/welcome_screen.h"
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
 
 #include <memory>
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/mock_network_state_helper.h"
@@ -41,46 +42,45 @@
   void ButtonPressed(views::Button* sender, const ui::Event& event) override {}
 };
 
-class WelcomeScreenTest : public WizardInProcessBrowserTest {
+class NetworkScreenTest : public WizardInProcessBrowserTest {
  public:
-  WelcomeScreenTest()
-      : WizardInProcessBrowserTest(OobeScreen::SCREEN_OOBE_WELCOME),
-        fake_session_manager_client_(nullptr) {}
+  NetworkScreenTest()
+      : WizardInProcessBrowserTest(OobeScreen::SCREEN_OOBE_NETWORK) {}
+  ~NetworkScreenTest() override = default;
 
  protected:
   void SetUpInProcessBrowserTestFixture() override {
     WizardInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
 
-    fake_session_manager_client_ = new FakeSessionManagerClient;
     DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+        std::make_unique<FakeSessionManagerClient>());
   }
 
   void SetUpOnMainThread() override {
     WizardInProcessBrowserTest::SetUpOnMainThread();
-    mock_base_screen_delegate_.reset(new MockBaseScreenDelegate());
+    mock_base_screen_delegate_ = std::make_unique<MockBaseScreenDelegate>();
     ASSERT_TRUE(WizardController::default_controller() != nullptr);
-    welcome_screen_ = WelcomeScreen::Get(
+    network_screen_ = NetworkScreen::Get(
         WizardController::default_controller()->screen_manager());
-    ASSERT_TRUE(welcome_screen_ != nullptr);
+    ASSERT_TRUE(network_screen_ != nullptr);
     ASSERT_EQ(WizardController::default_controller()->current_screen(),
-              welcome_screen_);
-    welcome_screen_->base_screen_delegate_ = mock_base_screen_delegate_.get();
-    ASSERT_TRUE(welcome_screen_->view_ != nullptr);
+              network_screen_);
+    network_screen_->base_screen_delegate_ = mock_base_screen_delegate_.get();
+    ASSERT_TRUE(network_screen_->view_ != nullptr);
 
     mock_network_state_helper_ = new login::MockNetworkStateHelper;
     SetDefaultNetworkStateHelperExpectations();
-    welcome_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
+    network_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
   }
 
-  void EmulateContinueButtonExit(WelcomeScreen* welcome_screen) {
+  void EmulateContinueButtonExit(NetworkScreen* network_screen) {
     EXPECT_CALL(*mock_base_screen_delegate_,
                 OnExit(_, ScreenExitCode::NETWORK_CONNECTED, _))
         .Times(1);
     EXPECT_CALL(*mock_network_state_helper_, IsConnected())
         .WillOnce(Return(true));
-    welcome_screen->OnContinueButtonPressed();
-    content::RunAllPendingInMessageLoop();
+    network_screen->OnContinueButtonClicked();
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetDefaultNetworkStateHelperExpectations() {
@@ -97,18 +97,17 @@
 
   std::unique_ptr<MockBaseScreenDelegate> mock_base_screen_delegate_;
   login::MockNetworkStateHelper* mock_network_state_helper_;
-  WelcomeScreen* welcome_screen_;
-  FakeSessionManagerClient* fake_session_manager_client_;
+  NetworkScreen* network_screen_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(WelcomeScreenTest);
+  DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
 };
 
-IN_PROC_BROWSER_TEST_F(WelcomeScreenTest, CanConnect) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, CanConnect) {
   EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
       .WillOnce((Return(true)));
   // EXPECT_FALSE(view_->IsContinueEnabled());
-  welcome_screen_->UpdateStatus();
+  network_screen_->UpdateStatus();
 
   EXPECT_CALL(*mock_network_state_helper_, IsConnected())
       .Times(2)
@@ -116,17 +115,17 @@
   // TODO(nkostylev): Add integration with WebUI view http://crosbug.com/22570
   // EXPECT_FALSE(view_->IsContinueEnabled());
   // EXPECT_FALSE(view_->IsConnecting());
-  welcome_screen_->UpdateStatus();
+  network_screen_->UpdateStatus();
 
   // EXPECT_TRUE(view_->IsContinueEnabled());
-  EmulateContinueButtonExit(welcome_screen_);
+  EmulateContinueButtonExit(network_screen_);
 }
 
-IN_PROC_BROWSER_TEST_F(WelcomeScreenTest, Timeout) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Timeout) {
   EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
       .WillOnce((Return(true)));
   // EXPECT_FALSE(view_->IsContinueEnabled());
-  welcome_screen_->UpdateStatus();
+  network_screen_->UpdateStatus();
 
   EXPECT_CALL(*mock_network_state_helper_, IsConnected())
       .Times(2)
@@ -134,7 +133,7 @@
   // TODO(nkostylev): Add integration with WebUI view http://crosbug.com/22570
   // EXPECT_FALSE(view_->IsContinueEnabled());
   // EXPECT_FALSE(view_->IsConnecting());
-  welcome_screen_->OnConnectionTimeout();
+  network_screen_->OnConnectionTimeout();
 
   // Close infobubble with error message - it makes the test stable.
   // EXPECT_FALSE(view_->IsContinueEnabled());
diff --git a/chrome/browser/chromeos/login/screens/network_screen_unittest.cc b/chrome/browser/chromeos/login/screens/network_screen_unittest.cc
new file mode 100644
index 0000000..d34e5cb5
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/network_screen_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/mock_network_screen.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_mock_time_message_loop_task_runner.h"
+#include "chrome/browser/chromeos/login/mock_network_state_helper.h"
+#include "chrome/browser/chromeos/login/screens/mock_base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/mock_model_view_channel.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::Return;
+
+namespace chromeos {
+
+class NetworkScreenUnitTest : public testing::Test {
+ public:
+  NetworkScreenUnitTest() = default;
+  ~NetworkScreenUnitTest() override = default;
+
+  // testing::Test:
+  void SetUp() override {
+    // Initialize the thread manager.
+    DBusThreadManager::Initialize();
+
+    // Configure the browser to use Hands-Off Enrollment.
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kEnterpriseEnableZeroTouchEnrollment, "hands-off");
+
+    // Create the NetworkScreen we will use for testing.
+    network_screen_ = std::make_unique<NetworkScreen>(
+        &mock_base_screen_delegate_, &mock_view_);
+    network_screen_->set_model_view_channel(&mock_channel_);
+    mock_network_state_helper_ = new login::MockNetworkStateHelper();
+    network_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
+  }
+
+  void TearDown() override {
+    TestingBrowserProcess::GetGlobal()->SetShuttingDown(true);
+    network_screen_.reset();
+    DBusThreadManager::Shutdown();
+  }
+
+ protected:
+  // A pointer to the NetworkScreen.
+  std::unique_ptr<NetworkScreen> network_screen_;
+
+  // Accessory objects needed by NetworkScreen.
+  MockBaseScreenDelegate mock_base_screen_delegate_;
+  login::MockNetworkStateHelper* mock_network_state_helper_ = nullptr;
+
+ private:
+  // Test versions of core browser infrastructure.
+  content::TestBrowserThreadBundle threads_;
+
+  // More accessory objects needed by NetworkScreen.
+  MockNetworkScreenView mock_view_;
+  MockModelViewChannel mock_channel_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkScreenUnitTest);
+};
+
+TEST_F(NetworkScreenUnitTest, ContinuesAutomatically) {
+  // Set expectation that NetworkScreen will finish.
+  EXPECT_CALL(mock_base_screen_delegate_,
+              OnExit(_, ScreenExitCode::NETWORK_CONNECTED, _))
+      .Times(1);
+
+  // Simulate a network connection.
+  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
+      .Times(AnyNumber())
+      .WillRepeatedly((Return(true)));
+  network_screen_->UpdateStatus();
+
+  // Check that we continued once
+  EXPECT_EQ(1, network_screen_->continue_attempts_);
+}
+
+TEST_F(NetworkScreenUnitTest, ContinuesOnlyOnce) {
+  // Set expectation that NetworkScreen will finish.
+  EXPECT_CALL(mock_base_screen_delegate_,
+              OnExit(_, ScreenExitCode::NETWORK_CONNECTED, _))
+      .Times(1);
+
+  // Connect to network "net0".
+  EXPECT_CALL(*mock_network_state_helper_, GetCurrentNetworkName())
+      .Times(AnyNumber())
+      .WillRepeatedly(Return(base::ASCIIToUTF16("net0")));
+  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
+      .Times(AnyNumber())
+      .WillRepeatedly(Return(true));
+
+  // Stop waiting for net0.
+  network_screen_->StopWaitingForConnection(base::ASCIIToUTF16("net0"));
+
+  // Check that we have continued exactly once.
+  ASSERT_EQ(1, network_screen_->continue_attempts_);
+
+  // Stop waiting for another network, net1.
+  network_screen_->StopWaitingForConnection(base::ASCIIToUTF16("net1"));
+
+  // Check that we have still continued only once.
+  EXPECT_EQ(1, network_screen_->continue_attempts_);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/network_screen_view.h b/chrome/browser/chromeos/login/screens/network_screen_view.h
new file mode 100644
index 0000000..cd796ae7
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/network_screen_view.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 CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_VIEW_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_VIEW_H_
+
+#include "base/strings/string16.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+
+namespace chromeos {
+
+class NetworkScreen;
+
+// Interface of network screen. Owned by NetworkScreen.
+class NetworkScreenView {
+ public:
+  constexpr static OobeScreen kScreenId = OobeScreen::SCREEN_OOBE_NETWORK;
+
+  virtual ~NetworkScreenView() {}
+
+  // Shows the contents of the screen.
+  virtual void Show() = 0;
+
+  // Hides the contents of the screen.
+  virtual void Hide() = 0;
+
+  // Binds |screen| to the view.
+  virtual void Bind(NetworkScreen* screen) = 0;
+
+  // Unbinds model from the view.
+  virtual void Unbind() = 0;
+
+  // Shows error message in a bubble.
+  virtual void ShowError(const base::string16& message) = 0;
+
+  // Hides error messages showing no error state.
+  virtual void ClearErrors() = 0;
+
+  // Shows network connecting status or network selection otherwise.
+  virtual void ShowConnectingStatus(bool connecting,
+                                    const base::string16& network_id) = 0;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_SCREEN_VIEW_H_
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.cc b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
index 41dad027..5e290c16 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.cc
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
@@ -10,8 +10,8 @@
 
 std::string ExitCodeToString(ScreenExitCode code) {
   switch (code) {
-    case ScreenExitCode::NETWORK_CONNECTED:
-      return "NETWORK_CONNECTED";
+    case ScreenExitCode::WELCOME_CONTINUED:
+      return "WELCOME_CONTINUED";
     case ScreenExitCode::HID_DETECTION_COMPLETED:
       return "HID_DETECTION_COMPLETED";
     case ScreenExitCode::CONNECTION_FAILED:
@@ -90,6 +90,10 @@
       return "ARC_TERMS_OF_SERVICE_BACK";
     case ScreenExitCode::DISCOVER_FINISHED:
       return "DISCOVER_FINISHED";
+    case ScreenExitCode::NETWORK_BACK:
+      return "NETWORK_BACK";
+    case ScreenExitCode::NETWORK_CONNECTED:
+      return "NETWORK_CONNECTED";
     case ScreenExitCode::EXIT_CODES_COUNT:
     default:
       NOTREACHED();
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.h b/chrome/browser/chromeos/login/screens/screen_exit_code.h
index 628006a7..a249dd60 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.h
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.h
@@ -19,8 +19,8 @@
 // Numeric ids are provided to facilitate interpretation of log files only,
 // they are subject to change without notice.
 enum class ScreenExitCode {
-  // "Continue" was pressed on welcome screen and network is online.
-  NETWORK_CONNECTED = 0,
+  // "Continue" was pressed on welcome screen.
+  WELCOME_CONTINUED = 0,
   HID_DETECTION_COMPLETED = 1,
   // Connection failed while trying to load a WebPageScreen.
   CONNECTION_FAILED = 2,
@@ -66,6 +66,8 @@
   APP_DOWNLOADING_FINISHED = 39,
   ARC_TERMS_OF_SERVICE_BACK = 40,
   DISCOVER_FINISHED = 41,
+  NETWORK_BACK = 42,
+  NETWORK_CONNECTED = 43,
   EXIT_CODES_COUNT  // not a real code, must be the last
 };
 
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.cc b/chrome/browser/chromeos/login/screens/welcome_screen.cc
index f9e8343..57e0ee4 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.cc
@@ -6,45 +6,36 @@
 
 #include <utility>
 
-#include "base/location.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/base/locale_util.h"
 #include "chrome/browser/chromeos/customization/customization_document.h"
-#include "chrome/browser/chromeos/login/help_app_launcher.h"
-#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/screen_manager.h"
 #include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/screen_exit_code.h"
 #include "chrome/browser/chromeos/login/screens/welcome_view.h"
 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/system/timezone_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_state_handler.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
-#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
-// Time in seconds for connection timeout.
-const int kConnectionTimeoutSec = 40;
-
-constexpr const char kUserActionContinueButtonClicked[] = "continue";
-constexpr const char kUserActionConnectDebuggingFeaturesClicked[] =
+constexpr char kUserActionContinueButtonClicked[] = "continue";
+constexpr char kUserActionConnectDebuggingFeaturesClicked[] =
     "connect-debugging-features";
-constexpr const char kContextKeyLocale[] = "locale";
-constexpr const char kContextKeyInputMethod[] = "input-method";
-constexpr const char kContextKeyTimezone[] = "timezone";
+constexpr char kContextKeyLocale[] = "locale";
+constexpr char kContextKeyInputMethod[] = "input-method";
+constexpr char kContextKeyTimezone[] = "timezone";
 
 }  // namespace
 
@@ -65,7 +56,6 @@
     : BaseScreen(base_screen_delegate, OobeScreen::SCREEN_OOBE_WELCOME),
       view_(view),
       delegate_(delegate),
-      network_state_helper_(new login::NetworkStateHelper),
       weak_factory_(this) {
   if (view_)
     view_->Bind(this);
@@ -79,8 +69,6 @@
 WelcomeScreen::~WelcomeScreen() {
   if (view_)
     view_->Unbind();
-  connection_timer_.Stop();
-  UnsubscribeNetworkNotification();
 
   input_method::InputMethodManager::Get()->RemoveObserver(this);
 }
@@ -92,9 +80,6 @@
   if (view_ == view) {
     view_ = nullptr;
     timezone_subscription_.reset();
-    // Ownership of WelcomeScreen is complicated; ensure that we remove
-    // this as a NetworkStateHandler observer when the view is destroyed.
-    UnsubscribeNetworkNotification();
   }
 }
 
@@ -143,21 +128,6 @@
   return timezone_;
 }
 
-void WelcomeScreen::GetConnectedWifiNetwork(std::string* out_onc_spec) {
-  // Currently We can only transfer unsecured WiFi configuration from shark to
-  // remora. There is no way to get password for a secured Wifi network in Cros
-  // for security reasons.
-  network_state_helper_->GetConnectedWifiNetwork(out_onc_spec);
-}
-
-void WelcomeScreen::CreateAndConnectNetworkFromOnc(
-    const std::string& onc_spec,
-    const base::Closure& success_callback,
-    const network_handler::ErrorCallback& error_callback) {
-  network_state_helper_->CreateAndConnectNetworkFromOnc(
-      onc_spec, success_callback, error_callback);
-}
-
 void WelcomeScreen::AddObserver(Observer* observer) {
   if (observer)
     observers_.AddObserver(observer);
@@ -172,8 +142,6 @@
 // BaseScreen implementation:
 
 void WelcomeScreen::Show() {
-  Refresh();
-
   // Here we should handle default locales, for which we do not have UI
   // resources. This would load fallback, but properly show "selected" locale
   // in the UI.
@@ -220,17 +188,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// WelcomeScreen, NetworkStateHandlerObserver implementation:
-
-void WelcomeScreen::NetworkConnectionStateChanged(const NetworkState* network) {
-  UpdateStatus();
-}
-
-void WelcomeScreen::DefaultNetworkChanged(const NetworkState* network) {
-  UpdateStatus();
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // WelcomeScreen, InputMethodManager::Observer implementation:
 
 void WelcomeScreen::InputMethodChanged(
@@ -282,112 +239,11 @@
                                   base::Unretained(this)));
 }
 
-void WelcomeScreen::Refresh() {
-  SubscribeNetworkNotification();
-  UpdateStatus();
-}
-
-void WelcomeScreen::SetNetworkStateHelperForTest(
-    login::NetworkStateHelper* helper) {
-  network_state_helper_.reset(helper);
-}
-
-void WelcomeScreen::SubscribeNetworkNotification() {
-  if (!is_network_subscribed_) {
-    is_network_subscribed_ = true;
-    NetworkHandler::Get()->network_state_handler()->AddObserver(this,
-                                                                FROM_HERE);
-  }
-}
-
-void WelcomeScreen::UnsubscribeNetworkNotification() {
-  if (is_network_subscribed_) {
-    is_network_subscribed_ = false;
-    NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
-                                                                   FROM_HERE);
-  }
-}
-
-void WelcomeScreen::NotifyOnConnection() {
-  // TODO(nkostylev): Check network connectivity.
-  UnsubscribeNetworkNotification();
-  connection_timer_.Stop();
-  Finish(ScreenExitCode::NETWORK_CONNECTED);
-}
-
-void WelcomeScreen::OnConnectionTimeout() {
-  StopWaitingForConnection(network_id_);
-  if (!network_state_helper_->IsConnected() && view_) {
-    // Show error bubble.
-    view_->ShowError(l10n_util::GetStringFUTF16(
-        IDS_NETWORK_SELECTION_ERROR,
-        l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME), network_id_));
-  }
-}
-
-void WelcomeScreen::UpdateStatus() {
-  if (!view_)
-    return;
-
-  bool is_connected = network_state_helper_->IsConnected();
-  if (is_connected)
-    view_->ClearErrors();
-
-  base::string16 network_name = network_state_helper_->GetCurrentNetworkName();
-  if (is_connected)
-    StopWaitingForConnection(network_name);
-  else if (network_state_helper_->IsConnecting())
-    WaitForConnection(network_name);
-  else
-    StopWaitingForConnection(network_id_);
-}
-
-void WelcomeScreen::StopWaitingForConnection(const base::string16& network_id) {
-  bool is_connected = network_state_helper_->IsConnected();
-  if (is_connected && continue_pressed_) {
-    NotifyOnConnection();
-    return;
-  }
-
-  continue_pressed_ = false;
-  connection_timer_.Stop();
-
-  network_id_ = network_id;
-  if (view_)
-    view_->ShowConnectingStatus(false, network_id_);
-
-  // Automatically continue if we are using Hands-Off Enrollment.
-  if (is_connected && continue_attempts_ == 0 &&
-      WizardController::UsingHandsOffEnrollment()) {
-    OnContinueButtonPressed();
-  }
-}
-
-void WelcomeScreen::WaitForConnection(const base::string16& network_id) {
-  if (network_id_ != network_id || !connection_timer_.IsRunning()) {
-    connection_timer_.Stop();
-    connection_timer_.Start(FROM_HERE,
-                            base::TimeDelta::FromSeconds(kConnectionTimeoutSec),
-                            this, &WelcomeScreen::OnConnectionTimeout);
-  }
-
-  network_id_ = network_id;
-  if (view_)
-    view_->ShowConnectingStatus(continue_pressed_, network_id_);
-}
-
 void WelcomeScreen::OnContinueButtonPressed() {
-  ++continue_attempts_;
   if (view_) {
     view_->StopDemoModeDetection();
-    view_->ClearErrors();
   }
-  if (network_state_helper_->IsConnected()) {
-    NotifyOnConnection();
-  } else {
-    continue_pressed_ = true;
-    WaitForConnection(network_id_);
-  }
+  Finish(ScreenExitCode::WELCOME_CONTINUED);
 }
 
 void WelcomeScreen::OnLanguageChangedCallback(
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.h b/chrome/browser/chromeos/login/screens/welcome_screen.h
index 667417e..c4d24709 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.h
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.h
@@ -6,20 +6,15 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WELCOME_SCREEN_H_
 
 #include <memory>
+#include <string>
 
 #include "base/callback_forward.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/strings/string16.h"
-#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/screens/base_screen.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chromeos/network/network_handler_callbacks.h"
-#include "chromeos/network/network_state_handler_observer.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 
 namespace chromeos {
@@ -32,12 +27,7 @@
 struct LanguageSwitchResult;
 }
 
-namespace login {
-class NetworkStateHelper;
-}
-
 class WelcomeScreen : public BaseScreen,
-                      public NetworkStateHandlerObserver,
                       public input_method::InputMethodManager::Observer {
  public:
   class Delegate {
@@ -85,35 +75,16 @@
   void SetTimezone(const std::string& timezone_id);
   std::string GetTimezone() const;
 
-  // Currently We can only get unsecured Wifi network configuration from shark
-  // that can be applied to remora. Returns the network ONC configuration.
-  void GetConnectedWifiNetwork(std::string* out_onc_spec);
-  void CreateAndConnectNetworkFromOnc(
-      const std::string& onc_spec,
-      const base::Closure& success_callback,
-      const network_handler::ErrorCallback& error_callback);
-
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
  private:
-  friend class WelcomeScreenTest;
-  friend class WelcomeScreenUnitTest;
-  FRIEND_TEST_ALL_PREFIXES(WelcomeScreenTest, Timeout);
-  FRIEND_TEST_ALL_PREFIXES(WelcomeScreenTest, CanConnect);
-  FRIEND_TEST_ALL_PREFIXES(WelcomeScreenUnitTest, ContinuesAutomatically);
-  FRIEND_TEST_ALL_PREFIXES(WelcomeScreenUnitTest, ContinuesOnlyOnce);
-
   // BaseScreen implementation:
   void Show() override;
   void Hide() override;
   void OnUserAction(const std::string& action_id) override;
   void OnContextKeyUpdated(const ::login::ScreenContext::KeyType& key) override;
 
-  // NetworkStateHandlerObserver implementation:
-  void NetworkConnectionStateChanged(const NetworkState* network) override;
-  void DefaultNetworkChanged(const NetworkState* network) override;
-
   // InputMethodManager::Observer implementation:
   void InputMethodChanged(input_method::InputMethodManager* manager,
                           Profile* profile,
@@ -125,35 +96,6 @@
   // Subscribe to timezone changes.
   void InitializeTimezoneObserver();
 
-  // Subscribes WelcomeScreen to the network change notification,
-  // forces refresh of current network state.
-  void Refresh();
-
-  // Sets the NetworkStateHelper for use in tests. This
-  // class will take ownership of the pointed object.
-  void SetNetworkStateHelperForTest(login::NetworkStateHelper* helper);
-
-  // Subscribes to network change notifications.
-  void SubscribeNetworkNotification();
-
-  // Unsubscribes from network change notifications.
-  void UnsubscribeNetworkNotification();
-
-  // Notifies wizard on successful connection.
-  void NotifyOnConnection();
-
-  // Called by |connection_timer_| when connection to the network timed out.
-  void OnConnectionTimeout();
-
-  // Update UI based on current network status.
-  void UpdateStatus();
-
-  // Stops waiting for network to connect.
-  void StopWaitingForConnection(const base::string16& network_id);
-
-  // Starts waiting for network connection. Shows spinner.
-  void WaitForConnection(const base::string16& network_id);
-
   // Called when continue button is pressed.
   void OnContinueButtonPressed();
 
@@ -177,30 +119,10 @@
   // Callback when the system timezone settings is changed.
   void OnSystemTimezoneChanged();
 
-  // True if subscribed to network change notification.
-  bool is_network_subscribed_ = false;
-
-  // ID of the the network that we are waiting for.
-  base::string16 network_id_;
-
-  // Keeps track of the number of times OnContinueButtonPressed was called.
-  // OnContinueButtonPressed is called either in response to the user
-  // pressing the continue button, or automatically during hands-off enrollment
-  // after a network connection is established.
-  int continue_attempts_ = 0;
-
-  // True if the user pressed the continue button in the UI.
-  // Indicates that we should proceed with OOBE as soon as we are connected.
-  bool continue_pressed_ = false;
-
-  // Timer for connection timeout.
-  base::OneShotTimer connection_timer_;
-
   std::unique_ptr<CrosSettings::ObserverSubscription> timezone_subscription_;
 
   WelcomeView* view_ = nullptr;
   Delegate* delegate_ = nullptr;
-  std::unique_ptr<login::NetworkStateHelper> network_state_helper_;
 
   std::string input_method_;
   std::string timezone_;
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen_unittest.cc b/chrome/browser/chromeos/login/screens/welcome_screen_unittest.cc
deleted file mode 100644
index 0f5e7e2e0..0000000
--- a/chrome/browser/chromeos/login/screens/welcome_screen_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_mock_time_message_loop_task_runner.h"
-#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
-#include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h"
-#include "chrome/browser/chromeos/login/mock_network_state_helper.h"
-#include "chrome/browser/chromeos/login/screens/mock_base_screen_delegate.h"
-#include "chrome/browser/chromeos/login/screens/mock_model_view_channel.h"
-#include "chrome/browser/chromeos/login/screens/mock_welcome_screen.h"
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/settings/device_settings_service.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/system/fake_statistics_provider.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/ime/chromeos/mock_component_extension_ime_manager.h"
-
-using testing::_;
-using testing::AnyNumber;
-using testing::Return;
-
-namespace chromeos {
-
-class WelcomeScreenUnitTest : public testing::Test {
- public:
-  WelcomeScreenUnitTest() {}
-
-  // testing::Test:
-  void SetUp() override {
-    // Initialize the thread manager.
-    DBusThreadManager::Initialize();
-
-    // Configure the browser to use Hands-Off Enrollment.
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kEnterpriseEnableZeroTouchEnrollment, "hands-off");
-
-    // Replace the regular InputMethodManager with a mock.
-    input_method::MockInputMethodManagerImpl* mock_input_manager =
-        new input_method::MockInputMethodManagerImpl();
-    mock_input_manager->SetComponentExtensionIMEManager(
-        std::unique_ptr<MockComponentExtensionIMEManager>(
-            new MockComponentExtensionIMEManager()));
-    input_method::InitializeForTesting(mock_input_manager);
-
-    // Create the WelcomeScreen we will use for testing.
-    welcome_screen_.reset(
-        new WelcomeScreen(&mock_base_screen_delegate_, nullptr, &mock_view_));
-    welcome_screen_->set_model_view_channel(&mock_channel_);
-    mock_network_state_helper_ = new login::MockNetworkStateHelper();
-    welcome_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
-  }
-
-  void TearDown() override {
-    TestingBrowserProcess::GetGlobal()->SetShuttingDown(true);
-    welcome_screen_.reset();
-    input_method::Shutdown();
-    DBusThreadManager::Shutdown();
-  }
-
- protected:
-  // A pointer to the WelcomeScreen.
-  std::unique_ptr<WelcomeScreen> welcome_screen_;
-
-  // Accessory objects needed by WelcomeScreen.
-  MockBaseScreenDelegate mock_base_screen_delegate_;
-  login::MockNetworkStateHelper* mock_network_state_helper_ = nullptr;
-
- private:
-  // Test versions of core browser infrastructure.
-  content::TestBrowserThreadBundle threads_;
-
-  // More accessory objects needed by WelcomeScreen.
-  MockWelcomeView mock_view_;
-  MockModelViewChannel mock_channel_;
-
-  // Scoped test versions of required global objects.
-  ScopedTestDeviceSettingsService device_settings_;
-  ScopedTestCrosSettings cros_settings_;
-  system::ScopedFakeStatisticsProvider provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(WelcomeScreenUnitTest);
-};
-
-TEST_F(WelcomeScreenUnitTest, ContinuesAutomatically) {
-  // Set expectation that WelcomeScreen will finish.
-  EXPECT_CALL(mock_base_screen_delegate_,
-              OnExit(_, ScreenExitCode::NETWORK_CONNECTED, _))
-      .Times(1);
-
-  // Simulate a network connection.
-  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
-      .Times(AnyNumber())
-      .WillRepeatedly((Return(true)));
-  welcome_screen_->UpdateStatus();
-
-  // Check that we continued once
-  EXPECT_EQ(1, welcome_screen_->continue_attempts_);
-}
-
-TEST_F(WelcomeScreenUnitTest, ContinuesOnlyOnce) {
-  // Set expectation that WelcomeScreen will finish.
-  EXPECT_CALL(mock_base_screen_delegate_,
-              OnExit(_, ScreenExitCode::NETWORK_CONNECTED, _))
-      .Times(1);
-
-  // Connect to network "net0".
-  EXPECT_CALL(*mock_network_state_helper_, GetCurrentNetworkName())
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(base::ASCIIToUTF16("net0")));
-  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(true));
-
-  // Stop waiting for net0.
-  welcome_screen_->StopWaitingForConnection(base::ASCIIToUTF16("net0"));
-
-  // Check that we have continued exactly once.
-  ASSERT_EQ(1, welcome_screen_->continue_attempts_);
-
-  // Stop waiting for another network, net1.
-  welcome_screen_->StopWaitingForConnection(base::ASCIIToUTF16("net1"));
-
-  // Check that we have still continued only once.
-  EXPECT_EQ(1, welcome_screen_->continue_attempts_);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/welcome_view.h b/chrome/browser/chromeos/login/screens/welcome_view.h
index 7e802331..0b7ccd8 100644
--- a/chrome/browser/chromeos/login/screens/welcome_view.h
+++ b/chrome/browser/chromeos/login/screens/welcome_view.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WELCOME_VIEW_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WELCOME_VIEW_H_
 
-#include "base/strings/string16.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
 
 namespace chromeos {
@@ -32,19 +31,9 @@
   // Unbinds model from the view.
   virtual void Unbind() = 0;
 
-  // Shows error message in a bubble.
-  virtual void ShowError(const base::string16& message) = 0;
-
-  // Hides error messages showing no error state.
-  virtual void ClearErrors() = 0;
-
   // Stops demo mode detection.
   virtual void StopDemoModeDetection() = 0;
 
-  // Shows network connecting status or network selection otherwise.
-  virtual void ShowConnectingStatus(bool connecting,
-                                    const base::string16& network_id) = 0;
-
   // Reloads localized contents.
   virtual void ReloadLocalizedContent() = 0;
 };
diff --git a/chrome/browser/chromeos/login/ui/fake_login_display_host.cc b/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
index f2ff591..ebee6661 100644
--- a/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
+++ b/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
@@ -140,6 +140,8 @@
 
 void FakeLoginDisplayHost::ShowFeedback() {}
 
+void FakeLoginDisplayHost::ShowResetScreen() {}
+
 void FakeLoginDisplayHost::ShowDialogForCaptivePortal() {}
 
 void FakeLoginDisplayHost::HideDialogForCaptivePortal() {}
diff --git a/chrome/browser/chromeos/login/ui/fake_login_display_host.h b/chrome/browser/chromeos/login/ui/fake_login_display_host.h
index 5d843c0a..a6415c54 100644
--- a/chrome/browser/chromeos/login/ui/fake_login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/fake_login_display_host.h
@@ -65,6 +65,7 @@
   void MigrateUserData(const std::string& old_password) override;
   void ResyncUserData() override;
   void ShowFeedback() override;
+  void ShowResetScreen() override;
   void ShowDialogForCaptivePortal() override;
   void HideDialogForCaptivePortal() override;
   void UpdateAddUserButtonStatus() override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host.h b/chrome/browser/chromeos/login/ui/login_display_host.h
index 8752c8c..ba21d944 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host.h
@@ -194,6 +194,9 @@
   // Shows a feedback report dialog.
   virtual void ShowFeedback() = 0;
 
+  // Shows the powerwash dialog.
+  virtual void ShowResetScreen() = 0;
+
   // In the views case, make the OobeUIDialogDelegate visible so that Captive
   // Portal web modal can be seen. In webui login, this should be a no-op.
   virtual void ShowDialogForCaptivePortal() = 0;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index a43a666..1fcc680 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -28,6 +28,7 @@
 
 constexpr char kLoginDisplay[] = "login";
 constexpr char kAccelSendFeedback[] = "send_feedback";
+constexpr char kAccelReset[] = "reset";
 
 }  // namespace
 
@@ -191,7 +192,10 @@
   }
 
   if (signin_screen_started_) {
+    // If we already have a signin screen instance, just reset the state of the
+    // oobe dialog.
     HideOobeDialog();
+    GetOobeUI()->GetGaiaScreenView()->ShowGaiaAsync(base::nullopt);
     return;
   }
 
@@ -308,6 +312,11 @@
   GetOobeUI()->ForwardAccelerator(kAccelSendFeedback);
 }
 
+void LoginDisplayHostMojo::ShowResetScreen() {
+  DCHECK(GetOobeUI());
+  GetOobeUI()->ForwardAccelerator(kAccelReset);
+}
+
 void LoginDisplayHostMojo::UpdateAddUserButtonStatus() {
   DCHECK(GetOobeUI());
   LoginScreenClient::Get()->login_screen()->SetAddUserButtonEnabled(
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
index e5ea154..1591ac0 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -92,6 +92,7 @@
   const user_manager::UserList GetUsers() override;
   void OnCancelPasswordChangedFlow() override;
   void ShowFeedback() override;
+  void ShowResetScreen() override;
   void ShowDialogForCaptivePortal() override;
   void HideDialogForCaptivePortal() override;
   void UpdateAddUserButtonStatus() override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
index 1797c700..adb7f006 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -1173,6 +1173,10 @@
   NOTREACHED();
 }
 
+void LoginDisplayHostWebUI::ShowResetScreen() {
+  NOTREACHED();
+}
+
 // This is handled differently in webui.
 void LoginDisplayHostWebUI::ShowDialogForCaptivePortal() {}
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.h b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
index 2891ac7..1fb0dbfd4 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
@@ -80,6 +80,7 @@
   void UpdateOobeDialogSize(int width, int height) override;
   const user_manager::UserList GetUsers() override;
   void ShowFeedback() override;
+  void ShowResetScreen() override;
   void ShowDialogForCaptivePortal() override;
   void HideDialogForCaptivePortal() override;
   void UpdateAddUserButtonStatus() override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
index e5097be..7d4249d1 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
@@ -74,8 +74,9 @@
 
   UserSelectionScreen* user_selection_screen = host_->user_selection_screen();
   user_selection_screen->Init(filtered_users);
-  client->login_screen()->LoadUsers(
-      user_selection_screen->UpdateAndReturnUserListForMojo(), show_guest);
+  client->login_screen()->SetUserList(
+      user_selection_screen->UpdateAndReturnUserListForMojo());
+  client->login_screen()->SetAllowLoginAsGuest(show_guest);
   user_selection_screen->SetUsersLoaded(true /*loaded*/);
 
   // Enable pin for any users who can use it.
diff --git a/chrome/browser/chromeos/login/ui/mock_login_display_host.h b/chrome/browser/chromeos/login/ui/mock_login_display_host.h
index d308a59..dbaa6e4 100644
--- a/chrome/browser/chromeos/login/ui/mock_login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/mock_login_display_host.h
@@ -72,6 +72,7 @@
   MOCK_METHOD1(MigrateUserData, void(const std::string&));
   MOCK_METHOD0(ResyncUserData, void());
   MOCK_METHOD0(ShowFeedback, void());
+  MOCK_METHOD0(ShowResetScreen, void());
   MOCK_METHOD0(OnCancelPasswordChangedFlow, void());
   MOCK_METHOD0(ShowDialogForCaptivePortal, void());
   MOCK_METHOD0(HideDialogForCaptivePortal, void());
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
index d80fed1..4a49016c 100644
--- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
+++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h"
 
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_mojo.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -84,7 +85,8 @@
 }
 
 void OobeUIDialogDelegate::Show() {
-  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogVisibility(true);
+  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogState(
+      ash::mojom::OobeDialogState::GAIA_SIGNIN);
   dialog_widget_->Show();
 }
 
@@ -101,14 +103,16 @@
 void OobeUIDialogDelegate::Hide() {
   if (!dialog_widget_)
     return;
-  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogVisibility(false);
+  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogState(
+      ash::mojom::OobeDialogState::HIDDEN);
   dialog_widget_->Hide();
 }
 
 void OobeUIDialogDelegate::Close() {
   if (!dialog_widget_)
     return;
-  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogVisibility(false);
+  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogState(
+      ash::mojom::OobeDialogState::HIDDEN);
   dialog_widget_->Close();
 }
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 43b446c..1f2d31a4 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -51,6 +51,7 @@
 #include "chrome/browser/chromeos/login/screens/kiosk_autolaunch_screen.h"
 #include "chrome/browser/chromeos/login/screens/kiosk_enable_screen.h"
 #include "chrome/browser/chromeos/login/screens/network_error.h"
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
 #include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h"
 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
 #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h"
@@ -89,6 +90,8 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/geolocation/simple_geolocation_provider.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_handler_callbacks.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
@@ -127,6 +130,7 @@
 // Stores the list of all screens that should be shown when resuming OOBE.
 const chromeos::OobeScreen kResumableScreens[] = {
     chromeos::OobeScreen::SCREEN_OOBE_WELCOME,
+    chromeos::OobeScreen::SCREEN_OOBE_NETWORK,
     chromeos::OobeScreen::SCREEN_OOBE_UPDATE,
     chromeos::OobeScreen::SCREEN_OOBE_EULA,
     chromeos::OobeScreen::SCREEN_OOBE_ENROLLMENT,
@@ -290,7 +294,9 @@
 PrefService* WizardController::local_state_for_testing_ = nullptr;
 
 WizardController::WizardController()
-    : screen_manager_(std::make_unique<ScreenManager>()), weak_factory_(this) {
+    : screen_manager_(std::make_unique<ScreenManager>()),
+      network_state_helper_(std::make_unique<login::NetworkStateHelper>()),
+      weak_factory_(this) {
   // In session OOBE was initiated from voice interaction keyboard shortcuts.
   is_in_session_oobe_ =
       session_manager::SessionManager::Get()->IsSessionStarted();
@@ -398,6 +404,9 @@
   if (screen == OobeScreen::SCREEN_OOBE_WELCOME) {
     return std::make_unique<WelcomeScreen>(this, this,
                                            oobe_ui->GetWelcomeView());
+  } else if (screen == OobeScreen::SCREEN_OOBE_NETWORK) {
+    return std::make_unique<NetworkScreen>(this,
+                                           oobe_ui->GetNetworkScreenView());
   } else if (screen == OobeScreen::SCREEN_OOBE_UPDATE) {
     return std::make_unique<UpdateScreen>(this, oobe_ui->GetUpdateView(),
                                           remora_controller_.get());
@@ -517,6 +526,12 @@
     MaybeStartListeningForSharkConnection();
 }
 
+void WizardController::ShowNetworkScreen() {
+  VLOG(1) << "Showing network screen.";
+  UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_NETWORK));
+}
+
 void WizardController::ShowLoginScreen(const LoginScreenContext& context) {
   // This may be triggered by multiply asynchronous events from the JS side.
   if (login_screen_started_)
@@ -801,10 +816,24 @@
     ShowWelcomeScreen();
 }
 
+void WizardController::OnWelcomeContinued() {
+  ShowNetworkScreen();
+}
+
+void WizardController::OnNetworkBack() {
+  if (is_in_demo_setup_flow_) {
+    ShowDemoModePreferencesScreen();
+  } else {
+    ShowWelcomeScreen();
+  }
+}
+
 void WizardController::OnNetworkConnected() {
   if (is_official_build_) {
     if (!StartupUtils::IsEulaAccepted()) {
       ShowEulaScreen();
+    } else if (arc::IsArcTermsOfServiceOobeNegotiationNeeded()) {
+      ShowArcTermsOfServiceScreen();
     } else {
       // Possible cases:
       // 1. EULA was accepted, forced shutdown/reboot during update.
@@ -823,6 +852,11 @@
 }
 
 void WizardController::OnUpdateCompleted() {
+  if (is_in_demo_setup_flow_) {
+    ShowDemoModeSetupScreen();
+    return;
+  }
+
   if (IsSharkRequisition() || IsBootstrappingMaster()) {
     ShowControllerPairingScreen();
   } else if (IsControllerDetected()) {
@@ -854,11 +888,7 @@
 }
 
 void WizardController::OnEulaBack() {
-  if (is_in_demo_setup_flow_) {
-    ShowDemoModePreferencesScreen();
-  } else {
-    ShowWelcomeScreen();
-  }
+    ShowNetworkScreen();
 }
 
 void WizardController::OnChangedMetricsReportingState(bool enabled) {
@@ -884,11 +914,10 @@
 void WizardController::OnUpdateErrorUpdating(bool is_critical_update) {
   // If there was an error while getting or applying the update, return to
   // network selection screen if the OOBE isn't complete and the update is
-  // deemed critical. Otherwise, similar to OnUpdateErrorCheckingForUpdate(),
-  // we do not want to block users from being able to proceed to the login
-  // screen.
+  // deemed critical. Otherwise, similar to OnUpdateErrorCheckingForUpdate(), we
+  // do not want to block users from being able to proceed to the login screen.
   if (is_out_of_box_ && is_critical_update)
-    ShowWelcomeScreen();
+    ShowNetworkScreen();
   else
     OnUpdateCompleted();
 }
@@ -983,7 +1012,7 @@
 
 void WizardController::OnArcTermsOfServiceAccepted() {
   if (is_in_demo_setup_flow_) {
-    ShowDemoModeSetupScreen();
+    InitiateOOBEUpdate();
     return;
   }
 
@@ -1004,7 +1033,8 @@
 
 void WizardController::OnArcTermsOfServiceBack() {
   DCHECK(is_in_demo_setup_flow_);
-  ShowPreviousScreen();
+  DCHECK(StartupUtils::IsEulaAccepted());
+  ShowNetworkScreen();
 }
 
 void WizardController::OnRecommendAppsSkipped() {
@@ -1066,7 +1096,7 @@
 
 void WizardController::OnDemoPreferencesContinued() {
   DCHECK(is_in_demo_setup_flow_);
-  ShowEulaScreen();
+  ShowNetworkScreen();
 }
 
 void WizardController::OnDemoPreferencesCanceled() {
@@ -1290,6 +1320,8 @@
 void WizardController::AdvanceToScreen(OobeScreen screen) {
   if (screen == OobeScreen::SCREEN_OOBE_WELCOME) {
     ShowWelcomeScreen();
+  } else if (screen == OobeScreen::SCREEN_OOBE_NETWORK) {
+    ShowNetworkScreen();
   } else if (screen == OobeScreen::SCREEN_SPECIAL_LOGIN) {
     ShowLoginScreen(LoginScreenContext());
   } else if (screen == OobeScreen::SCREEN_OOBE_UPDATE) {
@@ -1397,6 +1429,12 @@
     case ScreenExitCode::HID_DETECTION_COMPLETED:
       OnHIDDetectionCompleted();
       break;
+    case ScreenExitCode::WELCOME_CONTINUED:
+      OnWelcomeContinued();
+      break;
+    case ScreenExitCode::NETWORK_BACK:
+      OnNetworkBack();
+      break;
     case ScreenExitCode::NETWORK_CONNECTED:
       OnNetworkConnected();
       break;
@@ -1540,9 +1578,8 @@
 void WizardController::SetHostNetwork() {
   if (!shark_controller_)
     return;
-  WelcomeScreen* welcome_screen = WelcomeScreen::Get(screen_manager());
   std::string onc_spec;
-  welcome_screen->GetConnectedWifiNetwork(&onc_spec);
+  network_state_helper_->GetConnectedWifiNetwork(&onc_spec);
   if (!onc_spec.empty())
     shark_controller_->SetHostNetwork(onc_spec);
 }
@@ -1586,16 +1623,14 @@
   remora_controller_->OnNetworkConnectivityChanged(
       pairing_chromeos::HostPairingController::CONNECTIVITY_CONNECTING);
 
-  WelcomeScreen* welcome_screen = WelcomeScreen::Get(screen_manager());
   const chromeos::NetworkState* network_state = chromeos::NetworkHandler::Get()
                                                     ->network_state_handler()
                                                     ->DefaultNetwork();
-
   if (NetworkAllowUpdate(network_state)) {
-    welcome_screen->CreateAndConnectNetworkFromOnc(
+    network_state_helper_->CreateAndConnectNetworkFromOnc(
         onc_spec, base::DoNothing(), network_handler::ErrorCallback());
   } else {
-    welcome_screen->CreateAndConnectNetworkFromOnc(
+    network_state_helper_->CreateAndConnectNetworkFromOnc(
         onc_spec,
         base::Bind(&WizardController::OnSetHostNetworkSuccessful,
                    weak_factory_.GetWeakPtr()),
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 22c0da0..a554362 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -40,6 +40,10 @@
 
 namespace chromeos {
 
+namespace login {
+class NetworkStateHelper;
+}  // namespace login
+
 class ErrorScreen;
 struct Geoposition;
 class LoginDisplayHost;
@@ -152,6 +156,7 @@
  private:
   // Show specific screen.
   void ShowWelcomeScreen();
+  void ShowNetworkScreen();
   void ShowUserImageScreen();
   void ShowEulaScreen();
   void ShowEnrollmentScreen();
@@ -188,6 +193,8 @@
 
   // Exit handlers:
   void OnHIDDetectionCompleted();
+  void OnWelcomeContinued();
+  void OnNetworkBack();
   void OnNetworkConnected();
   void OnConnectionFailed();
   void OnUpdateCompleted();
@@ -440,6 +447,8 @@
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, Accelerators);
   FRIEND_TEST_ALL_PREFIXES(WizardControllerDeviceStateTest,
                            ControlFlowNoForcedReEnrollmentOnFirstBoot);
+
+  friend class DemoSetupTest;
   friend class WizardControllerBrokenLocalStateTest;
   friend class WizardControllerDemoSetupTest;
   friend class WizardControllerDeviceStateTest;
@@ -460,6 +469,9 @@
   // Pairing controller for remora devices.
   std::unique_ptr<pairing_chromeos::HostPairingController> remora_controller_;
 
+  // Helper for network realted operations.
+  std::unique_ptr<login::NetworkStateHelper> network_state_helper_;
+
   // Maps screen names to last time of their shows.
   std::map<std::string, base::Time> screen_show_times_;
 
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index a9fca51..07670a56 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/chromeos/login/screens/mock_device_disabled_screen_view.h"
 #include "chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_eula_screen.h"
+#include "chrome/browser/chromeos/login/screens/mock_network_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_update_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_welcome_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h"
@@ -571,6 +572,8 @@
     EXPECT_CALL(*mock_welcome_screen_, Show()).Times(0);
     EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(0);
 
+    MOCK(mock_network_screen_, OobeScreen::SCREEN_OOBE_NETWORK,
+         MockNetworkScreen, MockNetworkScreenView);
     MOCK(mock_update_screen_, OobeScreen::SCREEN_OOBE_UPDATE, MockUpdateScreen,
          MockUpdateView);
     MOCK_WITH_DELEGATE(mock_eula_screen_, OobeScreen::SCREEN_OOBE_EULA,
@@ -722,6 +725,8 @@
   }
 
   MockWelcomeScreen* mock_welcome_screen_;  // Unowned ptr.
+  MockOutShowHide<MockNetworkScreen, MockNetworkScreenView>*
+      mock_network_screen_;
   MockOutShowHide<MockUpdateScreen, MockUpdateView>* mock_update_screen_;
   MockOutShowHide<MockEulaScreen, MockEulaView>* mock_eula_screen_;
   MockOutShowHide<MockEnrollmentScreen, MockEnrollmentScreenView>*
@@ -766,11 +771,16 @@
                        ControlFlowErrorUpdateNonCriticalUpdate) {
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -802,11 +812,16 @@
                        ControlFlowErrorUpdateCriticalUpdate) {
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -821,22 +836,26 @@
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(0);
-  EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(NotNull(), _)).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(0);  // last transition
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(0);  // last transition
   OnExit(*mock_update_screen_,
          ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE);
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
 }
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowSkipUpdateEnroll) {
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -868,20 +887,23 @@
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowEulaDeclined) {
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
-  EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(NotNull(), _)).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(0);  // last transition
   OnExit(*mock_eula_screen_, ScreenExitCode::EULA_BACK);
 
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
 }
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest,
@@ -948,11 +970,16 @@
   const ScreenExitCode update_screen_exit_code = GetParam();
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1047,8 +1074,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1075,8 +1107,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1160,8 +1197,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1244,8 +1286,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1397,8 +1444,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1467,8 +1519,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1558,8 +1615,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1597,8 +1659,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1648,8 +1715,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1699,8 +1771,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1777,8 +1854,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1935,8 +2017,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -1979,8 +2066,13 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+  OnExit(*mock_welcome_screen_, ScreenExitCode::WELCOME_CONTINUED);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  OnExit(*mock_welcome_screen_, ScreenExitCode::NETWORK_CONNECTED);
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
@@ -2061,6 +2153,7 @@
 class WizardControllerDemoSetupTest : public WizardControllerFlowTest {
  protected:
   WizardControllerDemoSetupTest() = default;
+  ~WizardControllerDemoSetupTest() override = default;
 
   // InProcessBrowserTest:
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -2077,6 +2170,14 @@
     return WizardController::default_controller()->is_in_demo_setup_flow_;
   }
 
+  template <class T, class H>
+  void SkipToScreen(OobeScreen screen, MockOutShowHide<T, H>* screen_mock) {
+    EXPECT_CALL(*screen_mock, Show()).Times(1);
+    auto* const wizard_controller = WizardController::default_controller();
+    wizard_controller->SimulateDemoModeSetupForTesting();
+    wizard_controller->AdvanceToScreen(screen);
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WizardControllerDemoSetupTest);
 };
@@ -2096,11 +2197,19 @@
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_demo_preferences_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
 
   OnExit(*mock_demo_preferences_screen_,
          ScreenExitCode::DEMO_MODE_PREFERENCES_CONTINUED);
 
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
+
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
@@ -2113,11 +2222,21 @@
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_arc_terms_of_service_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_setup_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
 
   OnExit(*mock_arc_terms_of_service_screen_,
          ScreenExitCode::ARC_TERMS_OF_SERVICE_ACCEPTED);
 
+  base::RunLoop().RunUntilIdle();
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+
+  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_demo_setup_screen_, Show()).Times(1);
+
+  OnExit(*mock_arc_terms_of_service_screen_, ScreenExitCode::UPDATE_INSTALLED);
+
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_SETUP);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
@@ -2143,11 +2262,19 @@
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_demo_preferences_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
 
   OnExit(*mock_demo_preferences_screen_,
          ScreenExitCode::DEMO_MODE_PREFERENCES_CONTINUED);
 
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+
+  OnExit(*mock_network_screen_, ScreenExitCode::NETWORK_CONNECTED);
+
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
@@ -2160,11 +2287,22 @@
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_arc_terms_of_service_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_setup_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
 
   OnExit(*mock_arc_terms_of_service_screen_,
          ScreenExitCode::ARC_TERMS_OF_SERVICE_ACCEPTED);
 
+  // Let update screen smooth time process (time = 0ms).
+  base::RunLoop().RunUntilIdle();
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+
+  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_demo_setup_screen_, Show()).Times(1);
+
+  OnExit(*mock_arc_terms_of_service_screen_, ScreenExitCode::UPDATE_INSTALLED);
+
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_SETUP);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
@@ -2182,11 +2320,8 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_FALSE(IsInDemoSetupFlow());
   WaitUntilJSIsReady();
-
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_preferences_screen_, Show()).Times(1);
-
-  WizardController::default_controller()->StartDemoModeSetup();
+  SkipToScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES,
+               mock_demo_preferences_screen_);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES);
   EXPECT_TRUE(IsInDemoSetupFlow());
@@ -2201,34 +2336,39 @@
   EXPECT_FALSE(IsInDemoSetupFlow());
 }
 
+IN_PROC_BROWSER_TEST_F(WizardControllerDemoSetupTest, NetworkBackPressed) {
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
+  EXPECT_FALSE(IsInDemoSetupFlow());
+  WaitUntilJSIsReady();
+  SkipToScreen(OobeScreen::SCREEN_OOBE_NETWORK, mock_network_screen_);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_demo_preferences_screen_, Show()).Times(1);
+
+  OnExit(*mock_eula_screen_, ScreenExitCode::NETWORK_BACK);
+
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES);
+  EXPECT_TRUE(IsInDemoSetupFlow());
+}
+
 IN_PROC_BROWSER_TEST_F(WizardControllerDemoSetupTest, EulaBackPressed) {
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_FALSE(IsInDemoSetupFlow());
   WaitUntilJSIsReady();
-
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_preferences_screen_, Show()).Times(1);
-
-  WizardController::default_controller()->StartDemoModeSetup();
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES);
-  EXPECT_TRUE(IsInDemoSetupFlow());
-
-  EXPECT_CALL(*mock_demo_preferences_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-
-  OnExit(*mock_demo_preferences_screen_,
-         ScreenExitCode::DEMO_MODE_PREFERENCES_CONTINUED);
+  SkipToScreen(OobeScreen::SCREEN_OOBE_EULA, mock_eula_screen_);
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_preferences_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
 
   OnExit(*mock_eula_screen_, ScreenExitCode::EULA_BACK);
 
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES);
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_TRUE(IsInDemoSetupFlow());
 }
 
@@ -2237,38 +2377,21 @@
   EXPECT_FALSE(IsInDemoSetupFlow());
   WaitUntilJSIsReady();
 
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_demo_preferences_screen_, Show()).Times(1);
-
-  WizardController::default_controller()->StartDemoModeSetup();
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES);
-  EXPECT_TRUE(IsInDemoSetupFlow());
-
-  EXPECT_CALL(*mock_demo_preferences_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-
-  OnExit(*mock_demo_preferences_screen_,
-         ScreenExitCode::DEMO_MODE_PREFERENCES_CONTINUED);
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
-  EXPECT_TRUE(IsInDemoSetupFlow());
-
-  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_arc_terms_of_service_screen_, Show()).Times(1);
-
-  OnExit(*mock_eula_screen_, ScreenExitCode::EULA_ACCEPTED);
+  // User cannot go to ARC ToS screen without accepting eula - simulate that.
+  StartupUtils::MarkEulaAccepted();
+  SkipToScreen(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE,
+               mock_arc_terms_of_service_screen_);
 
   CheckCurrentScreen(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE);
   EXPECT_TRUE(IsInDemoSetupFlow());
 
   EXPECT_CALL(*mock_arc_terms_of_service_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
 
   OnExit(*mock_arc_terms_of_service_screen_,
          ScreenExitCode::ARC_TERMS_OF_SERVICE_BACK);
 
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
+  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
   EXPECT_TRUE(IsInDemoSetupFlow());
 }
 
@@ -2434,7 +2557,7 @@
 // TODO(rsgingerrs): Add tests for Recommend Apps UI.
 
 // TODO(alemate): Add tests for Discover UI.
-static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 42,
+static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 44,
               "tests for new control flow are missing");
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
index 29e2862..a487065 100644
--- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
@@ -200,9 +200,9 @@
   if (value) {
     std::string onc_blob;
     value->GetAsString(&onc_blob);
-    std::unique_ptr<base::DictionaryValue> root_dict =
+    std::unique_ptr<base::Value> root_dict =
         chromeos::onc::ReadDictionaryFromJson(onc_blob);
-    if (root_dict.get() == NULL) {
+    if (!root_dict) {
       errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED);
       return false;
     }
@@ -289,9 +289,10 @@
     return NULL;
 
   std::unique_ptr<base::DictionaryValue> toplevel_dict =
-      chromeos::onc::ReadDictionaryFromJson(json_string);
+      base::DictionaryValue::From(
+          chromeos::onc::ReadDictionaryFromJson(json_string));
   if (!toplevel_dict)
-    return NULL;
+    return nullptr;
 
   // Placeholder to insert in place of the filtered setting.
   const char kPlaceholder[] = "********";
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
index 14aeda3..98e28a9 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
@@ -248,17 +248,18 @@
     providers.push_back(&provider_);
     policy_service_ = std::make_unique<PolicyServiceImpl>(std::move(providers));
 
-    std::unique_ptr<base::DictionaryValue> fake_toplevel_onc =
+    std::unique_ptr<base::Value> fake_toplevel_onc =
         chromeos::onc::ReadDictionaryFromJson(kFakeONC);
 
-    base::DictionaryValue* global_config = NULL;
-    fake_toplevel_onc->GetDictionaryWithoutPathExpansion(
-        onc::toplevel_config::kGlobalNetworkConfiguration, &global_config);
+    base::DictionaryValue* global_config = nullptr;
+    fake_toplevel_onc
+        ->FindKey(onc::toplevel_config::kGlobalNetworkConfiguration)
+        ->GetAsDictionary(&global_config);
     fake_global_network_config_.MergeDictionary(global_config);
 
-    base::ListValue* certs = NULL;
-    fake_toplevel_onc->GetListWithoutPathExpansion(
-        onc::toplevel_config::kCertificates, &certs);
+    base::ListValue* certs = nullptr;
+    fake_toplevel_onc->FindKey(onc::toplevel_config::kCertificates)
+        ->GetAsList(&certs);
     fake_certificates_ =
         std::make_unique<chromeos::onc::OncParsedCertificates>(*certs);
 
@@ -267,7 +268,7 @@
   }
 
   base::Value* GetExpectedFakeNetworkConfigs(::onc::ONCSource source) {
-    std::unique_ptr<base::DictionaryValue> fake_toplevel_onc =
+    std::unique_ptr<base::Value> fake_toplevel_onc =
         chromeos::onc::ReadDictionaryFromJson(kFakeONC);
     fake_network_configs_ =
         fake_toplevel_onc->FindKey(onc::toplevel_config::kNetworkConfigurations)
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index 9084632..fdda59f 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -514,8 +514,8 @@
   SetUpSharedEthernet();
   SetUpProxyConfigService(&profile_prefs_);
 
-  std::unique_ptr<base::DictionaryValue> ethernet_policy(
-      chromeos::onc::ReadDictionaryFromJson(kEthernetPolicy));
+  std::unique_ptr<base::Value> ethernet_policy =
+      chromeos::onc::ReadDictionaryFromJson(kEthernetPolicy);
 
   std::unique_ptr<base::ListValue> network_configs(new base::ListValue);
   network_configs->Append(std::move(ethernet_policy));
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc
index 91df152..f75b26b 100644
--- a/chrome/browser/download/download_history.cc
+++ b/chrome/browser/download/download_history.cc
@@ -13,15 +13,16 @@
 // When the DownloadManager and its delegate (ChromeDownloadManagerDelegate) are
 // initialized, DownloadHistory is created and queries the HistoryService. When
 // the HistoryService calls back from QueryDownloads() to QueryCallback(),
-// DownloadHistory uses DownloadManager::CreateDownloadItem() to inform
-// DownloadManager of these persisted DownloadItems. CreateDownloadItem()
+// DownloadHistory will then wait for DownloadManager to call
+// LoadHistoryDownloads(), and uses DownloadManager::CreateDownloadItem() to
+// inform DownloadManager of these persisted DownloadItems. CreateDownloadItem()
 // internally calls OnDownloadCreated(), which normally adds items to the
-// database, so QueryCallback() uses |loading_id_| to disable adding these items
-// to the database.  If a download is removed via OnDownloadRemoved() while the
-// item is still being added to the database, DownloadHistory uses
-// |removed_while_adding_| to remember to remove the item when its ItemAdded()
-// callback is called.  All callbacks are bound with a weak pointer to
-// DownloadHistory to prevent use-after-free bugs.
+// database, so LoadHistoryDownloads() uses |loading_id_| to disable adding
+// these items to the database.  If a download is removed via
+// OnDownloadRemoved() while the item is still being added to the database,
+// DownloadHistory uses |removed_while_adding_| to remember to remove the item
+// when its ItemAdded() callback is called.  All callbacks are bound with a weak
+// pointer to DownloadHistory to prevent use-after-free bugs.
 // ChromeDownloadManagerDelegate owns DownloadHistory, and deletes it in
 // Shutdown(), which is called by DownloadManagerImpl::Shutdown() after all
 // DownloadItems are destroyed.
@@ -335,6 +336,7 @@
         history::ToContentDownloadInterruptReason(it->interrupt_reason),
         it->opened, it->last_access_time, it->transient,
         history::ToContentReceivedSlices(it->download_slice_info));
+    CreateDownloadHistoryData(item, true);
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) {
       new extensions::DownloadedByExtension(
@@ -440,19 +442,8 @@
 void DownloadHistory::OnDownloadCreated(content::DownloadManager* manager,
                                         download::DownloadItem* item) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // All downloads should pass through OnDownloadCreated exactly once.
-  CHECK(!DownloadHistoryData::Get(item));
-  DownloadHistoryData* data = new DownloadHistoryData(item);
-  if (item->GetId() == loading_id_) {
-    data->SetState(DownloadHistoryData::PERSISTED);
-    data->set_was_restored_from_history(true);
-    loading_id_ = download::DownloadItem::kInvalidId;
-  }
-  if (item->GetState() == download::DownloadItem::IN_PROGRESS) {
-    data->set_info(GetDownloadRow(item));
-  }
-  MaybeAddToHistory(item);
+  if (item->GetId() != loading_id_)
+    CreateDownloadHistoryData(item, false);
 }
 
 void DownloadHistory::OnDownloadUpdated(content::DownloadManager* manager,
@@ -539,3 +530,19 @@
   for (Observer& observer : observers_)
     observer.OnDownloadsRemoved(remove_ids);
 }
+
+void DownloadHistory::CreateDownloadHistoryData(
+    download::DownloadItem* item,
+    bool was_restored_from_history) {
+  CHECK(!DownloadHistoryData::Get(item));
+  DownloadHistoryData* data = new DownloadHistoryData(item);
+  if (was_restored_from_history) {
+    DCHECK(item->GetId() == loading_id_);
+    loading_id_ = download::DownloadItem::kInvalidId;
+    data->SetState(DownloadHistoryData::PERSISTED);
+    data->set_was_restored_from_history(true);
+  }
+  if (item->GetState() == download::DownloadItem::IN_PROGRESS)
+    data->set_info(GetDownloadRow(item));
+  MaybeAddToHistory(item);
+}
diff --git a/chrome/browser/download/download_history.h b/chrome/browser/download/download_history.h
index 496c874..7748e59 100644
--- a/chrome/browser/download/download_history.h
+++ b/chrome/browser/download/download_history.h
@@ -135,6 +135,10 @@
   // Removes all |removing_ids_| from |history_|.
   void RemoveDownloadsBatch();
 
+  // Creates DownloadHistoryData and attach it to the |item|.
+  void CreateDownloadHistoryData(download::DownloadItem* item,
+                                 bool was_restored_from_history);
+
   download::AllDownloadItemNotifier notifier_;
 
   std::unique_ptr<HistoryAdapter> history_;
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
index d29ba90..244c8779 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
+#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h"
 #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h"
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
index 90b1b90..987e885 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
@@ -11,12 +11,20 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/api_resource.h"
 #include "extensions/browser/api/api_resource_manager.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
 
 namespace cryptauth {
 class Connection;
 }  // namespace cryptauth
 
 namespace extensions {
+
+class EasyUnlockPrivateConnection;
+
+template <>
+BrowserContextKeyedAPIFactory<ApiResourceManager<EasyUnlockPrivateConnection>>*
+ApiResourceManager<EasyUnlockPrivateConnection>::GetFactoryInstance();
+
 // An ApiResource wrapper for a cryptauth::Connection.
 class EasyUnlockPrivateConnection : public ApiResource {
  public:
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index 535ae7fd..ec40a5a 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -62,6 +62,7 @@
 #include "extensions/common/features/feature_channel.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/updater/chromeos_extension_cache_delegate.h"
 #include "chrome/browser/extensions/updater/extension_cache_impl.h"
@@ -293,8 +294,9 @@
 
 bool ChromeExtensionsBrowserClient::IsInDemoMode() {
 #if defined(OS_CHROMEOS)
-  // TODO(michaelpg): Implement for real.
-  return false;
+  const chromeos::DemoSession* const demo_session =
+      chromeos::DemoSession::Get();
+  return demo_session && demo_session->started();
 #else
   return false;
 #endif
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index 1fff89e..b412ffb4 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -179,6 +179,27 @@
   histogram_tester.ExpectUniqueSample("Tabs.SadTab.CrashCreated", 1, 1);
 }
 
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, HeapCorruptionInRenderer) {
+  base::HistogramTester histogram_tester;
+
+  OpenTabsAndNavigateToCrashyUrl(content::kChromeUIHeapCorruptionCrashURL);
+
+  // Verify that the expected stability metrics were recorded.
+  const PrefService* prefs = g_browser_process->local_state();
+  EXPECT_EQ(1, prefs->GetInteger(metrics::prefs::kStabilityLaunchCount));
+  // The three tabs from OpenTabs() and the one tab to open chrome://crash/.
+  EXPECT_EQ(4, prefs->GetInteger(metrics::prefs::kStabilityPageLoadCount));
+  EXPECT_EQ(1, prefs->GetInteger(metrics::prefs::kStabilityRendererCrashCount));
+
+  histogram_tester.ExpectUniqueSample(
+      "CrashExitCodes.Renderer",
+      std::abs(static_cast<int32_t>(STATUS_HEAP_CORRUPTION)), 1);
+  histogram_tester.ExpectUniqueSample("Tabs.SadTab.CrashCreated", 1, 1);
+  LOG(INFO) << histogram_tester.GetAllHistogramsRecorded();
+}
+#endif  // OS_WIN
+
 IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, MAYBE_CheckCrashRenderers) {
   base::HistogramTester histogram_tester;
 
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc
index bb6e49e..010a2e25 100644
--- a/chrome/browser/notifications/platform_notification_service_impl.cc
+++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -11,11 +11,13 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
+#include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/notifications/metrics/notification_metrics_logger.h"
 #include "chrome/browser/notifications/metrics/notification_metrics_logger_factory.h"
 #include "chrome/browser/notifications/notification_common.h"
@@ -52,6 +54,7 @@
 #include "content/public/common/notification_resources.h"
 #include "content/public/common/platform_notification_data.h"
 #include "extensions/buildflags/buildflags.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -74,6 +77,7 @@
 
 using content::BrowserContext;
 using content::BrowserThread;
+using content::NotificationDatabaseData;
 using message_center::NotifierId;
 
 namespace {
@@ -340,6 +344,32 @@
   return next_id;
 }
 
+void PlatformNotificationServiceImpl::RecordNotificationUkmEvent(
+    BrowserContext* browser_context,
+    const NotificationDatabaseData& data) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // Only record the event if a user explicitly interacted with the notification
+  // to close it.
+  if (data.closed_reason != NotificationDatabaseData::ClosedReason::USER &&
+      data.num_clicks == 0 && data.num_action_button_clicks == 0) {
+    return;
+  }
+
+  // Query the HistoryService so we only record a notification if the origin is
+  // in the user's history.
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+  history::HistoryService* history_service =
+      HistoryServiceFactory::GetForProfile(profile,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+  DCHECK(history_service);
+  history_service->QueryURL(
+      data.origin, /*want_visits=*/false,
+      base::BindOnce(
+          &PlatformNotificationServiceImpl::OnUrlHistoryQueryComplete,
+          base::Unretained(this), data),
+      &task_tracker_);
+}
+
 void PlatformNotificationServiceImpl::OnClickEventDispatchComplete(
     base::OnceClosure completed_closure,
     content::PersistentNotificationStatus status) {
@@ -368,6 +398,38 @@
   std::move(completed_closure).Run();
 }
 
+void PlatformNotificationServiceImpl::OnUrlHistoryQueryComplete(
+    const content::NotificationDatabaseData& data,
+    bool found_url,
+    const history::URLRow& url_row,
+    const history::VisitVector& visits) {
+  // Post the |history_query_complete_closure_for_testing_| closure to the
+  // current task runner to inform tests that the history query has completed.
+  if (history_query_complete_closure_for_testing_) {
+    base::PostTask(FROM_HERE,
+                   std::move(history_query_complete_closure_for_testing_));
+  }
+
+  // Only record the notification if the |data.origin| is in the history
+  // service.
+  if (!found_url)
+    return;
+
+  ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
+  DCHECK(recorder);
+  // We are using UpdateSourceURL as notifications are not tied to a navigation.
+  // This is ok from a privacy perspective as we have explicitly verified that
+  // |data.origin| is in the HistoryService before recording to UKM.
+  ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+  recorder->UpdateSourceURL(source_id, data.origin);
+
+  ukm::builders::Notification(source_id)
+      .SetClosedReason(static_cast<int>(data.closed_reason))
+      .SetNumClicks(data.num_clicks)
+      .SetNumActionButtonClicks(data.num_action_button_clicks)
+      .Record(recorder);
+}
+
 message_center::Notification
 PlatformNotificationServiceImpl::CreateNotificationFromData(
     Profile* profile,
diff --git a/chrome/browser/notifications/platform_notification_service_impl.h b/chrome/browser/notifications/platform_notification_service_impl.h
index 3b80694..4ec348a3 100644
--- a/chrome/browser/notifications/platform_notification_service_impl.h
+++ b/chrome/browser/notifications/platform_notification_service_impl.h
@@ -19,9 +19,12 @@
 #include "base/memory/singleton.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
+#include "base/task/cancelable_task_tracker.h"
 #include "chrome/browser/notifications/notification_common.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/buildflags.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_types.h"
 #include "content/public/browser/platform_notification_service.h"
 #include "content/public/common/persistent_notification_status.h"
 #include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
@@ -95,6 +98,14 @@
       const DisplayedNotificationsCallback& callback) override;
   int64_t ReadNextPersistentNotificationId(
       content::BrowserContext* browser_context) override;
+  void RecordNotificationUkmEvent(
+      content::BrowserContext* browser_context,
+      const content::NotificationDatabaseData& data) override;
+
+  void set_history_query_complete_closure_for_testing(
+      base::OnceClosure closure) {
+    history_query_complete_closure_for_testing_ = std::move(closure);
+  }
 
  private:
   friend struct base::DefaultSingletonTraits<PlatformNotificationServiceImpl>;
@@ -105,6 +116,8 @@
                            CreateNotificationFromData);
   FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest,
                            DisplayNameForContextMessage);
+  FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest,
+                           RecordNotificationUkmEvent);
 
   PlatformNotificationServiceImpl();
   ~PlatformNotificationServiceImpl() override;
@@ -115,6 +128,10 @@
   void OnCloseEventDispatchComplete(
       base::OnceClosure completed_closure,
       content::PersistentNotificationStatus status);
+  void OnUrlHistoryQueryComplete(const content::NotificationDatabaseData& data,
+                                 bool found_url,
+                                 const history::URLRow& url_row,
+                                 const history::VisitVector& visits);
 
   // Creates a new Web Notification-based Notification object. Should only be
   // called when the notification is first shown.
@@ -149,6 +166,13 @@
   // programmatically to avoid dispatching close events for them.
   std::unordered_set<std::string> closed_notifications_;
 
+  // Task tracker used for querying URLs in the history service.
+  base::CancelableTaskTracker task_tracker_;
+
+  // Testing-only closure to observe when querying the history service has been
+  // completed, and the result of logging UKM can be observed.
+  base::OnceClosure history_query_complete_closure_for_testing_;
+
   DISALLOW_COPY_AND_ASSIGN(PlatformNotificationServiceImpl);
 };
 
diff --git a/chrome/browser/notifications/platform_notification_service_unittest.cc b/chrome/browser/notifications/platform_notification_service_unittest.cc
index a2c60f1..98e0af0 100644
--- a/chrome/browser/notifications/platform_notification_service_unittest.cc
+++ b/chrome/browser/notifications/platform_notification_service_unittest.cc
@@ -10,22 +10,29 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/feature_list.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/notifications/metrics/mock_notification_metrics_logger.h"
 #include "chrome/browser/notifications/metrics/notification_metrics_logger_factory.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/history/core/browser/history_database_params.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/test/test_history_database.h"
+#include "components/ukm/test_ukm_recorder.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/common/notification_resources.h"
 #include "content/public/common/platform_notification_data.h"
 #include "content/public/test/mock_permission_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/buildflags/buildflags.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
@@ -43,12 +50,16 @@
 using ::testing::Return;
 using content::NotificationResources;
 using content::PlatformNotificationData;
+using content::NotificationDatabaseData;
 using message_center::Notification;
 
 namespace {
 
 const char kNotificationId[] = "my-notification-id";
 const int kNotificationVibrationPattern[] = { 100, 200, 300 };
+const char kClosedReason[] = "ClosedReason";
+const char kNumClicks[] = "NumClicks";
+const char kNumActionButtonClicks[] = "NumActionButtonClicks";
 
 class TestingProfileWithPermissionManager : public TestingProfile {
  public:
@@ -91,6 +102,8 @@
         NotificationMetricsLoggerFactory::GetInstance()
             ->SetTestingFactoryAndUse(
                 &profile_, &MockNotificationMetricsLogger::FactoryForTests));
+
+    recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
   }
 
   void TearDown() override {
@@ -125,6 +138,8 @@
 
   // Owned by the |profile_| as a keyed service.
   MockNotificationMetricsLogger* mock_logger_;
+
+  std::unique_ptr<ukm::TestAutoSetUkmRecorder> recorder_;
 };
 
 TEST_F(PlatformNotificationServiceTest, DisplayNonPersistentThenClose) {
@@ -276,6 +291,107 @@
   EXPECT_TRUE(buttons[1].placeholder);
 }
 
+TEST_F(PlatformNotificationServiceTest, RecordNotificationUkmEventHistory) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  HistoryServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+      &profile_, [](content::BrowserContext* context) {
+        return static_cast<std::unique_ptr<KeyedService>>(
+            std::make_unique<history::HistoryService>());
+      });
+
+  history::HistoryService* history_service =
+      HistoryServiceFactory::GetForProfile(&profile_,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+
+  // Initialize the |history_service| based on our |temp_dir|.
+  history_service->Init(
+      history::TestHistoryDatabaseParamsForPath(temp_dir.GetPath()));
+
+  NotificationDatabaseData data;
+  data.closed_reason = NotificationDatabaseData::ClosedReason::USER;
+  data.origin = GURL("https://chrome.com/");
+
+  size_t initial_entries_count = recorder_->entries_count();
+  size_t expected_entries_count = initial_entries_count + 1;
+
+  // First attempt to record an event for |data.origin| before it has been added
+  // to the |history_service|. Nothing should be recorded.
+  service()->RecordNotificationUkmEvent(&profile_, data);
+  {
+    base::RunLoop run_loop;
+    service()->set_history_query_complete_closure_for_testing(
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  EXPECT_EQ(recorder_->entries_count(), initial_entries_count);
+
+  // Now add |data.origin| to the |history_service|. After this, notification
+  // events being logged should end up in UKM.
+  history_service->AddPage(data.origin, base::Time::Now(),
+                           history::SOURCE_BROWSED);
+
+  service()->RecordNotificationUkmEvent(&profile_, data);
+  {
+    base::RunLoop run_loop;
+    service()->set_history_query_complete_closure_for_testing(
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  EXPECT_EQ(recorder_->entries_count(), expected_entries_count);
+
+  // Delete the |data.origin| from the |history_service|. Subsequent events
+  // should not be logged to UKM anymore.
+  history_service->DeleteURL(data.origin);
+
+  service()->RecordNotificationUkmEvent(&profile_, data);
+  {
+    base::RunLoop run_loop;
+    service()->set_history_query_complete_closure_for_testing(
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  EXPECT_EQ(recorder_->entries_count(), expected_entries_count);
+}
+
+TEST_F(PlatformNotificationServiceTest, RecordNotificationUkmEvent) {
+  NotificationDatabaseData data;
+  data.notification_id = "notification1";
+  data.closed_reason = NotificationDatabaseData::ClosedReason::USER;
+  data.num_clicks = 3;
+  data.num_action_button_clicks = 1;
+  history::URLRow url_row;
+  history::VisitVector visits;
+
+  // The history service does not find the given URL and nothing is recorded.
+  service()->OnUrlHistoryQueryComplete(data, false, url_row, visits);
+  std::vector<const ukm::mojom::UkmEntry*> entries =
+      recorder_->GetEntriesByName(ukm::builders::Notification::kEntryName);
+  EXPECT_EQ(0u, entries.size());
+
+  // The history service finds the given URL and the notification is logged.
+  service()->OnUrlHistoryQueryComplete(data, true, url_row, visits);
+  auto* entry =
+      recorder_->GetEntriesByName(ukm::builders::Notification::kEntryName)[0];
+  recorder_->ExpectEntryMetric(
+      entry, kClosedReason,
+      static_cast<int>(NotificationDatabaseData::ClosedReason::USER));
+  recorder_->ExpectEntryMetric(entry, kNumClicks, 3);
+  recorder_->ExpectEntryMetric(entry, kNumActionButtonClicks, 1);
+}
+
+// Expect each call to ReadNextPersistentNotificationId to return a larger
+// value.
+TEST_F(PlatformNotificationServiceTest, NextPersistentNotificationId) {
+  int64_t first_id = service()->ReadNextPersistentNotificationId(&profile_);
+  int64_t second_id = service()->ReadNextPersistentNotificationId(&profile_);
+  EXPECT_LT(first_id, second_id);
+}
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 
 TEST_F(PlatformNotificationServiceTest, DisplayNameForContextMessage) {
@@ -341,12 +457,4 @@
             base::UTF16ToUTF8(notification.context_message()));
 }
 
-// Expect each call to ReadNextPersistentNotificationId to return a larger
-// value.
-TEST_F(PlatformNotificationServiceTest, NextPersistentNotificationId) {
-  int64_t first_id = service()->ReadNextPersistentNotificationId(&profile_);
-  int64_t second_id = service()->ReadNextPersistentNotificationId(&profile_);
-  EXPECT_LT(first_id, second_id);
-}
-
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 5ad7d13e..7c009cf 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -497,7 +497,7 @@
 // Tests that updating video src when video is in Picture-in-Picture session
 // keep Picture-in-Picture window opened.
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       DISABLED_UpdateVideoSrcKeepsPictureInPictureWindowOpened) {
+                       UpdateVideoSrcKeepsPictureInPictureWindowOpened) {
   LoadTabAndEnterPictureInPicture(browser());
 
   EXPECT_TRUE(window_controller()->GetWindowForTesting()->IsVisible());
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
index 19344bf..b52efa42 100644
--- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc
+++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -12,7 +12,6 @@
 #include "components/certificate_transparency/pref_names.h"
 #include "components/component_updater/pref_names.h"
 #include "components/consent_auditor/pref_names.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
 #include "components/dom_distiller/core/pref_names.h"
 #include "components/flags_ui/flags_ui_pref_names.h"
 #include "components/google/core/browser/google_pref_names.h"
@@ -932,75 +931,6 @@
     cryptauth::prefs::kCryptAuthGCMRegistrationId,
 #endif  // defined(CHROMEOS)
 
-    // components/data_reduction_proxy/core/common/
-    // data_reduction_proxy_pref_names.h
-    data_reduction_proxy::prefs::
-        kDailyContentLengthHttpsWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthLongBypassWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthShortBypassWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthUnknownWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxy,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthViaDataReductionProxyApplication,
-    data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxyVideo,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthViaDataReductionProxyUnknown,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthWithDataReductionProxyEnabledApplication,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthWithDataReductionProxyEnabledVideo,
-    data_reduction_proxy::prefs::
-        kDailyContentLengthWithDataReductionProxyEnabledUnknown,
-    data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate,
-    data_reduction_proxy::prefs::kDailyHttpOriginalContentLength,
-    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthApplication,
-    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthVideo,
-    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthUnknown,
-    data_reduction_proxy::prefs::kDailyHttpReceivedContentLength,
-    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthApplication,
-    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthVideo,
-    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthUnknown,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthViaDataReductionProxy,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthViaDataReductionProxyApplication,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthViaDataReductionProxyVideo,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthViaDataReductionProxyUnknown,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthWithDataReductionProxyEnabled,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo,
-    data_reduction_proxy::prefs::
-        kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
-    data_reduction_proxy::prefs::kDataReductionProxy,
-    data_reduction_proxy::prefs::kDataReductionProxyConfig,
-    data_reduction_proxy::prefs::kDataUsageReportingEnabled,
-    data_reduction_proxy::prefs::kDataReductionProxyWasEnabledBefore,
-    data_reduction_proxy::prefs::kDataReductionProxyLastEnabledTime,
-    data_reduction_proxy::prefs::
-        kDataReductionProxySavingsClearedNegativeSystemClock,
-    data_reduction_proxy::prefs::kHttpOriginalContentLength,
-    data_reduction_proxy::prefs::kHttpReceivedContentLength,
-    data_reduction_proxy::prefs::kDataReductionProxyLastConfigRetrievalTime,
-    data_reduction_proxy::prefs::kNetworkProperties,
-
-    data_reduction_proxy::prefs::kThisWeekNumber,
-    data_reduction_proxy::prefs::kThisWeekServicesDownstreamBackgroundKB,
-    data_reduction_proxy::prefs::kThisWeekServicesDownstreamForegroundKB,
-    data_reduction_proxy::prefs::kLastWeekServicesDownstreamBackgroundKB,
-    data_reduction_proxy::prefs::kLastWeekServicesDownstreamForegroundKB,
-    data_reduction_proxy::prefs::kThisWeekUserTrafficContentTypeDownstreamKB,
-    data_reduction_proxy::prefs::kLastWeekUserTrafficContentTypeDownstreamKB,
-
     // components/dom_distiller/core/pref_names.h
     dom_distiller::prefs::kFont, dom_distiller::prefs::kTheme,
     dom_distiller::prefs::kFontScale,
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
index 3d20ea7..d29deae 100644
--- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
+++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -164,11 +164,18 @@
     delete localStorage['voiceName'];
   }
 
-  window.speechSynthesis.onvoiceschanged = function() {
-    chrome.storage.local.get({voiceName: ''}, function(items) {
-      this.updateVoice_(items.voiceName);
-    }.bind(this));
-  }.bind(this);
+  if (window.speechSynthesis) {
+    window.speechSynthesis.onvoiceschanged = function() {
+      chrome.storage.local.get({voiceName: ''}, function(items) {
+        this.updateVoice_(items.voiceName);
+      }.bind(this));
+    }.bind(this);
+  } else {
+    // SpeechSynthesis API is not available on chromecast. Call
+    // updateVoice_ to set the one and only voice as the current
+    // voice.
+    this.updateVoice_(undefined);
+  }
 
   chrome.storage.onChanged.addListener(function(changes, namespace) {
     if (changes.voiceName) {
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_pt-PT.xtb b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_pt-PT.xtb
index 86be081..36067e9 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_pt-PT.xtb
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_pt-PT.xtb
@@ -633,7 +633,7 @@
 <translation id="6065293622157674001">Início de erro de gramática</translation>
 <translation id="6082768461603900813">Navegação básica</translation>
 <translation id="6092707270915298410">Fim do link</translation>
-<translation id="6118126368611144850">Aplicações Android para o Chrome. Se tiver a Play Store instalada no seu dispositivo, conheça em primeira mão o ChromeVox com aplicações Android. Transfira o Google Chrome Canary a partir da Play Store para experimentar o suporte experimental.</translation>
+<translation id="6118126368611144850">Aplicações Android para o Chrome. Se tiver a Play Store instalada no seu dispositivo, conheça em primeira mão o ChromeVox com aplicações para Android. Transfira o Google Chrome Canary a partir da Play Store para experimentar o suporte experimental.</translation>
 <translation id="611827076493383239">vtd</translation>
 <translation id="6119955456199054975">Fim da célula.</translation>
 <translation id="6122013438240733403">btn</translation>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
index 7155b105..7ea225e 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -27,8 +27,8 @@
 <include src="oobe_update.html">
 <include src="oobe_i18n_dropdown.html">
 <include src="oobe_welcome_dialog.html">
-<include src="oobe_network_dialog.html">
-<include src="oobe_network_dialog_icons.html">
+<include src="oobe_network.html">
+<include src="oobe_network_icons.html">
 <include src="oobe_welcome.html">
 <include src="oobe_voice_interaction_value_prop.html">
 <include src="oobe_wait_for_container_ready.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
index cd30bbf..3a96876a 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -39,7 +39,7 @@
 // <include src="oobe_i18n_dropdown.js">
 // <include src="oobe_welcome_dialog.js">
 // <include src="oobe_welcome.js">
-// <include src="oobe_network_dialog.js">
+// <include src="oobe_network.js">
 // <include src="offline_ad_login.js">
 // <include src="active_directory_password_change.js">
 // <include src="arc_terms_of_service.js">
diff --git a/chrome/browser/resources/chromeos/login/md_header_bar.js b/chrome/browser/resources/chromeos/login/md_header_bar.js
index 33f89d4d..f669c4bc 100644
--- a/chrome/browser/resources/chromeos/login/md_header_bar.js
+++ b/chrome/browser/resources/chromeos/login/md_header_bar.js
@@ -301,6 +301,9 @@
     set signinUIState(state) {
       this.signinUIState_ = state;
       this.updateUI_();
+
+      if (Oobe.getInstance().showingViewsLogin)
+        chrome.send('updateSigninUIState', [state]);
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index 49a6d37..a72c6192 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -11,14 +11,15 @@
 // <include src="login_non_lock_shared.js">
 // <include src="oobe_screen_auto_enrollment_check.js">
 // <include src="oobe_screen_controller_pairing.js">
+// <include src="oobe_screen_demo_setup.js">
+// <include src="oobe_screen_demo_preferences.js">
 // <include src="oobe_screen_enable_debugging.js">
 // <include src="oobe_screen_eula.js">
 // <include src="oobe_screen_hid_detection.js">
 // <include src="oobe_screen_host_pairing.js">
-// <include src="oobe_screen_welcome.js">
+// <include src="oobe_screen_network.js">
 // <include src="oobe_screen_update.js">
-// <include src="oobe_screen_demo_setup.js">
-// <include src="oobe_screen_demo_preferences.js">
+// <include src="oobe_screen_welcome.js">
 
 cr.define('cr.ui.Oobe', function() {
   return {
@@ -31,6 +32,7 @@
       login.HIDDetectionScreen.register();
       login.WrongHWIDScreen.register();
       login.WelcomeScreen.register();
+      login.NetworkScreen.register();
       login.EulaScreen.register();
       login.UpdateScreen.register();
       login.AutoEnrollmentCheckScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/oobe_network_dialog.css b/chrome/browser/resources/chromeos/login/oobe_network.css
similarity index 100%
rename from chrome/browser/resources/chromeos/login/oobe_network_dialog.css
rename to chrome/browser/resources/chromeos/login/oobe_network.css
diff --git a/chrome/browser/resources/chromeos/login/oobe_network_dialog.html b/chrome/browser/resources/chromeos/login/oobe_network.html
similarity index 92%
rename from chrome/browser/resources/chromeos/login/oobe_network_dialog.html
rename to chrome/browser/resources/chromeos/login/oobe_network.html
index f8fa54f..c47c7e2 100644
--- a/chrome/browser/resources/chromeos/login/oobe_network_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_network.html
@@ -2,10 +2,10 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 
-<dom-module id="oobe-network-dialog">
+<dom-module id="oobe-network-md">
   <template>
     <link rel="stylesheet" href="oobe_flex_layout.css">
-    <link rel="stylesheet" href="oobe_network_dialog.css">
+    <link rel="stylesheet" href="oobe_network.css">
     <oobe-dialog id="networkDialog" role="dialog" on-show-dialog="onShown_"
         aria-label$="[[i18nDynamic(locale, 'networkSectionTitle')]]"
         has-buttons>
diff --git a/chrome/browser/resources/chromeos/login/oobe_network_dialog.js b/chrome/browser/resources/chromeos/login/oobe_network.js
similarity index 89%
rename from chrome/browser/resources/chromeos/login/oobe_network_dialog.js
rename to chrome/browser/resources/chromeos/login/oobe_network.js
index aad2d7f..27ff1db 100644
--- a/chrome/browser/resources/chromeos/login/oobe_network_dialog.js
+++ b/chrome/browser/resources/chromeos/login/oobe_network.js
@@ -7,7 +7,7 @@
  */
 
 Polymer({
-  is: 'oobe-network-dialog',
+  is: 'oobe-network-md',
 
   behaviors: [I18nBehavior, OobeDialogHostBehavior],
 
@@ -54,7 +54,7 @@
    * @private
    */
   onNextClicked_: function() {
-    this.fire('next-button-clicked');
+    chrome.send('login.NetworkScreen.userActed', ['continue']);
   },
 
   /**
@@ -62,7 +62,7 @@
    * @private
    */
   onBackClicked_: function() {
-    this.fire('back-button-clicked');
+    chrome.send('login.NetworkScreen.userActed', ['back']);
   },
 
 });
diff --git a/chrome/browser/resources/chromeos/login/oobe_network_dialog_icons.html b/chrome/browser/resources/chromeos/login/oobe_network_icons.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/oobe_network_dialog_icons.html
rename to chrome/browser/resources/chromeos/login/oobe_network_icons.html
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.html b/chrome/browser/resources/chromeos/login/oobe_screen_network.html
new file mode 100644
index 0000000..04e8282
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.html
@@ -0,0 +1,3 @@
+<div class="step hidden animated" id="network-selection" role="group" hidden>
+  <oobe-network-md id="oobe-network-md"></oobe-network-md>
+</div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.js b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
new file mode 100644
index 0000000..1f8b9e8
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview OOBE network selection screen implementation.
+ */
+
+login.createScreen('NetworkScreen', 'network-selection', function() {
+  return {
+    EXTERNAL_API: ['showError'],
+
+    /** Dropdown element for networks selection. */
+    dropdown_: null,
+
+    /** @override */
+    decorate: function() {
+      var networkScreen = $('oobe-network-md');
+      networkScreen.screen = this;
+      networkScreen.enabled = true;
+    },
+
+    /** Returns a control which should receive an initial focus. */
+    get defaultControl() {
+      return $('oobe-network-md');
+    },
+
+    /**
+     * Shows the network error message.
+     * @param {string} message Message to be shown.
+     */
+    showError: function(message) {
+      var error = document.createElement('div');
+      var messageDiv = document.createElement('div');
+      messageDiv.className = 'error-message-bubble';
+      messageDiv.textContent = message;
+      error.appendChild(messageDiv);
+      error.setAttribute('role', 'alert');
+    },
+
+    /** This is called after resources are updated. */
+    updateLocalizedContent: function() {
+      $('oobe-network-md').updateLocalizedContent();
+    },
+  };
+});
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js b/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js
index a7f19e8..ae6a4248 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js
@@ -12,12 +12,7 @@
   var CONTEXT_KEY_TIMEZONE = 'timezone';
 
   return {
-    EXTERNAL_API: ['showError'],
-
-    /**
-     * Dropdown element for networks selection.
-     */
-    dropdown_: null,
+    EXTERNAL_API: [],
 
     /** @override */
     decorate: function() {
@@ -58,7 +53,7 @@
      * @type {string}
      */
     get header() {
-      return loadTimeData.getString('networkScreenTitle');
+      return loadTimeData.getString('welcomeScreenTitle');
     },
 
     /**
@@ -69,19 +64,6 @@
     },
 
     /**
-     * Shows the network error message.
-     * @param {string} message Message to be shown.
-     */
-    showError: function(message) {
-      var error = document.createElement('div');
-      var messageDiv = document.createElement('div');
-      messageDiv.className = 'error-message-bubble';
-      messageDiv.textContent = message;
-      error.appendChild(messageDiv);
-      error.setAttribute('role', 'alert');
-    },
-
-    /**
      * This is called after resources are updated.
      */
     updateLocalizedContent: function() {
diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html
index 583f72d..6aaf1ee 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screens.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screens.html
@@ -1,5 +1,6 @@
 <include src="oobe_screen_eula.html">
 <include src="oobe_screen_welcome.html">
+<include src="oobe_screen_network.html">
 <include src="oobe_screen_enable_debugging.html">
 <include src="oobe_screen_reset.html">
 <include src="oobe_screen_autolaunch.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index 79ea4645..a16207d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -57,7 +57,7 @@
     <link rel="stylesheet" href="oobe_welcome.css">
     <link rel="stylesheet" href="oobe_flex_layout.css">
     <oobe-welcome-dialog id="welcomeScreen" role="dialog"
-        aria-label$="[[i18nDynamic(locale, 'networkScreenGreeting')]]"
+        aria-label$="[[i18nDynamic(locale, 'welcomeScreenGreeting')]]"
         current-language="[[currentLanguage]]"
         on-language-button-clicked="onWelcomeSelectLanguageButtonClicked_"
         on-accessibility-button-clicked="onWelcomeAccessibilityButtonClicked_"
@@ -272,9 +272,5 @@
         </oobe-text-button>
       </div>
     </oobe-dialog>
-    <oobe-network-dialog id="networkSelectionScreen" role="dialog" hidden
-        on-back-button-clicked="onNetworkSelectionBackButtonClicked_"
-        on-next-button-clicked="onNetworkSelectionNextButtonClicked_">
-    </oobe-network-dialog>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js
index 4342c357..876d61e 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -88,15 +88,12 @@
 
     if (this.fullScreenDialog) {
       this.$.welcomeScreen.fullScreenDialog = true;
-      this.$.networkSelectionScreen.fullScreenDialog = true;
     }
 
     this.behaviors.forEach((behavior) => {
       if (behavior.onBeforeShow)
         behavior.onBeforeShow.call(this);
     });
-
-    this.$.networkSelectionScreen.onBeforeShow();
   },
 
   /**
@@ -108,7 +105,6 @@
     this.timezones = loadTimeData.getValue('timezoneList');
     this.highlightStrength = loadTimeData.getValue('highlightStrength');
 
-    this.$.networkSelectionScreen.i18nUpdateLocale();
     this.$.welcomeScreen.i18nUpdateLocale();
     this.i18nUpdateLocale();
   },
@@ -134,7 +130,6 @@
    */
   hideAllScreens_: function() {
     this.$.welcomeScreen.hidden = true;
-    this.$.networkSelectionScreen.hidden = true;
 
     var screens = Polymer.dom(this.root).querySelectorAll('oobe-dialog');
     for (var i = 0; i < screens.length; ++i) {
@@ -195,7 +190,7 @@
    * @private
    */
   onWelcomeNextButtonClicked_: function() {
-    this.showScreen_('networkSelectionScreen');
+    chrome.send('login.WelcomeScreen.userActed', ['continue']);
   },
 
   /**
@@ -234,20 +229,6 @@
     this.showScreen_('timezoneScreen');
   },
 
-  /** @private */
-  onNetworkSelectionNextButtonClicked_: function() {
-    chrome.send('login.WelcomeScreen.userActed', ['continue']);
-  },
-
-  /**
-   * Handle "<- Back" button on network selection screen.
-   *
-   * @private
-   */
-  onNetworkSelectionBackButtonClicked_: function() {
-    this.showScreen_('welcomeScreen');
-  },
-
   /**
    * Handle language selection.
    *
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
index b43d30a..75e2650b1 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
@@ -64,7 +64,7 @@
       <div class="vertical-margin"></div>
       <div class="welcome-content flex layout vertical center">
         <div class="layout vertical end-justified" id="titleContainer">
-          <h1 id="title">[[i18nDynamic(locale, 'networkScreenGreeting')]]</h1>
+          <h1 id="title">[[i18nDynamic(locale, 'welcomeScreenGreeting')]]</h1>
         </div>
         <div class="welcome-illustration" hidden="[[isInTabletMode]]">
           <img srcset="images/welcome_illustration_1x.png 1x,
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index c81aa886..97463c89 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -706,6 +706,11 @@
       $('login-header-bar').showCreateSupervisedButton =
           data.supervisedUsersCanCreate;
       $('login-header-bar').showGuestButton = data.guestSignin;
+      if (Oobe.getInstance().showingViewsLogin) {
+        chrome.send(
+            'showGuestButton',
+            [data.guestSignin && !this.closable && this.isAtTheBeginning()]);
+      }
 
       // Reset SAML
       this.classList.toggle('full-width', false);
diff --git a/chrome/browser/resources/print_preview/new/BUILD.gn b/chrome/browser/resources/print_preview/new/BUILD.gn
index 09aac51..b8b48894 100644
--- a/chrome/browser/resources/print_preview/new/BUILD.gn
+++ b/chrome/browser/resources/print_preview/new/BUILD.gn
@@ -75,6 +75,7 @@
     "//ui/webui/resources/js:event_tracker",
     "//ui/webui/resources/js:util",
     "//ui/webui/resources/js:webui_listener_tracker",
+    "//ui/webui/resources/js/cr/ui:focus_outline_manager",
   ]
 }
 
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html
index efc76e0..9f21c03 100644
--- a/chrome/browser/resources/print_preview/new/app.html
+++ b/chrome/browser/resources/print_preview/new/app.html
@@ -1,5 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_outline_manager.html">
 <link rel="import" href="chrome://resources/html/event_tracker.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/webui_listener_tracker.html">
diff --git a/chrome/browser/resources/print_preview/new/app.js b/chrome/browser/resources/print_preview/new/app.js
index 49797f3..9995f2d 100644
--- a/chrome/browser/resources/print_preview/new/app.js
+++ b/chrome/browser/resources/print_preview/new/app.js
@@ -170,6 +170,11 @@
   openDialogs_: [],
 
   /** @override */
+  ready: function() {
+    cr.ui.FocusOutlineManager.forDocument(document);
+  },
+
+  /** @override */
   attached: function() {
     this.nativeLayer_ = print_preview.NativeLayer.getInstance();
     this.documentInfo_ = new print_preview.DocumentInfo();
diff --git a/chrome/browser/resources/print_preview/new/more_settings.html b/chrome/browser/resources/print_preview/new/more_settings.html
index 5279738..67e37e6 100644
--- a/chrome/browser/resources/print_preview/new/more_settings.html
+++ b/chrome/browser/resources/print_preview/new/more_settings.html
@@ -1,26 +1,39 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
-
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/html/action_link.html">
-<link rel="import" href="chrome://resources/html/action_link_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="../metrics.html">
 <link rel="import" href="strings.html">
 
 <dom-module id="print-preview-more-settings">
   <template>
-    <style include="action-link cr-hidden-style">
+    <style include="cr-hidden-style">
       :host {
+        display: block;
+        margin: 10px auto 0;
+      }
+
+      :host button {
         align-items: center;
         background-color: #f6f6f6;
+        background-image: none;
         --border: 1px solid #e1e1e1;
         border-bottom: var(--border);
+        border-left: none;
+        border-right: none;
         border-top: var(--border);
+        box-shadow: none;
         cursor: pointer;
         display: flex;
-        margin-top: 4px;
-        min-height: 38px;
+        margin: auto;
+        min-height: 51px;
+        outline: none;
         padding: 5px 20px;
+        /* sidebar width - 2px */
+        width: 308px;
+      }
+
+      :host-context(.focus-outline-visible) button:focus {
+        outline: -webkit-focus-ring-color auto 5px;
       }
 
       :host([hidden]) {
@@ -28,7 +41,23 @@
       }
 
       :host #label {
+        color: var(--google-blue-700);
         flex: 1;
+        text-align: left;
+      }
+
+      :host-context([dir=rtl]) #label {
+        text-align: right;
+      }
+
+      :host([disabled]) #label {
+        color: var(--paper-grey-600);
+        opacity: .65;
+      }
+
+      :host #label:hover,
+      :host #label:active {
+        text-decoration: underline;
       }
 
       :host #icon {
@@ -44,10 +73,12 @@
         background-image: url(chrome://resources/images/icon_expand_more.svg);
       }
     </style>
-    <a id="label" is="action-link" disabled="[[disabled]]">
-      [[getLabelText_(settingsExpandedByUser)]]
-    </a>
-    <div id="icon" class$="[[getIconClass_(settingsExpandedByUser)]]"></div>
+    <button disabled="[[disabled]]" on-click="onMoreSettingsClick_"
+        aria-expanded$="[[getAriaExpanded_(settingsExpandedByUser)]]"
+        aria-label$="[[i18n('moreOptionsLabel')]]">
+      <span id="label">[[getLabelText_(settingsExpandedByUser)]]</span>
+      <div id="icon" class$="[[getIconClass_(settingsExpandedByUser)]]"></div>
+    </button>
   </template>
   <script src="more_settings.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/print_preview/new/more_settings.js b/chrome/browser/resources/print_preview/new/more_settings.js
index 431625fb..5a31e23 100644
--- a/chrome/browser/resources/print_preview/new/more_settings.js
+++ b/chrome/browser/resources/print_preview/new/more_settings.js
@@ -13,11 +13,10 @@
       notify: true,
     },
 
-    disabled: Boolean,
-  },
-
-  listeners: {
-    'click': 'onMoreSettingsClick_',
+    disabled: {
+      type: Boolean,
+      reflectToAttribute: true,
+    },
   },
 
   /** @private {!print_preview.PrintSettingsUiMetricsContext} */
@@ -41,6 +40,14 @@
         this.settingsExpandedByUser ? 'lessOptionsLabel' : 'moreOptionsLabel');
   },
 
+  /**
+   * @return {string} 'true' if the settings are expanded, 'false' otherwise
+   * @private
+   */
+  getAriaExpanded_: function() {
+    return this.settingsExpandedByUser ? 'true' : 'false';
+  },
+
   /** @private */
   onMoreSettingsClick_: function() {
     this.settingsExpandedByUser = !this.settingsExpandedByUser;
diff --git a/chrome/browser/resources/print_preview/new/print_preview_shared_css.html b/chrome/browser/resources/print_preview/new/print_preview_shared_css.html
index 6e08aef..a9d42ee 100644
--- a/chrome/browser/resources/print_preview/new/print_preview_shared_css.html
+++ b/chrome/browser/resources/print_preview/new/print_preview_shared_css.html
@@ -108,31 +108,33 @@
       }
 
       /* Focus ****************************************************************/
+      :host {
+        --print-preview-focus-border: {
+          /* We use border color because it follows the border radius (unlike
+           * outline). This is particularly noticeable on mac. */
+          border-color: rgb(77, 144, 254);
+          outline: none;
+          /* OVERRIDE */
+          transition: border-color 200ms;
+        };
+      }
 
       :enabled:focus:-webkit-any(
           select,
-          input[type='checkbox'],
           input[type='number'],
-          input[type='radio'],
           input[type='search'],
           input[type='text'],
-          input:not([type]),
-            button) {
-        /* We use border color because it follows the border radius (unlike
-         * outline). This is particularly noticeable on mac. */
-        border-color: rgb(77, 144, 254);
-        outline: none;
-        /* OVERRIDE */
-        transition: border-color 200ms;
+          input:not([type])) {
+        @apply --print-preview-focus-border;
       }
 
-      html:not(.focus-outline-visible)
-      :enabled:focus:-webkit-any(input[type='checkbox'],
-                                 input[type='radio'],
-                                 button) {
-        border-color: rgba(0,0,0,0.25);
+      :host-context(.focus-outline-visible)
+      :enabled:focus:-webkit-any(
+          input[type='checkbox'],
+          input[type='radio'],
+          button) {
+        @apply --print-preview-focus-border;
       }
-
     </style>
   </template>
 </dom-module>
diff --git a/chrome/browser/signin/profile_oauth2_token_service_factory.cc b/chrome/browser/signin/profile_oauth2_token_service_factory.cc
index 0c94782..2994cf0d 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_factory.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_factory.cc
@@ -42,11 +42,12 @@
 bool ShouldCreateCrOsOAuthDelegate(Profile* profile) {
   // Chrome OS Account Manager should only be instantiated in "regular"
   // profiles. Do not try to create |ChromeOSOAuth2TokenServiceDelegate| (which
-  // uses CrOS Account Manager as the source of truth) for Signin Profile and
-  // Lock Screen Profile.
+  // uses CrOS Account Manager as the source of truth) for Signin Profile,
+  // Lock Screen Profile and Guest Sessions.
   return chromeos::switches::IsAccountManagerEnabled() &&
          !chromeos::ProfileHelper::IsSigninProfile(profile) &&
-         !chromeos::ProfileHelper::IsLockScreenAppProfile(profile);
+         !chromeos::ProfileHelper::IsLockScreenAppProfile(profile) &&
+         !profile->IsGuestSession();
 }
 
 std::unique_ptr<chromeos::ChromeOSOAuth2TokenServiceDelegate>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 03555a2..9eaeb2c 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1954,7 +1954,6 @@
       "views/select_file_dialog_extension.h",
       "views/select_file_dialog_extension_factory.cc",
       "views/select_file_dialog_extension_factory.h",
-      "views/tabs/window_finder_ash.cc",
       "webui/chromeos/assistant_optin/assistant_optin_handler.cc",
       "webui/chromeos/assistant_optin/assistant_optin_handler.h",
       "webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h",
@@ -2059,6 +2058,8 @@
       "webui/chromeos/login/native_window_delegate.h",
       "webui/chromeos/login/network_dropdown_handler.cc",
       "webui/chromeos/login/network_dropdown_handler.h",
+      "webui/chromeos/login/network_screen_handler.cc",
+      "webui/chromeos/login/network_screen_handler.h",
       "webui/chromeos/login/network_state_informer.cc",
       "webui/chromeos/login/network_state_informer.h",
       "webui/chromeos/login/oobe_display_chooser.cc",
@@ -3104,8 +3105,6 @@
         "views/ime_driver/remote_text_input_client.h",
         "views/ime_driver/simple_input_method.cc",
         "views/ime_driver/simple_input_method.h",
-        "views/tabs/window_finder_mus.cc",
-        "views/tabs/window_finder_mus.h",
       ]
 
       deps += [ "//ui/views/mus" ]
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index a61619c7..036848b 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -163,8 +163,7 @@
 }
 
 void LoginScreenClient::ShowResetScreen() {
-  chromeos::LoginDisplayHost::default_host()->StartWizard(
-      chromeos::OobeScreen::SCREEN_OOBE_RESET);
+  chromeos::LoginDisplayHost::default_host()->ShowResetScreen();
 }
 
 void LoginScreenClient::LoadWallpaper(const AccountId& account_id) {
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm b/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm
index 933db087..3fb15c9 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm
@@ -5,6 +5,8 @@
 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.h"
 
 #include "base/mac/availability.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h"
 #include "components/autofill/core/browser/autofill_popup_delegate.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
@@ -62,8 +64,13 @@
     return;
 
   if (@available(macOS 10.12.2, *)) {
-    touch_bar_controller_ = [WebTextfieldTouchBarController
-        controllerForWindow:[container_view() window]];
+    BrowserWindowController* bwc = [BrowserWindowController
+        browserWindowControllerForWindow:[container_view() window]];
+    TabContentsController* tabContentsController =
+        [[bwc tabStripController] activeTabContentsController];
+    touch_bar_controller_ =
+        [tabContentsController webTextfieldTouchBarController];
+
     [touch_bar_controller_ showCreditCardAutofillWithController:this];
   }
 }
@@ -72,8 +79,9 @@
     const std::vector<base::string16>& values,
     const std::vector<base::string16>& labels) {
   AutofillPopupControllerImpl::UpdateDataListValues(values, labels);
-  if (touch_bar_controller_)
+  if (touch_bar_controller_) {
     [touch_bar_controller_ invalidateTouchBar];
+  }
 }
 
 void AutofillPopupControllerImplMac::Hide() {
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
index 63a17bb..7fe6d64 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -12,6 +12,7 @@
 #include "base/mac/scoped_nsobject.h"
 
 class FullscreenObserver;
+@class WebTextfieldTouchBarController;
 
 namespace content {
 class WebContents;
@@ -52,6 +53,8 @@
    // Reference to the fullscreen window created to display the WebContents
    // view separately.
    NSWindow* separateFullscreenWindow_;
+
+   base::scoped_nsobject<WebTextfieldTouchBarController> touchBarController_;
 }
 @property(readonly, nonatomic) content::WebContents* webContents;
 
@@ -97,6 +100,8 @@
 // widget or back to WebContentsView's widget.
 - (void)toggleFullscreenWidget:(BOOL)enterFullscreen;
 
+- (WebTextfieldTouchBarController*)webTextfieldTouchBarController;
+
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_TAB_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
index 3929fd4..2067c7a 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/cocoa/fullscreen_placeholder_view.h"
 #include "chrome/browser/ui/cocoa/separate_fullscreen_window.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/common/chrome_features.h"
@@ -219,6 +220,8 @@
     fullscreenObserver_.reset(new FullscreenObserver(self));
     [self changeWebContents:contents];
     isPopup_ = popup;
+    touchBarController_.reset([[WebTextfieldTouchBarController alloc]
+        initWithTabContentsController:self]);
   }
   return self;
 }
@@ -238,6 +241,10 @@
   [self setView:view];
 }
 
+- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2)) {
+  return [touchBarController_ makeTouchBar];
+}
+
 - (void)ensureContentsVisibleInSuperview:(NSView*)superview {
   if (!contents_)
     return;
@@ -417,6 +424,10 @@
   return isPopup_;
 }
 
+- (WebTextfieldTouchBarController*)webTextfieldTouchBarController {
+  return touchBarController_.get();
+}
+
 @end
 
 @implementation TabContentsController (SeparateFullscreenWindowDelegate)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
index dc19594c0..a51d2a8d 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
@@ -21,7 +21,6 @@
 @class CustomWindowControlsView;
 @class NewTabButtonCocoa;
 @class TabContentsController;
-@class TabControllerCocoa;
 @class TabViewCocoa;
 @class TabStripDragController;
 @class TabStripView;
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
index fea91ee..19e8228 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
@@ -23,6 +23,8 @@
 #import "chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/omnibox/browser/vector_icons.h"
@@ -130,6 +132,7 @@
 // the profile preferences and the back/forward commands.
 class TouchBarNotificationBridge : public CommandObserver,
                                    public BookmarkTabHelperObserver,
+                                   public TabStripModelObserver,
                                    public content::WebContentsObserver {
  public:
   TouchBarNotificationBridge(BrowserWindowDefaultTouchBar* owner,
@@ -137,6 +140,7 @@
       : owner_(owner), browser_(browser), contents_(nullptr) {
     TabStripModel* model = browser_->tab_strip_model();
     DCHECK(model);
+    model->AddObserver(this);
 
     UpdateWebContents(model->GetActiveWebContents());
   }
@@ -144,6 +148,10 @@
   ~TouchBarNotificationBridge() override {
     if (contents_)
       BookmarkTabHelper::FromWebContents(contents_)->RemoveObserver(this);
+
+    TabStripModel* model = browser_->tab_strip_model();
+    if (model)
+      model->RemoveObserver(this);
   }
 
   void UpdateTouchBar() { [[owner_ controller] invalidateTouchBar]; }
@@ -174,6 +182,16 @@
     [owner_ setIsStarred:starred];
   }
 
+  // TabStripModelObserver:
+  void ActiveTabChanged(content::WebContents* old_contents,
+                        content::WebContents* new_contents,
+                        int index,
+                        int reason) override {
+    UpdateWebContents(new_contents);
+    contents_ = new_contents;
+    UpdateTouchBar();
+  }
+
  protected:
   // CommandObserver:
   void EnabledStateChangedForCommand(int command, bool enabled) override {
@@ -197,6 +215,11 @@
     [owner_ setIsPageLoading:NO];
   }
 
+  void WebContentsDestroyed() override {
+    // Clean up if the web contents is being destroyed.
+    UpdateWebContents(nullptr);
+  }
+
  private:
   BrowserWindowDefaultTouchBar* owner_;  // Weak.
   Browser* browser_;                     // Weak.
@@ -246,7 +269,6 @@
 
 // Creates and returns the search button.
 - (NSView*)searchTouchBarView API_AVAILABLE(macos(10.12));
-
 @end
 
 @implementation BrowserWindowDefaultTouchBar
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h
index 6f0e576..9d000d47 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h
@@ -12,11 +12,6 @@
 
 class Browser;
 @class BrowserWindowDefaultTouchBar;
-@class WebTextfieldTouchBarController;
-
-namespace content {
-class WebContents;
-}
 
 // Provides a touch bar for the browser window. This class implements the
 // NSTouchBarDelegate and handles the items in the touch bar.
@@ -31,16 +26,12 @@
 // nil.
 - (void)invalidateTouchBar;
 
-- (void)updateWebContents:(content::WebContents*)contents;
-
-- (content::WebContents*)webContents;
 @end
 
 @interface BrowserWindowTouchBarController (ExposedForTesting)
 
 - (BrowserWindowDefaultTouchBar*)defaultTouchBar;
 
-- (WebTextfieldTouchBarController*)webTextfieldTouchBar;
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_TOUCHBAR_BROWSER_WINDOW_TOUCH_BAR_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
index 43bc4d9e..f31ffbe 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
@@ -12,72 +12,17 @@
 #import "base/mac/sdk_forward_declarations.h"
 #include "chrome/browser/ui/browser.h"
 #import "chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h"
-#import "chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
 #import "ui/base/cocoa/touch_bar_util.h"
 
-class WebContentsNotificationBridge : public TabStripModelObserver,
-                                      public content::WebContentsObserver {
- public:
-  WebContentsNotificationBridge(BrowserWindowTouchBarController* owner,
-                                Browser* browser)
-      : owner_(owner), browser_(browser), contents_(nullptr) {
-    TabStripModel* model = browser_->tab_strip_model();
-    DCHECK(model);
-    model->AddObserver(this);
-
-    UpdateWebContents(model->GetActiveWebContents());
-  }
-
-  ~WebContentsNotificationBridge() override {
-    TabStripModel* model = browser_->tab_strip_model();
-    if (model)
-      model->RemoveObserver(this);
-  }
-
-  void UpdateWebContents(content::WebContents* new_contents) {
-    contents_ = new_contents;
-    Observe(contents_);
-
-    [owner_ updateWebContents:contents_];
-  }
-
-  // TabStripModelObserver:
-  void ActiveTabChanged(content::WebContents* old_contents,
-                        content::WebContents* new_contents,
-                        int index,
-                        int reason) override {
-    UpdateWebContents(new_contents);
-    contents_ = new_contents;
-  }
-
-  content::WebContents* contents() const { return contents_; }
-
- protected:
-  // WebContentsObserver:
-  void WebContentsDestroyed() override {
-    // Clean up if the web contents is being destroyed.
-    UpdateWebContents(nullptr);
-  }
-
- private:
-  BrowserWindowTouchBarController* owner_;  // Weak.
-  Browser* browser_;                        // Weak.
-  content::WebContents* contents_;          // Weak.
-};
-
 @interface BrowserWindowTouchBarController () {
+  // The browser associated with the touch bar.
+  Browser* browser_;  // Weak.
+
   NSWindow* window_;  // Weak.
 
-  // Used to receive and handle notifications.
-  std::unique_ptr<WebContentsNotificationBridge> notificationBridge_;
-
   base::scoped_nsobject<BrowserWindowDefaultTouchBar> defaultTouchBar_;
-
-  base::scoped_nsobject<WebTextfieldTouchBarController> webTextfieldTouchBar_;
 }
 @end
 
@@ -85,17 +30,10 @@
 
 - (instancetype)initWithBrowser:(Browser*)browser window:(NSWindow*)window {
   if ((self = [super init])) {
-    DCHECK(browser);
-    window_ = window;
-
-    notificationBridge_ =
-        std::make_unique<WebContentsNotificationBridge>(self, browser);
-
     defaultTouchBar_.reset([[BrowserWindowDefaultTouchBar alloc]
         initWithBrowser:browser
              controller:self]);
-    webTextfieldTouchBar_.reset(
-        [[WebTextfieldTouchBarController alloc] initWithController:self]);
+    window_ = window;
   }
 
   return self;
@@ -107,23 +45,9 @@
 }
 
 - (NSTouchBar*)makeTouchBar {
-  NSTouchBar* touchBar = [webTextfieldTouchBar_ makeTouchBar];
-  if (touchBar)
-    return touchBar;
-
   return [defaultTouchBar_ makeTouchBar];
 }
 
-- (void)updateWebContents:(content::WebContents*)contents {
-  [defaultTouchBar_ updateWebContents:contents];
-  [webTextfieldTouchBar_ updateWebContents:contents];
-  [self invalidateTouchBar];
-}
-
-- (content::WebContents*)webContents {
-  return notificationBridge_->web_contents();
-}
-
 @end
 
 @implementation BrowserWindowTouchBarController (ExposedForTesting)
@@ -132,8 +56,4 @@
   return defaultTouchBar_.get();
 }
 
-- (WebTextfieldTouchBarController*)webTextfieldTouchBar {
-  return webTextfieldTouchBar_.get();
-}
-
 @end
diff --git a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.h
index 7e4c5d3..d916ebcd 100644
--- a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.h
+++ b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.h
@@ -25,6 +25,8 @@
 - (instancetype)initWithWebContents:(content::WebContents*)webContents
                          controller:(WebTextfieldTouchBarController*)controller;
 
+- (void)initObserver;
+
 - (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
 
 - (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
diff --git a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm
index 0cfeb53..85cb010f 100644
--- a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm
@@ -26,10 +26,6 @@
                           SuggestedTextTouchBarController* owner)
       : WebContentsObserver(web_contents), owner_(owner) {}
 
-  void UpdateWebContents(content::WebContents* web_contents) {
-    Observe(web_contents);
-  }
-
   void DidChangeTextSelection(const base::string16& text,
                               const gfx::Range& range) override {
     if (@available(macOS 10.12.2, *)) {
@@ -86,15 +82,18 @@
   if ((self = [super init])) {
     webContents_ = webContents;
     controller_ = controller;
-    observer_.reset(
-        new text_observer::WebContentsTextObserver(webContents_, self));
   }
 
   return self;
 }
 
+- (void)initObserver {
+  observer_.reset(
+      new text_observer::WebContentsTextObserver(webContents_, self));
+}
+
 - (NSTouchBar*)makeTouchBar {
-  if (!webContents_ || !webContents_->IsFocusedElementEditable())
+  if (!webContents_->IsFocusedElementEditable())
     return nil;
 
   base::scoped_nsobject<NSTouchBar> touchBar([[ui::NSTouchBar() alloc] init]);
@@ -254,9 +253,7 @@
 }
 
 - (void)setWebContents:(content::WebContents*)webContents {
-  // TODO(tnijssen): Update the text suggestions when we change web contents.
   webContents_ = webContents;
-  observer_->UpdateWebContents(webContents);
 }
 
 - (content::WebContents*)webContents {
diff --git a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
index dbca4d7e..5237569 100644
--- a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
+++ b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
@@ -12,7 +12,6 @@
 #import "base/mac/scoped_nsobject.h"
 #import "ui/base/cocoa/touch_bar_forward_declarations.h"
 
-@class BrowserWindowTouchBarController;
 @class CreditCardAutofillTouchBarController;
 @class SuggestedTextTouchBarController;
 @class TabContentsController;
@@ -21,32 +20,24 @@
 class AutofillPopupController;
 }
 
-namespace content {
-class WebContents;
-}
-
 // Provides a touch bar for the textfields in the WebContents. This class
 // implements the NSTouchBarDelegate and handles the items in the touch bar.
 @interface WebTextfieldTouchBarController : NSObject<NSTouchBarDelegate> {
-  BrowserWindowTouchBarController* controller_;  // weak.
+  TabContentsController* owner_;  // weak.
   base::scoped_nsobject<CreditCardAutofillTouchBarController>
       autofillTouchBarController_;
   base::scoped_nsobject<SuggestedTextTouchBarController>
       suggestedTextTouchBarController_;
 }
 
-+ (WebTextfieldTouchBarController*)controllerForWindow:(NSWindow*)window;
-
 // Designated initializer.
-- (instancetype)initWithController:(BrowserWindowTouchBarController*)controller;
+- (instancetype)initWithTabContentsController:(TabContentsController*)owner;
 
 - (void)showCreditCardAutofillWithController:
     (autofill::AutofillPopupController*)controller;
 
 - (void)hideCreditCardAutofillTouchBar;
 
-- (void)updateWebContents:(content::WebContents*)contents;
-
 - (void)invalidateTouchBar;
 
 // Creates and returns a touch bar.
diff --git a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
index f51d0af6..347f606 100644
--- a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
@@ -8,47 +8,25 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/credit_card_autofill_touch_bar_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.h"
-#include "chrome/browser/ui/views/frame/browser_frame_mac.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/chrome_features.h"
 #include "content/public/browser/web_contents.h"
 #import "ui/base/cocoa/touch_bar_util.h"
-#include "ui/base/ui_base_features.h"
 
 @implementation WebTextfieldTouchBarController
 
-+ (WebTextfieldTouchBarController*)controllerForWindow:(NSWindow*)window {
-  if (features::IsViewsBrowserCocoa()) {
-    BrowserWindowController* bwc =
-        [BrowserWindowController browserWindowControllerForWindow:window];
-    return [[bwc browserWindowTouchBarController] webTextfieldTouchBar];
-  }
-
-  BrowserView* browser_view =
-      BrowserView::GetBrowserViewForNativeWindow(window);
-  if (!browser_view)
-    return nil;
-
-  BrowserFrameMac* browser_frame = static_cast<BrowserFrameMac*>(
-      browser_view->frame()->native_browser_frame());
-  return [browser_frame->GetTouchBarController() webTextfieldTouchBar];
-}
-
-- (instancetype)initWithController:
-    (BrowserWindowTouchBarController*)controller {
+- (instancetype)initWithTabContentsController:(TabContentsController*)owner {
   if ((self = [super init])) {
-    controller_ = controller;
+    owner_ = owner;
 
-    if (base::FeatureList::IsEnabled(features::kSuggestedTextTouchBar)) {
+    if (IsSuggestedTextTouchBarEnabled()) {
       suggestedTextTouchBarController_.reset(
           [[SuggestedTextTouchBarController alloc]
-              initWithWebContents:[controller_ webContents]
+              initWithWebContents:[owner_ webContents]
                        controller:self]);
+      [suggestedTextTouchBarController_ initObserver];
     }
   }
 
@@ -73,12 +51,13 @@
   [self invalidateTouchBar];
 }
 
-- (void)updateWebContents:(content::WebContents*)contents {
-  [suggestedTextTouchBarController_ setWebContents:contents];
+bool IsSuggestedTextTouchBarEnabled() {
+  return base::FeatureList::IsEnabled(features::kSuggestedTextTouchBar);
 }
 
 - (void)invalidateTouchBar {
-  [controller_ invalidateTouchBar];
+  if ([owner_ respondsToSelector:@selector(setTouchBar:)])
+    [owner_ performSelector:@selector(setTouchBar:) withObject:nil];
 }
 
 - (NSTouchBar*)makeTouchBar {
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index eac7521..8db8a7e 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -29,7 +29,7 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
 #include "components/nux_google_apps/constants.h"
-#include "components/nux_google_apps/webui.h"
+#include "components/nux_google_apps/google_apps_handler.h"
 #endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
 
 namespace {
diff --git a/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc b/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc
index e768135..d387496 100644
--- a/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc
+++ b/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc
@@ -11,6 +11,10 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/browser/bookmark_node.h"
 
+std::unique_ptr<ShowPromoDelegate> ShowPromoDelegate::CreatePromoDelegate() {
+  return std::make_unique<BookmarkBarPromoBubbleView>();
+}
+
 struct BookmarkBarPromoBubbleView::BubbleImpl : public FeaturePromoBubbleView {
   // Anchors the BookmarkBarPromoBubbleView to |anchor_view|.
   // The bubble widget and promo are owned by their native widget.
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h
index 36aa01a..5e4b775d 100644
--- a/chrome/browser/ui/views/frame/browser_frame.h
+++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -120,10 +120,6 @@
   // Note that in multi user mode this will upon each call create a new model.
   ui::MenuModel* GetSystemMenuModel();
 
-  NativeBrowserFrame* native_browser_frame() const {
-    return native_browser_frame_;
-  }
-
  private:
   // Callback for MenuRunner.
   void OnMenuClosed();
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.h b/chrome/browser/ui/views/frame/browser_frame_mac.h
index 1a1aa8e..d7a48c60 100644
--- a/chrome/browser/ui/views/frame/browser_frame_mac.h
+++ b/chrome/browser/ui/views/frame/browser_frame_mac.h
@@ -13,8 +13,7 @@
 
 class BrowserFrame;
 class BrowserView;
-@class BrowserWindowTouchBarController;
-@class BrowserWindowTouchBarViewsDelegate;
+@protocol WindowTouchBarDelegate;
 @class ChromeCommandDispatcherDelegate;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -26,8 +25,6 @@
  public:
   BrowserFrameMac(BrowserFrame* browser_frame, BrowserView* browser_view);
 
-  BrowserWindowTouchBarController* GetTouchBarController() const;
-
   // Overridden from views::NativeWidgetMac:
   int SheetPositionY() override;
   void OnWindowFullscreenStateChange() override;
@@ -60,7 +57,7 @@
   BrowserView* browser_view_;  // Weak. Our ClientView.
   base::scoped_nsobject<ChromeCommandDispatcherDelegate>
       command_dispatcher_delegate_;
-  base::scoped_nsobject<BrowserWindowTouchBarViewsDelegate> touch_bar_delegate_;
+  base::scoped_nsprotocol<id<WindowTouchBarDelegate>> touch_bar_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserFrameMac);
 };
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm
index ff426e6b..12c822a 100644
--- a/chrome/browser/ui/views/frame/browser_frame_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -42,18 +42,16 @@
 
 // Bridge Obj-C class for WindowTouchBarDelegate and
 // BrowserWindowTouchBarController.
-@interface BrowserWindowTouchBarViewsDelegate
+@interface BrowserWindowTouchBarControllerViewsDelegate
     : NSObject<WindowTouchBarDelegate> {
   Browser* browser_;  // Weak.
   NSWindow* window_;  // Weak.
   base::scoped_nsobject<BrowserWindowTouchBarController> touchBarController_;
 }
 
-- (BrowserWindowTouchBarController*)touchBarController;
-
 @end
 
-@implementation BrowserWindowTouchBarViewsDelegate
+@implementation BrowserWindowTouchBarControllerViewsDelegate
 
 - (instancetype)initWithBrowser:(Browser*)browser window:(NSWindow*)window {
   if ((self = [super init])) {
@@ -64,10 +62,6 @@
   return self;
 }
 
-- (BrowserWindowTouchBarController*)touchBarController {
-  return touchBarController_.get();
-}
-
 - (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2)) {
   if (!touchBarController_) {
     touchBarController_.reset([[BrowserWindowTouchBarController alloc]
@@ -89,11 +83,6 @@
 BrowserFrameMac::~BrowserFrameMac() {
 }
 
-BrowserWindowTouchBarController* BrowserFrameMac::GetTouchBarController()
-    const {
-  return [touch_bar_delegate_ touchBarController];
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // BrowserFrameMac, views::NativeWidgetMac implementation:
 
@@ -148,9 +137,10 @@
   [ns_window setCommandHandler:[[[BrowserWindowCommandHandler alloc] init]
                                    autorelease]];
 
-  touch_bar_delegate_.reset([[BrowserWindowTouchBarViewsDelegate alloc]
-      initWithBrowser:browser_view_->browser()
-               window:ns_window]);
+  touch_bar_delegate_.reset(
+      [[BrowserWindowTouchBarControllerViewsDelegate alloc]
+          initWithBrowser:browser_view_->browser()
+                   window:ns_window]);
   [ns_window setWindowTouchBarDelegate:touch_bar_delegate_.get()];
 
   return ns_window.autorelease();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index a17e1359..a816cef 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -872,20 +872,20 @@
 
 // Tests that a web app's theme color is set.
 IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, ThemeColor) {
-  EXPECT_EQ(GetThemeColor(), frame_header_->active_frame_color_for_testing());
-  EXPECT_EQ(GetThemeColor(), frame_header_->inactive_frame_color_for_testing());
+  aura::Window* window = browser_view_->GetWidget()->GetNativeWindow();
+  EXPECT_EQ(GetThemeColor(),window->GetProperty(ash::kFrameActiveColorKey));
+  EXPECT_EQ(GetThemeColor(), window->GetProperty(ash::kFrameInactiveColorKey));
   EXPECT_EQ(SK_ColorWHITE, GetActiveIconColor(hosted_app_button_container_));
 }
 
-// Make sure that for hosted apps, the height of the frame header and its
-// contents don't exceed the height of the caption buttons.
+// Make sure that for hosted apps, the height of the frame doesn't exceed the
+// height of the caption buttons.
 IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, FrameSize) {
-  EXPECT_EQ(frame_header_->GetHeaderHeight(),
+  const int inset = GetFrameViewAsh(browser_view_)->GetTopInset(false);
+  EXPECT_EQ(inset,
             GetAshLayoutSize(ash::AshLayoutSize::kNonBrowserCaption).height());
-  EXPECT_LE(app_menu_button_->size().height(),
-            frame_header_->GetHeaderHeight());
-  EXPECT_LE(hosted_app_button_container_->size().height(),
-            frame_header_->GetHeaderHeight());
+  EXPECT_GE(inset, app_menu_button_->size().height());
+  EXPECT_GE(inset, hosted_app_button_container_->size().height());
 }
 
 // Test that the HostedAppButtonContainer is the designated toolbar button
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc
index 70fb9b590..0f126a3 100644
--- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc
+++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/command_line.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
@@ -15,6 +16,7 @@
 #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_view.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/chrome_switches.h"
 #include "components/version_info/channel.h"
 #include "content/public/common/content_features.h"
 #include "ui/events/event.h"
@@ -67,7 +69,10 @@
   // menu and controls reveal when the cursor is moved to the top.
   return false;
 #else
-  return base::FeatureList::IsEnabled(features::kFullscreenExitUI);
+  // Fullscreen exit UI should not be enabled when kiosk mode is on.
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kKioskMode) &&
+         base::FeatureList::IsEnabled(features::kFullscreenExitUI);
 #endif
 }
 
diff --git a/chrome/browser/ui/views/tabs/DEPS b/chrome/browser/ui/views/tabs/DEPS
index 99c329f3..04632bf 100644
--- a/chrome/browser/ui/views/tabs/DEPS
+++ b/chrome/browser/ui/views/tabs/DEPS
@@ -1,6 +1,6 @@
 specific_include_rules = {
-  # mash-ok. Mash uses window_finder_mus.cc instead of window_finder_ash.cc.
-  "window_finder_ash\.cc": [
+  # mash-ok
+  "window_finder_chromeos\.cc": [
     "+ash/wm/root_window_finder.h",
   ],
 }
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 1acfe3fb..24c4571 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -1033,10 +1033,7 @@
 }
 
 void Tab::ActiveStateChanged() {
-  if (IsActive()) {
-    // Clear the blocked WebContents for active tabs because it's distracting.
-    icon_->SetAttention(TabIcon::AttentionType::kBlockedWebContents, false);
-  }
+  UpdateTabIconNeedsAttentionBlocked();
   OnButtonColorMaybeChanged();
   alert_indicator_button_->UpdateEnabledForMuteToggle();
   Layout();
@@ -1070,14 +1067,7 @@
   icon_->SetNetworkState(data_.network_state, data_.should_hide_throbber);
   icon_->SetCanPaintToLayer(controller_->CanPaintThrobberToLayer());
   icon_->SetIsCrashed(data_.IsCrashed());
-  if (IsActive()) {
-    icon_->SetAttention(TabIcon::AttentionType::kBlockedWebContents, false);
-  } else {
-    // Only non-active WebContents get the blocked attention type because it's
-    // confusing on the active tab.
-    icon_->SetAttention(TabIcon::AttentionType::kBlockedWebContents,
-                        data_.blocked);
-  }
+  UpdateTabIconNeedsAttentionBlocked();
 
   base::string16 title = data_.title;
   if (title.empty()) {
@@ -1699,5 +1689,17 @@
   close_button_->SetIconColors(icon_color);
 }
 
+void Tab::UpdateTabIconNeedsAttentionBlocked() {
+  // Only show the blocked attention indicator on non-active tabs. For active
+  // tabs, the user sees the dialog blocking the tab, so there's no point to it
+  // and it would be distracting.
+  if (IsActive()) {
+    icon_->SetAttention(TabIcon::AttentionType::kBlockedWebContents, false);
+  } else {
+    icon_->SetAttention(TabIcon::AttentionType::kBlockedWebContents,
+                        data_.blocked);
+  }
+}
+
 Tab::BackgroundCache::BackgroundCache() = default;
 Tab::BackgroundCache::~BackgroundCache() = default;
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 5156c2e..818ba18 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -301,6 +301,10 @@
   // time the theme or active state may have changed.
   void OnButtonColorMaybeChanged();
 
+  // Updates the blocked attention state of the |icon_|. This only updates
+  // state; it is the responsibility of the caller to request a paint.
+  void UpdateTabIconNeedsAttentionBlocked();
+
   // The controller, never NULL.
   TabController* const controller_;
 
diff --git a/chrome/browser/ui/views/tabs/tab_icon.cc b/chrome/browser/ui/views/tabs/tab_icon.cc
index 5dea01f6..f66b830 100644
--- a/chrome/browser/ui/views/tabs/tab_icon.cc
+++ b/chrome/browser/ui/views/tabs/tab_icon.cc
@@ -204,7 +204,7 @@
       icon_to_paint = &themed_favicon_;
   }
 
-  if (attention_types_ != 0 && !should_display_crashed_favicon_) {
+  if (ShowingAttentionIndicator() && !should_display_crashed_favicon_) {
     PaintAttentionIndicatorAndIcon(canvas, *icon_to_paint, icon_bounds);
   } else if (!icon_to_paint->isNull()) {
     canvas->DrawImageInt(*icon_to_paint, 0, 0, icon_bounds.width(),
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
index 6c20e8d..835f41c9 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -195,8 +195,8 @@
     return tab->showing_close_button_;
   }
 
-  bool IsShowingAttentionIndicator(int model_index) {
-    return tab_strip_->tab_at(model_index)->icon_->ShowingAttentionIndicator();
+  bool IsShowingAttentionIndicator(Tab* tab) {
+    return tab->icon_->ShowingAttentionIndicator();
   }
 
   // Checks whether |tab| contains |point_in_tabstrip_coords|, where the point
@@ -819,6 +819,41 @@
   EXPECT_LT(dragged_tab->bounds().width(), min_active_width);
 }
 
+// The "blocked" attention indicator should only show for background tabs.
+TEST_P(TabStripTest, TabNeedsAttentionBlocked) {
+  controller_->AddTab(0, false);
+  controller_->AddTab(1, true);
+
+  Tab* tab1 = tab_strip_->tab_at(1);
+
+  // Block tab1.
+  TabRendererData data;
+  data.blocked = true;
+  tab1->SetData(data);
+
+  EXPECT_FALSE(IsShowingAttentionIndicator(tab1));
+  controller_->SelectTab(0);
+  EXPECT_TRUE(IsShowingAttentionIndicator(tab1));
+  controller_->SelectTab(1);
+  EXPECT_FALSE(IsShowingAttentionIndicator(tab1));
+}
+
+// The generic "wants attention" version should always show.
+TEST_P(TabStripTest, TabNeedsAttentionGeneric) {
+  controller_->AddTab(0, false);
+  controller_->AddTab(1, true);
+
+  Tab* tab1 = tab_strip_->tab_at(1);
+
+  tab1->SetTabNeedsAttention(true);
+
+  EXPECT_TRUE(IsShowingAttentionIndicator(tab1));
+  controller_->SelectTab(0);
+  EXPECT_TRUE(IsShowingAttentionIndicator(tab1));
+  controller_->SelectTab(1);
+  EXPECT_TRUE(IsShowingAttentionIndicator(tab1));
+}
+
 // Defines an alias to be used for tests that are only relevant to the touch-
 // optimized UI mode.
 using TabStripTouchOptimizedUiOnlyTest = TabStripTest;
diff --git a/chrome/browser/ui/views/tabs/window_finder_ash.cc b/chrome/browser/ui/views/tabs/window_finder_ash.cc
deleted file mode 100644
index 855fb15..0000000
--- a/chrome/browser/ui/views/tabs/window_finder_ash.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/tabs/window_finder.h"
-
-// The direct usage of //ash/ is fine here, as this code is only executed in
-// classic ash. See window_finder_chromeos.cc.
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/wm/root_window_finder.h"  // mash-ok
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/wm/core/window_util.h"
-
-namespace {
-
-gfx::NativeWindow GetLocalProcessWindowAtPointImpl(
-    const gfx::Point& screen_point,
-    const std::set<gfx::NativeWindow>& ignore,
-    gfx::NativeWindow window) {
-  if (ignore.find(window) != ignore.end())
-    return NULL;
-
-  if (!window->IsVisible())
-    return NULL;
-
-  if (window->id() == ash::kShellWindowId_PhantomWindow ||
-      window->id() == ash::kShellWindowId_OverlayContainer ||
-      window->id() == ash::kShellWindowId_MouseCursorContainer)
-    return NULL;
-
-  if (window->layer()->type() == ui::LAYER_TEXTURED) {
-    // Returns the window that has visible layer and can hit the
-    // |screen_point|, because we want to detach the tab as soon as
-    // the dragging mouse moved over to the window that can hide the
-    // moving tab.
-    aura::client::ScreenPositionClient* client =
-        aura::client::GetScreenPositionClient(window->GetRootWindow());
-    gfx::Point local_point = screen_point;
-    client->ConvertPointFromScreen(window, &local_point);
-    return window->GetEventHandlerForPoint(local_point) ? window : nullptr;
-  }
-
-  for (aura::Window::Windows::const_reverse_iterator i =
-           window->children().rbegin(); i != window->children().rend(); ++i) {
-    gfx::NativeWindow result =
-        GetLocalProcessWindowAtPointImpl(screen_point, ignore, *i);
-    if (result)
-      return result;
-  }
-  return NULL;
-}
-
-}  // namespace
-
-gfx::NativeWindow GetLocalProcessWindowAtPointAsh(
-    const gfx::Point& screen_point,
-    const std::set<gfx::NativeWindow>& ignore) {
-  return GetLocalProcessWindowAtPointImpl(
-      screen_point, ignore, ash::wm::GetRootWindowAt(screen_point));
-}
diff --git a/chrome/browser/ui/views/tabs/window_finder_chromeos.cc b/chrome/browser/ui/views/tabs/window_finder_chromeos.cc
index aaf58e5c0..d66dfac 100644
--- a/chrome/browser/ui/views/tabs/window_finder_chromeos.cc
+++ b/chrome/browser/ui/views/tabs/window_finder_chromeos.cc
@@ -3,23 +3,88 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/tabs/window_finder.h"
-#include "chrome/browser/ui/views/tabs/window_finder_mus.h"
 
+#include "ash/public/cpp/shell_window_ids.h"
+#include "ash/wm/root_window_finder.h"  // mash-ok
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/window.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/views/mus/mus_client.h"
+
+namespace {
 
 gfx::NativeWindow GetLocalProcessWindowAtPointAsh(
     const gfx::Point& screen_point,
-    const std::set<gfx::NativeWindow>& ignore);
+    const std::set<gfx::NativeWindow>& ignore,
+    gfx::NativeWindow window) {
+  if (ignore.find(window) != ignore.end())
+    return nullptr;
+
+  if (!window->IsVisible())
+    return nullptr;
+
+  if (window->id() == ash::kShellWindowId_PhantomWindow ||
+      window->id() == ash::kShellWindowId_OverlayContainer ||
+      window->id() == ash::kShellWindowId_MouseCursorContainer)
+    return nullptr;
+
+  if (window->layer()->type() == ui::LAYER_TEXTURED) {
+    // Returns the window that has visible layer and can hit the
+    // |screen_point|, because we want to detach the tab as soon as
+    // the dragging mouse moved over to the window that can hide the
+    // moving tab.
+    aura::client::ScreenPositionClient* client =
+        aura::client::GetScreenPositionClient(window->GetRootWindow());
+    gfx::Point local_point = screen_point;
+    client->ConvertPointFromScreen(window, &local_point);
+    return window->GetEventHandlerForPoint(local_point) ? window : nullptr;
+  }
+
+  for (aura::Window::Windows::const_reverse_iterator i =
+           window->children().rbegin();
+       i != window->children().rend(); ++i) {
+    gfx::NativeWindow result =
+        GetLocalProcessWindowAtPointAsh(screen_point, ignore, *i);
+    if (result)
+      return result;
+  }
+  return nullptr;
+}
+
+gfx::NativeWindow GetLocalProcessWindowAtPointMus(
+    const gfx::Point& screen_point,
+    const std::set<gfx::NativeWindow>& ignore) {
+  std::set<aura::Window*> root_windows =
+      views::MusClient::Get()->window_tree_client()->GetRoots();
+  // TODO(erg): Needs to deal with stacking order here.
+
+  // For every mus window, look at the associated aura window and see if we're
+  // in that.
+  for (aura::Window* root : root_windows) {
+    views::Widget* widget = views::Widget::GetWidgetForNativeView(root);
+    if (widget && widget->GetWindowBoundsInScreen().Contains(screen_point)) {
+      aura::Window* content_window = widget->GetNativeWindow();
+
+      // If we were instructed to ignore this window, ignore it.
+      if (base::ContainsKey(ignore, content_window))
+        continue;
+
+      return content_window;
+    }
+  }
+
+  return nullptr;
+}
+
+}  // namespace
 
 gfx::NativeWindow WindowFinder::GetLocalProcessWindowAtPoint(
     const gfx::Point& screen_point,
     const std::set<gfx::NativeWindow>& ignore) {
-  if (!features::IsAshInBrowserProcess()) {
-    gfx::NativeWindow mus_result = nullptr;
-    if (GetLocalProcessWindowAtPointMus(screen_point, ignore, &mus_result))
-      return mus_result;
-  }
+  if (!features::IsAshInBrowserProcess())
+    return GetLocalProcessWindowAtPointMus(screen_point, ignore);
 
-  return GetLocalProcessWindowAtPointAsh(screen_point, ignore);
+  return GetLocalProcessWindowAtPointAsh(
+      screen_point, ignore, ash::wm::GetRootWindowAt(screen_point));
 }
diff --git a/chrome/browser/ui/views/tabs/window_finder_mus.cc b/chrome/browser/ui/views/tabs/window_finder_mus.cc
deleted file mode 100644
index 700a2dee..0000000
--- a/chrome/browser/ui/views/tabs/window_finder_mus.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/tabs/window_finder_mus.h"
-
-#include "ui/aura/mus/window_tree_client.h"
-#include "ui/aura/window.h"
-#include "ui/views/mus/mus_client.h"
-
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#endif
-
-namespace {
-
-bool IsUsingMus() {
-#if defined(USE_AURA)
-  return aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS;
-#else
-  return false;
-#endif
-}
-
-}  // namespace
-
-bool GetLocalProcessWindowAtPointMus(
-    const gfx::Point& screen_point,
-    const std::set<gfx::NativeWindow>& ignore,
-    gfx::NativeWindow* mus_result) {
-  *mus_result = nullptr;
-  if (!IsUsingMus())
-    return false;
-
-  std::set<aura::Window*> root_windows =
-      views::MusClient::Get()->window_tree_client()->GetRoots();
-  // TODO(erg): Needs to deal with stacking order here.
-
-  // For every mus window, look at the associated aura window and see if we're
-  // in that.
-  for (aura::Window* root : root_windows) {
-    views::Widget* widget = views::Widget::GetWidgetForNativeView(root);
-    if (widget && widget->GetWindowBoundsInScreen().Contains(screen_point)) {
-      aura::Window* content_window = widget->GetNativeWindow();
-
-      // If we were instructed to ignore this window, ignore it.
-      if (base::ContainsKey(ignore, content_window))
-        continue;
-
-      *mus_result = content_window;
-      return true;
-    }
-  }
-
-  return true;
-}
diff --git a/chrome/browser/ui/views/tabs/window_finder_mus.h b/chrome/browser/ui/views/tabs/window_finder_mus.h
deleted file mode 100644
index 41f536f..0000000
--- a/chrome/browser/ui/views/tabs/window_finder_mus.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_TABS_WINDOW_FINDER_MUS_H_
-#define CHROME_BROWSER_UI_VIEWS_TABS_WINDOW_FINDER_MUS_H_
-
-#include "chrome/browser/ui/views/tabs/window_finder.h"
-
-// Used to locate the aura::Window under the specified point when in mus.
-// If running in mus true is returned and |mus_result| is set to the
-// aura::Window associated with the ui::Window under the specified point.
-// It's possible for true to be returned and mus_result to be set to null.
-bool GetLocalProcessWindowAtPointMus(
-    const gfx::Point& screen_point,
-    const std::set<gfx::NativeWindow>& ignore,
-    gfx::NativeWindow* mus_result);
-
-#endif  // CHROME_BROWSER_UI_VIEWS_TABS_WINDOW_FINDER_MUS_H_
diff --git a/chrome/browser/ui/views/tabs/window_finder_ozone.cc b/chrome/browser/ui/views/tabs/window_finder_ozone.cc
index d1be0df5..bb904744 100644
--- a/chrome/browser/ui/views/tabs/window_finder_ozone.cc
+++ b/chrome/browser/ui/views/tabs/window_finder_ozone.cc
@@ -3,15 +3,11 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/tabs/window_finder.h"
-#include "chrome/browser/ui/views/tabs/window_finder_mus.h"
 
 gfx::NativeWindow WindowFinder::GetLocalProcessWindowAtPoint(
     const gfx::Point& screen_point,
     const std::set<gfx::NativeWindow>& ignore) {
-  gfx::NativeWindow mus_result = nullptr;
-  if (GetLocalProcessWindowAtPointMus(screen_point, ignore, &mus_result))
-    return mus_result;
-
-  NOTREACHED() << "For Ozone builds, only mash launch is supported for now.";
+  NOTIMPLEMENTED()
+      << "For Ozone builds, window finder is not supported for now.";
   return nullptr;
 }
diff --git a/chrome/browser/ui/views/tabs/window_finder_win.cc b/chrome/browser/ui/views/tabs/window_finder_win.cc
index e632e52..7ce77a08 100644
--- a/chrome/browser/ui/views/tabs/window_finder_win.cc
+++ b/chrome/browser/ui/views/tabs/window_finder_win.cc
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/windows_version.h"
-#include "chrome/browser/ui/views/tabs/window_finder_mus.h"
 #include "ui/aura/window.h"
 #include "ui/display/win/screen_win.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
@@ -239,10 +238,6 @@
 gfx::NativeWindow WindowFinder::GetLocalProcessWindowAtPoint(
     const gfx::Point& screen_point,
     const std::set<gfx::NativeWindow>& ignore) {
-  gfx::NativeWindow mus_result = nullptr;
-  if (GetLocalProcessWindowAtPointMus(screen_point, ignore, &mus_result))
-    return mus_result;
-
   return LocalProcessWindowFinder::GetProcessWindowAtPoint(
       screen_point, RemapIgnoreSet(ignore));
 }
diff --git a/chrome/browser/ui/views/tabs/window_finder_x11.cc b/chrome/browser/ui/views/tabs/window_finder_x11.cc
index 909f5c4a..27280a4d 100644
--- a/chrome/browser/ui/views/tabs/window_finder_x11.cc
+++ b/chrome/browser/ui/views/tabs/window_finder_x11.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/views/tabs/window_finder.h"
 
-#include "chrome/browser/ui/views/tabs/window_finder_mus.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/point_conversions.h"
@@ -27,10 +26,6 @@
 gfx::NativeWindow WindowFinder::GetLocalProcessWindowAtPoint(
     const gfx::Point& screen_point,
     const std::set<gfx::NativeWindow>& ignore) {
-  gfx::NativeWindow mus_result = nullptr;
-  if (GetLocalProcessWindowAtPointMus(screen_point, ignore, &mus_result))
-    return mus_result;
-
   // The X11 server is the canonical state of what the window stacking order is.
   views::X11TopmostWindowFinder finder;
   return finder.FindLocalProcessWindowAt(DIPToPixelPoint(screen_point), ignore);
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index 22f1eba..d1db753 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -103,7 +103,7 @@
   builder->Add("rebootButton", IDS_RELAUNCH_BUTTON);
   builder->Add("diagnoseButton", IDS_DIAGNOSE_BUTTON);
   builder->Add("configureCertsButton", IDS_MANAGE_CERTIFICATES);
-  builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
+  builder->Add("continueButton", IDS_WELCOME_SELECTION_CONTINUE_BUTTON);
   builder->Add("okButton", IDS_APP_OK);
   builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME);
   builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME);
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 0d06906c..2d328a81 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/lifetime/browser_shutdown.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
@@ -579,6 +580,9 @@
   AddCallback("updateOobeDialogSize",
               &GaiaScreenHandler::HandleUpdateOobeDialogSize);
   AddCallback("hideOobeDialog", &GaiaScreenHandler::HandleHideOobeDialog);
+  AddCallback("updateSigninUIState",
+              &GaiaScreenHandler::HandleUpdateSigninUIState);
+  AddCallback("showGuestButton", &GaiaScreenHandler::HandleShowGuestButton);
 
   // Allow UMA metrics collection from JS.
   web_ui()->AddMessageHandler(std::make_unique<MetricsHandler>());
@@ -852,6 +856,26 @@
                             base::Value(false) /* isSamlUserPasswordless */);
 }
 
+void GaiaScreenHandler::HandleUpdateSigninUIState(int state) {
+  if (!ash::features::IsViewsLoginEnabled() ||
+      !LoginScreenClient::HasInstance()) {
+    return;
+  }
+
+  auto dialog_state = static_cast<ash::mojom::OobeDialogState>(state);
+  DCHECK(ash::mojom::IsKnownEnumValue(dialog_state));
+  LoginScreenClient::Get()->login_screen()->NotifyOobeDialogState(dialog_state);
+}
+
+void GaiaScreenHandler::HandleShowGuestButton(bool show) {
+  if (!ash::features::IsViewsLoginEnabled() ||
+      !LoginScreenClient::HasInstance()) {
+    return;
+  }
+
+  LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(show);
+}
+
 void GaiaScreenHandler::OnShowAddUser() {
   signin_screen_handler_->is_account_picker_showing_first_time_ = false;
   lock_screen_utils::EnforcePolicyInputMethods(std::string());
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 84306fd..6178fa46 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -137,6 +137,9 @@
   void HandleGetIsSamlUserPasswordless(const std::string& callback_id,
                                        const std::string& typed_email,
                                        const std::string& gaia_id);
+  void HandleUpdateSigninUIState(int state);
+  void HandleShowGuestButton(bool show);
+
   void OnShowAddUser();
 
   // Really handles the complete login message.
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
new file mode 100644
index 0000000..5af7430
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -0,0 +1,103 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h"
+
+#include <stddef.h>
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/login/screens/core_oobe_view.h"
+#include "chrome/browser/chromeos/login/screens/network_screen.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
+#include "components/login/localized_values_builder.h"
+
+namespace {
+
+const char kJsScreenPath[] = "login.NetworkScreen";
+
+}  // namespace
+
+namespace chromeos {
+
+NetworkScreenHandler::NetworkScreenHandler(CoreOobeView* core_oobe_view)
+    : BaseScreenHandler(kScreenId), core_oobe_view_(core_oobe_view) {
+  set_call_js_prefix(kJsScreenPath);
+  DCHECK(core_oobe_view_);
+}
+
+NetworkScreenHandler::~NetworkScreenHandler() {
+  if (screen_)
+    screen_->OnViewDestroyed(this);
+}
+
+void NetworkScreenHandler::Show() {
+  if (!page_is_ready()) {
+    show_on_init_ = true;
+    return;
+  }
+
+  // In OOBE all physical network technologies should be enabled, so the user is
+  // able to select any of the available networks on the device. Enabled
+  // technologies should not be changed if network screen is shown outside of
+  // OOBE.
+  // If OOBE is not completed, we assume that the only instance of this object
+  // could be OOBE itself.
+  if (!StartupUtils::IsOobeCompleted()) {
+    NetworkStateHandler* handler =
+        NetworkHandler::Get()->network_state_handler();
+    handler->SetTechnologyEnabled(NetworkTypePattern::Physical(), true,
+                                  chromeos::network_handler::ErrorCallback());
+  }
+  ShowScreen(kScreenId);
+}
+
+void NetworkScreenHandler::Hide() {}
+
+void NetworkScreenHandler::Bind(NetworkScreen* screen) {
+  screen_ = screen;
+  BaseScreenHandler::SetBaseScreen(screen_);
+}
+
+void NetworkScreenHandler::Unbind() {
+  screen_ = nullptr;
+  BaseScreenHandler::SetBaseScreen(nullptr);
+}
+
+void NetworkScreenHandler::ShowError(const base::string16& message) {
+  CallJS("showError", message);
+}
+
+void NetworkScreenHandler::ClearErrors() {
+  if (page_is_ready())
+    core_oobe_view_->ClearErrors();
+}
+
+void NetworkScreenHandler::ShowConnectingStatus(
+    bool connecting,
+    const base::string16& network_id) {}
+
+void NetworkScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {
+  builder->Add("networkSectionTitle", IDS_NETWORK_SELECTION_TITLE);
+  builder->Add("networkSectionHint", IDS_NETWORK_SELECTION_HINT);
+  builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME);
+  builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME);
+  network_element::AddLocalizedValuesToBuilder(builder);
+}
+
+void NetworkScreenHandler::GetAdditionalParameters(
+    base::DictionaryValue* dict) {}
+
+void NetworkScreenHandler::Initialize() {
+  if (show_on_init_) {
+    show_on_init_ = false;
+    Show();
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
new file mode 100644
index 0000000..1c88cdd
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_NETWORK_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_NETWORK_SCREEN_HANDLER_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/chromeos/login/screens/network_screen_view.h"
+#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
+
+namespace chromeos {
+
+class CoreOobeView;
+
+// WebUI implementation of NetworkScreenView. It is used to interact with
+// the OOBE network selection screen.
+class NetworkScreenHandler : public NetworkScreenView,
+                             public BaseScreenHandler {
+ public:
+  explicit NetworkScreenHandler(CoreOobeView* core_oobe_view);
+  ~NetworkScreenHandler() override;
+
+ private:
+  // NetworkScreenView:
+  void Show() override;
+  void Hide() override;
+  void Bind(NetworkScreen* screen) override;
+  void Unbind() override;
+  void ShowError(const base::string16& message) override;
+  void ClearErrors() override;
+  void ShowConnectingStatus(bool connecting,
+                            const base::string16& network_id) override;
+
+  // BaseScreenHandler:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+  void GetAdditionalParameters(base::DictionaryValue* dict) override;
+  void Initialize() override;
+
+  CoreOobeView* core_oobe_view_ = nullptr;
+  NetworkScreen* screen_ = nullptr;
+
+  // Keeps whether screen should be shown right after initialization.
+  bool show_on_init_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkScreenHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_NETWORK_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 4a80138..2500c7d 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -55,6 +55,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h"
 #include "chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h"
@@ -271,6 +272,8 @@
   if (display_type_ == kOobeDisplay)
     AddScreenHandler(std::make_unique<WelcomeScreenHandler>(core_handler_));
 
+  AddScreenHandler(std::make_unique<NetworkScreenHandler>(core_handler_));
+
   AddScreenHandler(std::make_unique<EnableDebuggingScreenHandler>());
 
   AddScreenHandler(std::make_unique<EulaScreenHandler>(core_handler_));
@@ -533,6 +536,10 @@
   return GetView<UserBoardScreenHandler>();
 }
 
+NetworkScreenView* OobeUI::GetNetworkScreenView() {
+  return GetView<NetworkScreenHandler>();
+}
+
 void OobeUI::OnShutdownPolicyChanged(bool reboot_on_shutdown) {
   core_handler_->UpdateShutdownAndRebootVisibility(reboot_on_shutdown);
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 65a907e..8b9699a 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -33,6 +33,8 @@
 class BaseScreenHandler;
 class ControllerPairingScreenView;
 class CoreOobeView;
+class DemoPreferencesScreenView;
+class DemoSetupScreenView;
 class DeviceDisabledScreenView;
 class EnableDebuggingScreenView;
 class EncryptionMigrationScreenView;
@@ -48,16 +50,14 @@
 class KioskEnableScreenView;
 class LoginScreenContext;
 class NativeWindowDelegate;
+class NetworkScreenView;
 class NetworkStateInformer;
-class WelcomeView;
 class OobeDisplayChooser;
 class RecommendAppsScreenView;
+class ResetView;
 class SigninScreenHandler;
 class SigninScreenHandlerDelegate;
 class SupervisedUserCreationScreenHandler;
-class ResetView;
-class DemoSetupScreenView;
-class DemoPreferencesScreenView;
 class SyncConsentScreenView;
 class TermsOfServiceScreenView;
 class UserBoardView;
@@ -66,6 +66,7 @@
 class UpdateRequiredView;
 class VoiceInteractionValuePropScreenView;
 class WaitForContainerReadyScreenView;
+class WelcomeView;
 class WrongHWIDScreenView;
 
 // A custom WebUI that defines datasource for out-of-box-experience (OOBE) UI:
@@ -135,6 +136,7 @@
   GaiaView* GetGaiaScreenView();
   UserBoardView* GetUserBoardView();
   DiscoverScreenView* GetDiscoverScreenView();
+  NetworkScreenView* GetNetworkScreenView();
 
   // ShutdownPolicyHandler::Delegate
   void OnShutdownPolicyChanged(bool reboot_on_shutdown) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
index 1b3047e9..f181f03 100644
--- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
@@ -11,38 +11,28 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
-#include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/customization/customization_document.h"
-#include "chrome/browser/chromeos/idle_detector.h"
 #include "chrome/browser/chromeos/login/screens/core_oobe_view.h"
 #include "chrome/browser/chromeos/login/screens/welcome_screen.h"
 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
-#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/browser/chromeos/system/timezone_util.h"
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
-#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/chromeos_switches.h"
-#include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_state_handler.h"
 #include "components/login/localized_values_builder.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
+#include "ui/base/ime/chromeos/component_extension_ime_manager.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/widget/widget.h"
+#include "ui/base/ime/chromeos/input_method_manager.h"
 
 namespace {
 
@@ -86,12 +76,6 @@
     return;
   }
 
-  // Make sure all physical network technologies are enabled. On OOBE, the user
-  // should be able to select any of the available networks on the device.
-  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
-  handler->SetTechnologyEnabled(NetworkTypePattern::Physical(), true,
-                                chromeos::network_handler::ErrorCallback());
-
   base::DictionaryValue welcome_screen_params;
   welcome_screen_params.SetBoolean(
       "isDeveloperMode", base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -112,23 +96,10 @@
   BaseScreenHandler::SetBaseScreen(nullptr);
 }
 
-void WelcomeScreenHandler::ShowError(const base::string16& message) {
-  CallJS("showError", message);
-}
-
-void WelcomeScreenHandler::ClearErrors() {
-  if (page_is_ready())
-    core_oobe_view_->ClearErrors();
-}
-
 void WelcomeScreenHandler::StopDemoModeDetection() {
   core_oobe_view_->StopDemoModeDetection();
 }
 
-void WelcomeScreenHandler::ShowConnectingStatus(
-    bool connecting,
-    const base::string16& network_id) {}
-
 void WelcomeScreenHandler::ReloadLocalizedContent() {
   base::DictionaryValue localized_strings;
   GetOobeUI()->GetLocalizedStrings(&localized_strings);
@@ -140,15 +111,14 @@
 void WelcomeScreenHandler::DeclareLocalizedValues(
     ::login::LocalizedValuesBuilder* builder) {
   if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation())
-    builder->Add("networkScreenGreeting", IDS_REMORA_CONFIRM_MESSAGE);
+    builder->Add("welcomeScreenGreeting", IDS_REMORA_CONFIRM_MESSAGE);
   else
-    builder->Add("networkScreenGreeting", IDS_WELCOME_SCREEN_GREETING);
+    builder->Add("welcomeScreenGreeting", IDS_WELCOME_SCREEN_GREETING);
 
-  builder->Add("networkScreenTitle", IDS_WELCOME_SCREEN_TITLE);
-  builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
+  builder->Add("welcomeScreenTitle", IDS_WELCOME_SCREEN_TITLE);
 
   // MD-OOBE (oobe-welcome-md)
-  builder->Add("debuggingFeaturesLink", IDS_NETWORK_ENABLE_DEV_FEATURES_LINK);
+  builder->Add("debuggingFeaturesLink", IDS_WELCOME_ENABLE_DEV_FEATURES_LINK);
   builder->Add("timezoneDropdownLabel", IDS_TIMEZONE_DROPDOWN_LABEL);
   builder->Add("oobeOKButtonText", IDS_OOBE_OK_BUTTON_TEXT);
   builder->Add("welcomeNextButtonText", IDS_OOBE_WELCOME_NEXT_BUTTON_TEXT);
@@ -157,8 +127,6 @@
   builder->Add("accessibilitySectionTitle", IDS_ACCESSIBILITY_SECTION_TITLE);
   builder->Add("accessibilitySectionHint", IDS_ACCESSIBILITY_SECTION_HINT);
   builder->Add("timezoneSectionTitle", IDS_TIMEZONE_SECTION_TITLE);
-  builder->Add("networkSectionTitle", IDS_NETWORK_SECTION_TITLE);
-  builder->Add("networkSectionHint", IDS_NETWORK_SECTION_HINT);
   builder->Add("advancedOptionsSectionTitle",
                IDS_OOBE_ADVANCED_OPTIONS_SCREEN_TITLE);
   builder->Add("advancedOptionsEEBootstrappingTitle",
@@ -178,8 +146,6 @@
   builder->Add("languageDropdownLabel", IDS_LANGUAGE_DROPDOWN_LABEL);
   builder->Add("keyboardDropdownTitle", IDS_KEYBOARD_DROPDOWN_TITLE);
   builder->Add("keyboardDropdownLabel", IDS_KEYBOARD_DROPDOWN_LABEL);
-  builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME);
-  builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME);
 
   builder->Add("highContrastOptionOff", IDS_HIGH_CONTRAST_OPTION_OFF);
   builder->Add("highContrastOptionOn", IDS_HIGH_CONTRAST_OPTION_ON);
@@ -194,7 +160,6 @@
 
   builder->Add("timezoneDropdownTitle", IDS_TIMEZONE_DROPDOWN_TITLE);
   builder->Add("timezoneButtonText", IDS_TIMEZONE_BUTTON_TEXT);
-  network_element::AddLocalizedValuesToBuilder(builder);
 }
 
 void WelcomeScreenHandler::GetAdditionalParameters(
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
index 73157f5..61e87a5 100644
--- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
@@ -6,16 +6,10 @@
 #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WELCOME_SCREEN_HANDLER_H_
 
 #include <memory>
-#include <string>
 
-#include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "chrome/browser/chromeos/base/locale_util.h"
 #include "chrome/browser/chromeos/login/screens/welcome_view.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-#include "ui/base/ime/chromeos/component_extension_ime_manager.h"
-#include "ui/base/ime/chromeos/input_method_manager.h"
-#include "ui/gfx/geometry/point.h"
 
 namespace base {
 class ListValue;
@@ -38,11 +32,7 @@
   void Hide() override;
   void Bind(WelcomeScreen* screen) override;
   void Unbind() override;
-  void ShowError(const base::string16& message) override;
-  void ClearErrors() override;
   void StopDemoModeDetection() override;
-  void ShowConnectingStatus(bool connecting,
-                            const base::string16& network_id) override;
   void ReloadLocalizedContent() override;
 
   // BaseScreenHandler implementation:
@@ -60,9 +50,6 @@
   // Keeps whether screen should be shown right after initialization.
   bool show_on_init_ = false;
 
-  // Position of the network control.
-  gfx::Point network_control_pos_;
-
   DISALLOW_COPY_AND_ASSIGN(WelcomeScreenHandler);
 };
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index f7c86340..66d0c07 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -31,6 +31,9 @@
     : account_manager_(account_manager),
       account_tracker_service_(account_tracker_service),
       weak_factory_(this) {
+  DCHECK(account_manager_);
+  DCHECK(account_tracker_service_);
+
   account_manager_->AddObserver(this);
   account_tracker_service_->AddObserver(this);
 }
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index 954647cb..e2feea6 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -183,15 +183,19 @@
   AddSettingsPageUIHandler(
       std::make_unique<chromeos::settings::AndroidAppsHandler>(profile));
 
-  chromeos::AccountManagerFactory* factory =
-      g_browser_process->platform_part()->GetAccountManagerFactory();
-  chromeos::AccountManager* account_manager =
-      factory->GetAccountManager(profile->GetPath().value());
-  DCHECK(account_manager);
-  AddSettingsPageUIHandler(
-      std::make_unique<chromeos::settings::AccountManagerUIHandler>(
-          account_manager,
-          AccountTrackerServiceFactory::GetInstance()->GetForProfile(profile)));
+  if (!profile->IsGuestSession()) {
+    chromeos::AccountManagerFactory* factory =
+        g_browser_process->platform_part()->GetAccountManagerFactory();
+    chromeos::AccountManager* account_manager =
+        factory->GetAccountManager(profile->GetPath().value());
+    DCHECK(account_manager);
+
+    AddSettingsPageUIHandler(
+        std::make_unique<chromeos::settings::AccountManagerUIHandler>(
+            account_manager,
+            AccountTrackerServiceFactory::GetInstance()->GetForProfile(
+                profile)));
+  }
   AddSettingsPageUIHandler(
       std::make_unique<chromeos::settings::ChangePictureHandler>());
   if (IsCrostiniUIAllowedForProfile(profile)) {
diff --git a/chrome/browser/ui/webui/welcome_ui.cc b/chrome/browser/ui/webui/welcome_ui.cc
index dc7d0286..db32e35 100644
--- a/chrome/browser/ui/webui/welcome_ui.cc
+++ b/chrome/browser/ui/webui/welcome_ui.cc
@@ -21,8 +21,11 @@
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "components/nux/show_promo_delegate.h"
 #include "components/nux_google_apps/constants.h"
-#include "components/nux_google_apps/webui.h"
+#include "components/nux_google_apps/google_apps_handler.h"
+#include "content/public/browser/web_contents.h"
 #endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
 
 namespace {
@@ -106,7 +109,14 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   if (base::FeatureList::IsEnabled(nux_google_apps::kNuxGoogleAppsFeature)) {
-    nux_google_apps::AddSources(html_source);
+    content::BrowserContext* browser_context =
+        web_ui->GetWebContents()->GetBrowserContext();
+    web_ui->AddMessageHandler(
+        std::make_unique<nux_google_apps::GoogleAppsHandler>(
+            profile->GetPrefs(),
+            BookmarkModelFactory::GetForBrowserContext(browser_context)));
+
+    nux_google_apps::GoogleAppsHandler::AddSources(html_source);
   }
 #endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD
 
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.cc b/chrome/browser/vr/metrics/session_metrics_helper.cc
index dfd7325..09871f1a 100644
--- a/chrome/browser/vr/metrics/session_metrics_helper.cc
+++ b/chrome/browser/vr/metrics/session_metrics_helper.cc
@@ -614,10 +614,11 @@
     // Get the ukm::SourceId from the handle so that we don't wind up with a
     // wrong ukm::SourceId from this WebContentObserver perhaps executing after
     // another which changes the SourceId.
+    ukm::SourceId source_id = ukm::ConvertToSourceId(
+        handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
     page_session_tracker_ =
         std::make_unique<SessionTracker<ukm::builders::XR_PageSession>>(
-            std::make_unique<ukm::builders::XR_PageSession>(
-                ukm::GetSourceIdForWebContentsDocument(web_contents())));
+            std::make_unique<ukm::builders::XR_PageSession>(source_id));
     if (pending_page_session_start_action_) {
       LogVrStartAction(*pending_page_session_start_action_);
       pending_page_session_start_action_ = base::nullopt;
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn
index 59124b9..040bc97 100644
--- a/chrome/chrome_cleaner/BUILD.gn
+++ b/chrome/chrome_cleaner/BUILD.gn
@@ -22,10 +22,14 @@
     "//chrome/chrome_cleaner/pup_data:unittest_sources",
     "//chrome/chrome_cleaner/settings:unittest_sources",
     "//chrome/chrome_cleaner/strings:unittest_sources",
+    "//chrome/chrome_cleaner/test:unittest_sources",
 
     # Dependencies of the test harness.
     "//base",
     "//base/test:test_support",
+    "//chrome/chrome_cleaner/os:cleaner_os",
+    "//chrome/chrome_cleaner/os:common_os",
+    "//chrome/chrome_cleaner/test:test_util",
     "//sandbox/win:sandbox",
     "//testing/gtest",
   ]
diff --git a/chrome/chrome_cleaner/DEPS b/chrome/chrome_cleaner/DEPS
index aa45b14..16f67f85 100644
--- a/chrome/chrome_cleaner/DEPS
+++ b/chrome/chrome_cleaner/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+sandbox/win/src",
   "+testing/gtest",
 ]
diff --git a/chrome/chrome_cleaner/os/BUILD.gn b/chrome/chrome_cleaner/os/BUILD.gn
index ee87e0ff..fe0dbf45 100644
--- a/chrome/chrome_cleaner/os/BUILD.gn
+++ b/chrome/chrome_cleaner/os/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-static_library("common_os") {
+source_set("common_os") {
   sources = [
     "digest_verifier.cc",
     "digest_verifier.h",
@@ -74,7 +74,6 @@
     "ntdll.lib",  # For NtQueryKey
     "secur32.lib",  # For GetUserNameEx
     "taskschd.lib",  # For CLSID_TaskScheduler
-    "wintrust.lib",  # For WinVerifyTrust
   ]
 
   defines = [ "SECURITY_WIN32" ]  # For secur32.lib
@@ -91,7 +90,7 @@
   ]
 }
 
-static_library("cleaner_os") {
+source_set("cleaner_os") {
   sources = [
     "file_removal_status_updater.cc",
     "file_removal_status_updater.h",
@@ -124,11 +123,27 @@
 
   sources = [
     # TODO(joenotcharles): Copy unit tests from the internal repo.
+    "digest_verifier_unittest.cc",
+    "disk_util_unittest.cc",
+    "file_path_sanitization_unittest.cc",
+    "file_path_set_unittest.cc",
+    "file_removal_status_updater_unittest.cc",
+    "file_remover_unittest.cc",
   ]
 
   deps = [
     ":cleaner_os",
     ":common_os",
     ":file_remover_api",
+    "//base",
+    "//base/test:test_config",
+    "//base/test:test_support",
+    "//chrome/chrome_cleaner/logging/proto:removal_status_proto",
+    "//chrome/chrome_cleaner/strings",
+    "//chrome/chrome_cleaner/test:test_executables",
+    "//chrome/chrome_cleaner/test:test_strings",
+    "//chrome/chrome_cleaner/test:test_util",
+    "//chrome/chrome_cleaner/test/resources:test_resources",
+    "//testing/gtest",
   ]
 }
diff --git a/chrome/chrome_cleaner/os/digest_verifier_unittest.cc b/chrome/chrome_cleaner/os/digest_verifier_unittest.cc
new file mode 100644
index 0000000..2be0340
--- /dev/null
+++ b/chrome/chrome_cleaner/os/digest_verifier_unittest.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/digest_verifier.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
+#include "chrome/chrome_cleaner/os/system_util.h"
+#include "chrome/chrome_cleaner/test/resources/grit/test_resources.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+TEST(DigestVerifier, KnownFile) {
+  std::shared_ptr<DigestVerifier> digest_verifier =
+      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
+  ASSERT_TRUE(digest_verifier);
+
+  base::FilePath dll_path = GetSampleDLLPath();
+  ASSERT_TRUE(base::PathExists(dll_path)) << dll_path.value();
+
+  EXPECT_TRUE(digest_verifier->IsKnownFile(dll_path));
+}
+
+TEST(DigestVerifier, UnknownFile) {
+  std::shared_ptr<DigestVerifier> digest_verifier =
+      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
+  ASSERT_TRUE(digest_verifier);
+
+  const base::FilePath self_path =
+      PreFetchedPaths::GetInstance()->GetExecutablePath();
+
+  EXPECT_FALSE(digest_verifier->IsKnownFile(self_path));
+}
+
+TEST(DigestVerifier, InexistentFile) {
+  std::shared_ptr<DigestVerifier> digest_verifier =
+      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
+  ASSERT_TRUE(digest_verifier);
+
+  base::FilePath invalid_path(L"this_file_should_not_exist.dll");
+  ASSERT_FALSE(base::PathExists(invalid_path));
+
+  EXPECT_FALSE(digest_verifier->IsKnownFile(invalid_path));
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/disk_util.cc b/chrome/chrome_cleaner/os/disk_util.cc
index 5e0534a..6b8e4b2 100644
--- a/chrome/chrome_cleaner/os/disk_util.cc
+++ b/chrome/chrome_cleaner/os/disk_util.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/chrome_cleaner/os/disk_util.h"
 
-#include <softpub.h>
 #include <stdint.h>
 
 #include <algorithm>
@@ -135,22 +134,6 @@
   }
 }
 
-// Return whether an executable is whitelisted. On success, |file_information|
-// receives the file version information. |file_information| is not modified by
-// this function but cannot be const because of the accessors prototype in base.
-bool IsExecutableWhiteListed(FileVersionInfo* file_information) {
-  DCHECK(file_information);
-  bool white_listed = false;
-  base::string16 company_name = file_information->company_name();
-  for (const base::string16& white_listed_name : company_white_list) {
-    if (company_name.compare(white_listed_name) == 0) {
-      white_listed = true;
-      break;
-    }
-  }
-  return white_listed;
-}
-
 void AppendFileInformationField(const wchar_t* field_name,
                                 const base::string16& field,
                                 base::string16* information) {
@@ -520,10 +503,28 @@
   return content;
 }
 
+bool IsExecutableOnDefaultReportingWhiteList(const base::FilePath& file_path) {
+  std::unique_ptr<FileVersionInfo> file_information(
+      FileVersionInfo::CreateFileVersionInfo(file_path));
+  if (!file_information)
+    return false;
+
+  bool white_listed = false;
+  base::string16 company_name = file_information->company_name();
+  for (const base::string16& white_listed_name : company_white_list) {
+    if (company_name.compare(white_listed_name) == 0) {
+      white_listed = true;
+      break;
+    }
+  }
+  return white_listed;
+}
+
 bool RetrieveDetailedFileInformation(
     const base::FilePath& file_path,
     internal::FileInformation* file_information,
-    bool* white_listed) {
+    bool* white_listed,
+    ReportingWhiteListCallback white_list_callback) {
   DCHECK(file_information);
   DCHECK(white_listed);
 
@@ -531,9 +532,7 @@
   if (!TryToExpandPath(file_path, &expanded_path))
     return false;
 
-  std::unique_ptr<FileVersionInfo> version(
-      FileVersionInfo::CreateFileVersionInfo(expanded_path));
-  if (version.get() && IsExecutableWhiteListed(version.get())) {
+  if (std::move(white_list_callback).Run(file_path)) {
     *white_listed = true;
     return false;
   }
@@ -550,7 +549,9 @@
   }
 
   // Set the executable version information, when available.
-  if (version.get()) {
+  std::unique_ptr<FileVersionInfo> version(
+      FileVersionInfo::CreateFileVersionInfo(expanded_path));
+  if (version) {
     file_information->company_name = version->company_name();
     file_information->company_short_name = version->company_short_name();
     file_information->product_name = version->product_name();
diff --git a/chrome/chrome_cleaner/os/disk_util.h b/chrome/chrome_cleaner/os/disk_util.h
index 201c5dcc..4285c1e8 100644
--- a/chrome/chrome_cleaner/os/disk_util.h
+++ b/chrome/chrome_cleaner/os/disk_util.h
@@ -14,6 +14,8 @@
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "base/strings/string16.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/chrome_cleaner/os/disk_util_types.h"
@@ -27,6 +29,9 @@
 
 class LayeredServiceProviderAPI;
 
+typedef base::OnceCallback<bool(const base::FilePath&)>
+    ReportingWhiteListCallback;
+
 // Return the full path of the relative path |input_path| when expanded to the
 // 64 bits program files path. Return an empty path when not running on 64 bits
 // OS.
@@ -92,13 +97,20 @@
 base::string16 FileInformationToString(
     const internal::FileInformation& file_information);
 
+// Returns true if the given |path| refers to an executable which is
+// whitelisted so that its details should not be reported.
+bool IsExecutableOnDefaultReportingWhiteList(const base::FilePath& file_path);
+
 // Retrieve the detailed information for the executable |file_path| and append
-// the fields to |file_information|. If the executable is |white_listed|,
-// |file_information| stay unchanged.
+// the fields to |file_information|. If the executable is |white_listed|
+// according to the given |white_list_callback|, |file_information| stays
+// unchanged.
 bool RetrieveDetailedFileInformation(
     const base::FilePath& file_path,
     internal::FileInformation* file_information,
-    bool* white_listed);
+    bool* white_listed,
+    ReportingWhiteListCallback white_list_callback =
+        base::BindOnce(&IsExecutableOnDefaultReportingWhiteList));
 
 // Retrieve the file information path, dates and size into |file_information|.
 bool RetrieveBasicFileInformation(const base::FilePath& file_path,
diff --git a/chrome/chrome_cleaner/os/disk_util_unittest.cc b/chrome/chrome_cleaner/os/disk_util_unittest.cc
new file mode 100644
index 0000000..84eaada
--- /dev/null
+++ b/chrome/chrome_cleaner/os/disk_util_unittest.cc
@@ -0,0 +1,1237 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/disk_util.h"
+
+#include <windows.h>
+
+#include <shlobj.h>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/stl_util.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_path_override.h"
+#include "base/test/test_shortcut_win.h"
+#include "base/test/test_timeouts.h"
+#include "base/win/windows_version.h"
+#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
+#include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
+#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
+#include "chrome/chrome_cleaner/strings/string_util.h"
+#include "chrome/chrome_cleaner/test/test_executables.h"
+#include "chrome/chrome_cleaner/test/test_file_util.h"
+#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+// A path name under program files.
+const wchar_t kProgramFilesBaseName[] = L"Foo";
+
+// Keep these digests in sorted order.
+const char* const kFileContentDigests[] = {
+    "02544E052F29BBA79C81243EC63B43B6CD85B185461928E65BFF501346C62A75",
+    "04614470DDF4939091F5EC4A13C92A9EAAACF07CA5C3F713E792E2D21CD24075",
+    // Hash for content: |kFileContent2|.
+    "82E0B92772BC0DA59AAB0B9231AA006FB37B4F99EC3E853C5A62786A1C7215BD",
+    "94F7BDF53CDFDE7AA5E5C90BCDA6793B7377CE39E2591ABC758EBAE8072A275C",
+    // Hash for content: |kFileContent1|.
+    "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371"};
+
+const wchar_t kFileName1[] = L"Filename one";
+const wchar_t kFileName2[] = L"Filename two";
+const wchar_t kFileName3[] = L"Third filename";
+const wchar_t kLongFileName1[] = L"Long File Name.bla";
+const wchar_t kLongFileName2[] = L"Other Long File Name.bla";
+const wchar_t kLongFileName2Subset[] = L"Long File";
+const char kFileContent1[] = "This is the file content.";
+const char kFileContent2[] = "Hi!";
+const char kFileContent3[] = "Hello World!";
+
+const internal::FileInformation kFileInformation1(L"some/path/something.tmp",
+                                                  "3/1/2016",
+                                                  "3/3/2016",
+                                                  "somedigest1234",
+                                                  9876,
+                                                  L"Company Name",
+                                                  L"CNShort",
+                                                  L"Product Name",
+                                                  L"PNShort",
+                                                  L"Internal Name",
+                                                  L"Something_Original.tmp",
+                                                  L"Very descriptive",
+                                                  L"42.1.2");
+
+const wchar_t kFileInformation1ExpectedString[] =
+    L"path = 'some/path/something.tmp', file_creation_date = "
+    L"'3/1/2016', file_last_modified_date = '3/3/2016', digest = "
+    L"'somedigest1234', size = '9876', company_name = 'Company Name', "
+    L"company_short_name = 'CNShort', product_name = 'Product Name', "
+    L"product_short_name = 'PNShort', internal_name = 'Internal Name', "
+    L"original_filename = 'Something_Original.tmp', file_description = 'Very "
+    L"descriptive', file_version = '42.1.2', active_file = '0'";
+
+// All potential format of content that get from registry. %ls will be replaced
+// by the executable path.
+// clang-format off
+const wchar_t* kMockRegistryContents[] = {
+    // Straight path as is.
+    L"%ls",
+    L"\"%ls\"",
+    // With command line arguments.
+    L"%ls -s",
+    L"\"%ls\" -s",
+    L"\"%ls -s\"",
+    // Using rundll.
+    L"C:\\Windows\\SysWow64\\rundll32 %ls",
+    L"C:\\Windows\\SysWow64\\rundll32 \"%ls\"",
+    // Using rundll with args.
+    L"C:\\Windows\\SysWow64\\rundll32.exe %ls,OpenAs_RunDLL %%1",
+    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\",OpenAs_RunDLL %%1",
+    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls,OpenAs_RunDLL\" %%1",
+    L"C:\\Windows\\SysWow64\\rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
+    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\" a1,OpenAs_RunDLL %%1",
+    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls a1,OpenAs_RunDLL\" %%1",
+    L"C:\\Windows\\System32\\rundll32 %ls",
+    // Rundll without a path.
+    L"rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
+    L"rundll32.exe \"%ls\" -s %%1",
+    L"rundll32.exe \"%ls -s\" %%1",
+    // Rundll without extension.
+    L"C:\\Windows\\SysWow64\\rundll32 %ls a1 a2,OpenAs_RunDLL %%1",
+    L"C:\\Windows\\SysWow64\\rundll32 \"%ls\" -s %%1",
+    L"C:\\Windows\\SysWow64\\rundll32 \"%ls -s\" %%1"};
+// clang-format on
+
+bool LaunchTestProcess(const wchar_t* executable,
+                       const char* action,
+                       bool wait) {
+  base::FilePath executable_path(executable);
+  base::CommandLine command_line(executable_path);
+  command_line.AppendSwitch(action);
+  base::LaunchOptions options = base::LaunchOptions();
+  options.wait = wait;
+  return base::LaunchProcess(command_line, options).IsValid();
+}
+
+bool DoesVolumeSupportNamedStreams(const base::FilePath& path) {
+  std::vector<base::string16> components;
+  path.GetComponents(&components);
+  DCHECK(!components.empty());
+  base::string16& drive = components[0];
+  drive += L'\\';
+  DWORD system_flags = 0;
+  if (::GetVolumeInformation(drive.c_str(), nullptr, 0, nullptr, nullptr,
+                             &system_flags, nullptr, 0) != TRUE) {
+    PLOG(ERROR) << "Cannot retrieve drive information: '" << path.value()
+                << "'.";
+    return false;
+  }
+
+  return (system_flags & FILE_NAMED_STREAMS) != 0;
+}
+
+void CreateProgramPathsAndFiles(const base::FilePath& temp_dir_path,
+                                base::FilePath* program_path,
+                                base::FilePath* spaced_program_path) {
+  DCHECK(program_path);
+  DCHECK(spaced_program_path);
+  base::FilePath folder;
+  base::FilePath file_path;
+  base::FilePath spaced_folder;
+  base::FilePath spaced_file_path;
+
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"folder", &folder));
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"  spaced folder",
+                                            &spaced_folder));
+
+  ASSERT_TRUE(CreateTemporaryFileInDir(folder, &file_path));
+  ASSERT_TRUE(CreateTemporaryFileInDir(spaced_folder, &spaced_file_path));
+
+  *program_path = file_path;
+  *spaced_program_path = spaced_file_path;
+}
+
+// Substitutes |registry_path| into each entry in the mock registry in turn
+// and passes the result to ExtractExecutablePathFromRegistryContent to get a
+// file path. Returns success if every file path matches |expected_path|.
+::testing::AssertionResult ExtractExecutablePathFromMockRegistryAndExpect(
+    const base::string16& registry_path,
+    const base::FilePath& expected_path) {
+  for (const base::string16& registry_content : kMockRegistryContents) {
+    base::string16 full_registry_content =
+        base::StringPrintf(registry_content.c_str(), registry_path.c_str());
+    base::FilePath extracted_path =
+        ExtractExecutablePathFromRegistryContent(full_registry_content);
+    if (!PathEqual(expected_path, extracted_path)) {
+      return ::testing::AssertionFailure()
+             << expected_path.value() << " != " << extracted_path.value()
+             << ", full_registry_content = " << full_registry_content;
+    }
+  }
+  return ::testing::AssertionSuccess();
+}
+
+// Return that the sample DLL is whitelisted and all other files are not.
+bool WhitelistSampleDLL(const base::FilePath& path) {
+  return PathEqual(path, GetSampleDLLPath());
+}
+
+}  // namespace
+
+TEST(DiskUtilTests, GetX64ProgramFilePath) {
+  base::FilePath x64_program_files =
+      GetX64ProgramFilesPath(base::FilePath(kProgramFilesBaseName));
+  if (base::win::OSInfo::GetInstance()->architecture() ==
+      base::win::OSInfo::X86_ARCHITECTURE) {
+    EXPECT_TRUE(x64_program_files.empty());
+    return;
+  }
+
+  EXPECT_FALSE(x64_program_files.empty());
+  EXPECT_NE(x64_program_files,
+            ExpandSpecialFolderPath(CSIDL_PROGRAM_FILES,
+                                    base::FilePath(kProgramFilesBaseName)));
+}
+
+TEST(DiskUtilTests, PathContainsWildcards) {
+  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\foo.txt")));
+  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\bar\\foo.txt")));
+  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t?t")));
+  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t*t")));
+  EXPECT_TRUE(
+      PathContainsWildcards(base::FilePath(L"c:\\"
+                                           LR"(???)"
+                                           L"*\\foo.txt")));
+  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"*:\\")));
+  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"foo.txt")));
+  EXPECT_TRUE(PathContainsWildcards(base::FilePath(LR"(foo.???)")));
+}
+
+TEST(DiskUtilTests, CollectMatchingPathsMultipleWildcards) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  // Create files and folders under |temp_dir| and add them to |expected_files|.
+  std::set<base::FilePath> expected_files;
+
+  base::ScopedTempDir sub_dir1;
+  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::ScopedTempDir sub_dir2;
+  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
+  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
+
+  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
+  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
+
+  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
+  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
+
+  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
+  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
+
+  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
+  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
+
+  expected_files.insert(sub_dir1_file_path1);
+  expected_files.insert(sub_dir1_file_path2);
+  expected_files.insert(sub_dir2_file_path1);
+  expected_files.insert(sub_dir2_file_path2);
+
+  base::FilePath wildcard_path1(
+      temp_dir.GetPath().Append(L"*").Append(L"Filename*"));
+  std::vector<base::FilePath> matches;
+  CollectMatchingPaths(wildcard_path1, &matches);
+  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
+}
+
+TEST(DiskUtilTests, CollectMatchingPathsDriveWildcard) {
+  std::vector<base::FilePath> matches;
+
+  // The drive could not be enumerated, thus no file will exists..
+  base::FilePath wildcard_path1(L"*:\\test");
+  CollectMatchingPaths(wildcard_path1, &matches);
+  EXPECT_TRUE(matches.empty());
+
+  base::FilePath wildcard_path2(L"*:\\");
+  CollectMatchingPaths(wildcard_path2, &matches);
+  EXPECT_TRUE(matches.empty());
+}
+
+TEST(DiskUtilTests, CollectMatchingPathsDirectoryWildcard) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  // Create files and folders under |temp_dir| and add them to |expected_files|.
+  std::set<base::FilePath> expected_files;
+
+  base::ScopedTempDir sub_dir1;
+  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::ScopedTempDir sub_dir2;
+  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
+  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
+
+  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
+  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
+
+  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
+  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
+
+  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
+  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
+
+  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
+  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
+
+  expected_files.insert(sub_dir1_file_path1);
+  expected_files.insert(sub_dir2_file_path1);
+  base::FilePath wildcard_path3(
+      temp_dir.GetPath().Append(L"*").Append(kFileName1));
+  std::vector<base::FilePath> matches;
+  CollectMatchingPaths(wildcard_path3, &matches);
+  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
+}
+
+TEST(DiskUtilTests, CollectMatchingPathsMultipleFileWildcards) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::ScopedTempDir sub_dir1;
+  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::ScopedTempDir sub_dir2;
+  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
+  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
+
+  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
+  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
+
+  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
+  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
+
+  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
+  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
+
+  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
+  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
+
+  // Create files and folders under |temp_dir| and add them to |expected_files|.
+  std::set<base::FilePath> expected_files;
+  expected_files.insert(sub_dir1_file_path3);
+  base::FilePath wildcard_path4(
+      temp_dir.GetPath().Append(L"*").Append(L"*Third*"));
+  std::vector<base::FilePath> matches;
+  CollectMatchingPaths(wildcard_path4, &matches);
+  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
+}
+
+TEST(DiskUtilTests, CollectMatchingPathsNoWildcards) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::ScopedTempDir sub_dir;
+  ASSERT_TRUE(sub_dir.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::FilePath sub_dir_file_path1(sub_dir.GetPath().Append(kFileName1));
+  base::File sub_dir_file1(sub_dir_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir_file_path1));
+
+  base::FilePath sub_dir_file_path2(sub_dir.GetPath().Append(kFileName2));
+  base::File sub_dir_file2(sub_dir_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir_file_path2));
+
+  base::FilePath sub_dir_file_path3(sub_dir.GetPath().Append(kFileName3));
+  base::File sub_dir_file3(sub_dir_file_path3, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir_file_path3));
+
+  // Create files and folders under |temp_dir| and add them to |expected_files|.
+  std::vector<base::FilePath> matches;
+
+  base::FilePath no_wildcard_path(sub_dir.GetPath());
+  CollectMatchingPaths(no_wildcard_path, &matches);
+  EXPECT_EQ(1UL, matches.size());
+  EXPECT_NE(matches.end(),
+            std::find(matches.begin(), matches.end(), sub_dir.GetPath()));
+}
+
+TEST(DiskUtilTests, CollectExecutableMatchingPaths) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::FilePath subfolder1_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
+                                            &subfolder1_path));
+
+  base::FilePath subfolder2_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
+                                            &subfolder2_path));
+
+  base::FilePath subfolder3_path(subfolder2_path.Append(L"folder.exe"));
+  ASSERT_TRUE(base::CreateDirectory(subfolder3_path));
+
+  base::FilePath file_path1(subfolder1_path.Append(L"dummy1.exe"));
+  base::FilePath file_path2(subfolder1_path.Append(L"dummy2.exe"));
+  base::FilePath file_path3(subfolder2_path.Append(L"dummy3.exe"));
+  base::FilePath file_path4(subfolder2_path.Append(L"dummy4.exe"));
+  base::FilePath file_path5(subfolder2_path.Append(L"info.exe.txt"));
+  base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
+
+  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
+  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
+  CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
+  CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
+  CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
+  CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
+
+  base::FilePath wildcard_path(temp_dir.GetPath().Append(L"*\\*.exe"));
+  std::vector<base::FilePath> executable_matches;
+  CollectMatchingPaths(wildcard_path, &executable_matches);
+
+  EXPECT_THAT(executable_matches,
+              testing::ElementsAre(file_path1, file_path2, file_path3,
+                                   file_path4, subfolder3_path));
+}
+
+TEST(DiskUtilTests, CollectMultipleDotWildcardsMatchingPaths) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::FilePath subfolder1_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
+                                            &subfolder1_path));
+
+  base::FilePath subfolder2_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
+                                            &subfolder2_path));
+
+  base::FilePath subfolder3_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(subfolder2_path, L"folder.exe",
+                                            &subfolder3_path));
+
+  base::FilePath file_path1(subfolder1_path.Append(L"dummy1.tar.gz"));
+  base::FilePath file_path2(subfolder1_path.Append(L"dummy2.12.exe"));
+  base::FilePath file_path3(subfolder2_path.Append(L"dummy3.tar.gz"));
+  base::FilePath file_path4(subfolder2_path.Append(L"dummy4.12.exe"));
+  base::FilePath file_path5(subfolder2_path.Append(L"info.tar.gz.txt"));
+  base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
+
+  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
+  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
+  CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
+  CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
+  CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
+  CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
+
+  base::FilePath wildcard_path_tar_gz(
+      temp_dir.GetPath().Append(L"*\\*.tar.gz"));
+  std::vector<base::FilePath> executable_matches_tar_gz;
+  CollectMatchingPaths(wildcard_path_tar_gz, &executable_matches_tar_gz);
+
+  EXPECT_THAT(executable_matches_tar_gz,
+              testing::ElementsAre(file_path1, file_path3));
+
+  base::FilePath wildcard_path_all(temp_dir.GetPath().Append(L"*\\*.*.*"));
+  std::vector<base::FilePath> executable_matches_all;
+  CollectMatchingPaths(wildcard_path_all, &executable_matches_all);
+
+  EXPECT_THAT(executable_matches_all,
+              testing::ElementsAre(file_path1, file_path2, file_path3,
+                                   file_path4, file_path5));
+}
+
+TEST(DiskUtilTests, CollectEmptyDirMatchingPaths) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::FilePath subfolder1_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
+                                            &subfolder1_path));
+
+  base::FilePath subfolder2_path;
+  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
+                                            &subfolder2_path));
+
+  base::FilePath wildcard_path1(temp_dir.GetPath().Append(L"*\\dummy.exe"));
+  std::vector<base::FilePath> executable_matches;
+  CollectMatchingPaths(wildcard_path1, &executable_matches);
+  EXPECT_TRUE(executable_matches.empty());
+}
+
+TEST(DiskUtilTests, CollectCumulativeMatchingPaths) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::ScopedTempDir sub_dir1;
+  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  // Create files and folders under |sub_dirX| and add them to |expected_files|.
+  std::set<base::FilePath> expected_files;
+  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
+  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
+  expected_files.insert(sub_dir1_file_path1);
+
+  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
+  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
+  expected_files.insert(sub_dir1_file_path2);
+
+  base::ScopedTempDir sub_dir2;
+  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
+
+  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
+  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
+  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
+  expected_files.insert(sub_dir2_file_path1);
+
+  base::FilePath wildcard_path1(sub_dir1.GetPath().Append(L"*"));
+  std::vector<base::FilePath> matches;
+  CollectMatchingPaths(wildcard_path1, &matches);
+  base::FilePath wildcard_path2(sub_dir2.GetPath().Append(L"*"));
+  CollectMatchingPaths(wildcard_path2, &matches);
+  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
+}
+
+TEST(DiskUtilTests, PathHasActiveExtension) {
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe")));
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe  ")));
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg.exe")));
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.lnk")));
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file")));
+  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\file.lnk::$DATA")));
+
+  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.wvm")));
+  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg")));
+  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg ")));
+  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\file.txt::$DATA")));
+}
+
+TEST(DiskUtilTests, HasDosExecutableHeader) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath executable = temp.GetPath().Append(L"executable.txt");
+  const char kExecutableFileContents[] = "MZ I am executable";
+  chrome_cleaner::CreateFileWithContent(executable, kExecutableFileContents,
+                                        sizeof(kExecutableFileContents));
+  EXPECT_TRUE(HasDosExecutableHeader(executable));
+
+  base::FilePath non_executable = temp.GetPath().Append(L"text.exe");
+  const char kTextFileContents[] = "I am benign text";
+  chrome_cleaner::CreateFileWithContent(non_executable, kTextFileContents,
+                                        sizeof(kTextFileContents));
+  EXPECT_FALSE(HasDosExecutableHeader(non_executable));
+}
+
+TEST(DiskUtilTests, HasAlternateFileStream) {
+  EXPECT_FALSE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt")));
+  EXPECT_FALSE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt::$DATA")));
+
+  EXPECT_TRUE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt:stream")));
+  EXPECT_TRUE(
+      HasAlternateFileStream(base::FilePath(L"C:\\file.txt:stream:$TYPE")));
+}
+
+TEST(DiskUtilTests, ExpandEnvPath) {
+  ASSERT_TRUE(
+      ::SetEnvironmentVariable(L"CLEANER_TEST_VAR", L"CLEANER_TEST_VALUE"));
+  ASSERT_TRUE(::SetEnvironmentVariable(L"ROOT_TEST_VAR", L"c:\\root"));
+  base::FilePath test_path1(L"C:\\%CLEANER_TEST_VAR%\\test\\foo");
+  base::FilePath test_path2(L"%ROOT_TEST_VAR%\\test\\foo");
+  base::FilePath test_path3(
+      L"C:\\aa%CLEANER_TEST_VAR%bb\\test\\%%CLEANER_TEST_VAR%%");
+
+  base::FilePath expanded_path;
+  ExpandEnvPath(test_path1, &expanded_path);
+  EXPECT_EQ(L"C:\\CLEANER_TEST_VALUE\\test\\foo", expanded_path.value());
+
+  ExpandEnvPath(test_path2, &expanded_path);
+  EXPECT_EQ(L"c:\\root\\test\\foo", expanded_path.value());
+
+  ExpandEnvPath(test_path3, &expanded_path);
+  EXPECT_EQ(L"C:\\aaCLEANER_TEST_VALUEbb\\test\\%CLEANER_TEST_VALUE%",
+            expanded_path.value());
+}
+
+TEST(DiskUtilTests, ExpandWow64Path) {
+  base::ScopedPathOverride windows_override(
+      CsidlToPathServiceKey(CSIDL_WINDOWS));
+  base::FilePath windows_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_WINDOWS),
+                                     &windows_folder));
+
+  base::FilePath system_folder(windows_folder.Append(L"system32"));
+  base::ScopedPathOverride system_override(CsidlToPathServiceKey(CSIDL_SYSTEM),
+                                           system_folder, true, true);
+
+  base::FilePath native_folder(windows_folder.Append(L"sysnative"));
+  ASSERT_TRUE(base::CreateDirectory(native_folder));
+
+  base::FilePath file_path1(system_folder.Append(kFileName1));
+  base::FilePath file_path2(native_folder.Append(kFileName2));
+  base::FilePath file_path3_system(system_folder.Append(kFileName3));
+  base::FilePath file_path3_native(native_folder.Append(kFileName3));
+  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
+  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
+  CreateFileWithContent(file_path3_system, kFileContent3,
+                        sizeof(kFileContent3));
+  CreateFileWithContent(file_path3_native, kFileContent3,
+                        sizeof(kFileContent3));
+
+  base::FilePath expanded_file1;
+  ExpandWow64Path(file_path1, &expanded_file1);
+  ASSERT_TRUE(PathEqual(expanded_file1, file_path1));
+
+  base::FilePath expanded_file2;
+  ExpandWow64Path(file_path2, &expanded_file2);
+  ASSERT_TRUE(PathEqual(expanded_file2, file_path2));
+
+  base::FilePath expanded_file3;
+  ExpandWow64Path(file_path3_system, &expanded_file3);
+  ASSERT_TRUE(PathEqual(expanded_file3, file_path3_native));
+}
+
+TEST(DiskUtilTests, ComputeDigestSHA256) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  // Check the digest of an non-existing file.
+  base::FilePath file_path1(temp_dir.GetPath().Append(kFileName1));
+  std::string digest1;
+  EXPECT_FALSE(ComputeDigestSHA256(file_path1, &digest1));
+  EXPECT_TRUE(digest1.empty());
+
+  // Create an empty file and validate the digest.
+  base::FilePath file_path2(temp_dir.GetPath().Append(kFileName2));
+  base::File empty_file(file_path2, base::File::FLAG_CREATE);
+  empty_file.Close();
+
+  std::string digest2;
+  EXPECT_TRUE(ComputeDigestSHA256(file_path2, &digest2));
+  EXPECT_STREQ(
+      "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
+      digest2.c_str());
+
+  // Create a file with some content and validate the digest.
+  base::FilePath file_path3(temp_dir.GetPath().Append(kFileName3));
+  base::File valid_file(
+      file_path3, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+  ASSERT_EQ(sizeof(kFileContent),
+            static_cast<size_t>(valid_file.WriteAtCurrentPos(
+                kFileContent, sizeof(kFileContent))));
+  valid_file.Close();
+
+  std::string digest3;
+  EXPECT_TRUE(ComputeDigestSHA256(file_path3, &digest3));
+  EXPECT_STREQ(
+      "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371",
+      digest3.c_str());
+}
+
+TEST(DiskUtilTests, ComputeDigestSHA256OnBigFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  struct DigestInfo {
+    size_t size;
+    const char* digest;
+  } digests[] = {
+      {1, "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"},
+      {2, "FB8E20FC2E4C3F248C60C39BD652F3C1347298BB977B8B4D5903B85055620603"},
+      {3, "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"},
+      {100, "2AC123DCD759EEBABFA1B17C0332B88B3815EF3F95FBFCCEB5FAC07E233235BD"},
+      {128, "6C05BE2C4268843AE47E68E611277CE62C02153F2F4D2E1E2A1A4B44F766CF74"},
+      {1000,
+       "915E53A44C18B19BB06BA5B3F5FCAF1DC4651E8404C63425CFC6174E74659D87"},
+      {1023,
+       "6A6EE128AAC6B98D2697EED0A912AE264603D046B3CBFD5E7EA1D01C865474D9"},
+      {1024,
+       "DBA4A6315B76548B7A4DD079EF6AA29A7B34FA8B92C11668473441715C5F0AF5"},
+      {1025,
+       "2B4B65474580781B4DC0AB66B9A0F39B869DE5A44CF26DBA22AC0496760D4230"},
+      {4095,
+       "7413609B553226A9A8A3203A82062111DC1F98C24163E303774F27E4F615BFB2"},
+      {4096,
+       "BC45051AC426475F459EC0B0C88A6646D037B8DFB1B9FA3CA3EF9203CE33E283"},
+      {4097,
+       "A9145EB3812CA8F11A014029FEE1854FABB76D2FFEA680D0875F78FA786F58B8"},
+      {10000,
+       "5B92F844F0ED521B75688F4B6FF58E127711709613589EB6EC88FDFBBDC7DC63"}};
+
+  for (size_t offset = 0; offset < base::size(digests); ++offset) {
+    DigestInfo* info = &digests[offset];
+    DCHECK(info);
+
+    // Create a file and write some content into it.
+    base::FilePath file_path(temp_dir.GetPath().Append(kFileName1));
+    base::File valid_file(
+        file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+    for (size_t position = 0; position < info->size; ++position) {
+      char c = 'a' + (position % 26);
+      ASSERT_EQ(1, valid_file.WriteAtCurrentPos(&c, 1));
+    }
+    valid_file.Close();
+
+    std::string digest;
+    EXPECT_TRUE(ComputeDigestSHA256(file_path, &digest));
+    EXPECT_STREQ(info->digest, digest.c_str());
+  }
+}
+
+TEST(DiskUtilTests, GetLayeredServiceProviders) {
+  // Make sure that running the OS implementation doesn't crash/dcheck.
+  LSPPathToGUIDs providers;
+  GetLayeredServiceProviders(LayeredServiceProviderWrapper(), &providers);
+  providers.clear();
+
+  // Make sure an empty test provider returns nothing
+  TestLayeredServiceProvider lsp;
+  GetLayeredServiceProviders(lsp, &providers);
+  EXPECT_TRUE(providers.empty());
+
+  // Now try with a couple of providers
+  base::FilePath file_path1 = base::FilePath(kFileName1);
+  base::FilePath file_path2 = base::FilePath(kFileName2);
+  lsp.AddProvider(kGUID1, file_path1);
+  lsp.AddProvider(kGUID2, file_path2);
+  lsp.AddProvider(kGUID3, file_path2);
+
+  GetLayeredServiceProviders(lsp, &providers);
+
+  EXPECT_EQ(2UL, providers.size());
+  EXPECT_NE(providers.end(), providers.find(file_path1));
+  EXPECT_NE(providers.end(), providers.find(file_path2));
+  EXPECT_EQ(1UL, providers.find(file_path1)->second.size());
+  EXPECT_NE(providers.find(file_path1)->second.end(),
+            providers.find(file_path1)->second.find(kGUID1));
+  EXPECT_EQ(2UL, providers.find(file_path2)->second.size());
+  EXPECT_NE(providers.find(file_path2)->second.end(),
+            providers.find(file_path2)->second.find(kGUID2));
+  EXPECT_NE(providers.find(file_path2)->second.end(),
+            providers.find(file_path2)->second.find(kGUID3));
+}
+
+TEST(DiskUtilTests, DeleteFileFromTempProcess) {
+  base::FilePath test_file;
+  base::ScopedTempDir test_dir;
+  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+  base::CreateTemporaryFileInDir(test_dir.GetPath(), &test_file);
+  ASSERT_TRUE(base::PathExists(test_file));
+  base::WriteFile(test_file, "foo", 3);
+  base::win::ScopedHandle process_handle;
+  EXPECT_TRUE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
+  ASSERT_NE(static_cast<HANDLE>(nullptr), process_handle.Get());
+  DWORD wait_result = ::WaitForSingleObject(
+      process_handle.Get(),
+      TestTimeouts::action_max_timeout().InMilliseconds());
+  process_handle.Close();
+  EXPECT_EQ(WAIT_OBJECT_0, wait_result);
+  EXPECT_FALSE(base::PathExists(test_file));
+  EXPECT_FALSE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
+  EXPECT_FALSE(process_handle.IsValid());
+}
+
+TEST(DiskUtilTests, ShortPathContainsCaseInsensitive) {
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath short_name_path;
+  CreateFileAndGetShortName(scoped_temp_dir.GetPath().Append(kLongFileName1),
+                            &short_name_path);
+
+  // Make sure the test strings would fail with the previous API.
+  ASSERT_FALSE(
+      String16ContainsCaseInsensitive(short_name_path.value(), kLongFileName1));
+
+  // Find the long name from the shorten version.
+  EXPECT_TRUE(ShortPathContainsCaseInsensitive(short_name_path.value(),
+                                               kLongFileName1));
+
+  // Make sure the shorten version can also be found.
+  EXPECT_TRUE(ShortPathContainsCaseInsensitive(short_name_path.value(),
+                                               short_name_path.value()));
+
+  // Validate the not found case.
+  EXPECT_FALSE(ShortPathContainsCaseInsensitive(short_name_path.value(),
+                                                kLongFileName2));
+
+  // Validate a non shorten case.
+  EXPECT_TRUE(
+      ShortPathContainsCaseInsensitive(kLongFileName2, kLongFileName2Subset));
+}
+
+TEST(DiskUtilTests, PathEqual) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath long_path1(temp_dir.GetPath().Append(kLongFileName1));
+  base::FilePath long_path2(temp_dir.GetPath().Append(kLongFileName2));
+  base::FilePath long_path1_upper(base::ToUpperASCII(long_path1.value()));
+
+  base::FilePath short_path1;
+  CreateFileAndGetShortName(long_path1, &short_path1);
+
+  // Same paths are equal.
+  EXPECT_TRUE(PathEqual(long_path1, long_path1));
+  EXPECT_TRUE(PathEqual(long_path2, long_path2));
+  // Same paths with different case are equal.
+  EXPECT_TRUE(PathEqual(long_path1, long_path1_upper));
+  // Different path are not equal.
+  EXPECT_FALSE(PathEqual(long_path1, long_path2));
+
+  // Short and long path to the same file are equal.
+  EXPECT_TRUE(PathEqual(short_path1, long_path1));
+  // Short and long path to different files are not equal.
+  EXPECT_FALSE(PathEqual(short_path1, long_path2));
+}
+
+TEST(DiskUtilTests, GetAppDataProductDirectory) {
+  base::ScopedPathOverride appdata_override(
+      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
+  base::FilePath appdata_dir;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_dir));
+
+  base::FilePath product_folder;
+  EXPECT_TRUE(GetAppDataProductDirectory(&product_folder));
+  EXPECT_TRUE(base::DirectoryExists(product_folder));
+  EXPECT_TRUE(PathEqual(appdata_dir, product_folder.DirName().DirName()));
+}
+
+// TODO(crbug.com/867550): This does not work in component builds because
+// test_process.exe depends on DLL's that don't get copied. Fix and re-enable.
+TEST(DiskUtilTests, DISABLED_ZoneIdentifier) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath path(temp_dir.GetPath().Append(kTestProcessExecutableName));
+
+  if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
+    LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
+    return;
+  }
+
+  // Copy the test_process executable in a temporary folder.
+  base::FilePath executable_path;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
+  base::FilePath source_path =
+      executable_path.Append(kTestProcessExecutableName);
+  ASSERT_TRUE(base::CopyFile(source_path, path));
+
+  // Overwrite the ZoneIdentifier.
+  EXPECT_FALSE(HasZoneIdentifier(path));
+  EXPECT_TRUE(OverwriteZoneIdentifier(path));
+  EXPECT_TRUE(HasZoneIdentifier(path));
+
+  // Validate the content of the Zone.Identifier stream.
+  base::FilePath stream_path(path.value() + L":Zone.Identifier");
+  std::string content;
+  ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
+  EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
+}
+
+// TODO(crbug.com/867550): This does not work in component builds because
+// test_process.exe depends on DLL's that don't get copied. Fix and re-enable.
+TEST(DiskUtilTests, DISABLED_ZoneIdentifierWhenProcessIsRunning) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
+    LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
+    return;
+  }
+
+  // Copy the test_process executable in a temporary folder.
+  base::FilePath executable_path;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
+  base::FilePath source_exe_path(
+      executable_path.Append(kTestProcessExecutableName));
+  base::FilePath target_exe_path(
+      temp_dir.GetPath().Append(kTestProcessExecutableName));
+  ASSERT_TRUE(base::CopyFile(source_exe_path, target_exe_path));
+
+  // Launch the test_process and wait it's completion. The process must set its
+  // zone identifier.
+  EXPECT_FALSE(HasZoneIdentifier(target_exe_path));
+  ASSERT_FALSE(IsProcessRunning(kTestProcessExecutableName));
+  ASSERT_TRUE(LaunchTestProcess(target_exe_path.value().c_str(),
+                                kTestForceOverwriteZoneIdentifier, false));
+  EXPECT_TRUE(WaitForProcessesStopped(kTestProcessExecutableName));
+  EXPECT_TRUE(HasZoneIdentifier(target_exe_path));
+
+  // Validate the content of the Zone.Identifier stream.
+  base::FilePath stream_path(target_exe_path.value() + L":Zone.Identifier");
+  std::string content;
+  ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
+  EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
+}
+
+TEST(DiskUtilTests,
+     ExtractExecutablePathFromRegistryContentWithSysnativeReplacement) {
+  base::FilePath system_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_SYSTEM),
+                                     &system_folder));
+
+  base::FilePath native_folder(system_folder.DirName().Append(L"sysnative"));
+  // Only run this test on 64-bits Windows with 32-bits process.
+  if (base::PathExists(native_folder)) {
+    base::ScopedTempDir temp_dir;
+    ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(native_folder));
+
+    base::FilePath program_path, spaced_program_path;
+    CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
+                               &spaced_program_path);
+    const base::FilePath program_paths[] = {program_path, spaced_program_path};
+    for (const auto& program_path : program_paths) {
+      // convert C:\\Windows\sysnative\scoped_folder\folder1234\file1 into
+      // C:\\Windows\system32\scoped_folder\folder1234\file1
+      base::FilePath program_path_system =
+          system_folder.Append(program_path.DirName().DirName().BaseName())
+              .Append(program_path.DirName().BaseName())
+              .Append(program_path.BaseName());
+      EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
+          program_path_system.value(), program_path));
+    }
+  }
+}
+
+TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContentWithEnvVariable) {
+  // This test expects files to be placed in %TEMP% and not anywhere else
+  // ScopedTempDir might decide to put them.
+  base::string16 temp_str;
+  ASSERT_NE(0U, ::GetEnvironmentVariableW(
+                    L"TEMP", ::base::WriteInto(&temp_str, MAX_PATH), MAX_PATH))
+      << logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
+  base::FilePath temp_path(temp_str);
+  ASSERT_TRUE(base::PathExists(temp_path));
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(temp_path));
+
+  base::FilePath program_path, spaced_program_path;
+  CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
+                             &spaced_program_path);
+  const base::FilePath program_paths[] = {program_path, spaced_program_path};
+
+  for (const auto& program_path : program_paths) {
+    // Convert
+    // "C:\Users\$USER\AppData\Local\Temp\scoped_dir1234\folder6788\A111.tmp"
+    // into "scoped_dir1234\folder6789\A111.tmp"
+    base::FilePath relative_program_path =
+        program_path.DirName()
+            .DirName()
+            .BaseName()
+            .Append(program_path.DirName().BaseName())
+            .Append(program_path.BaseName());
+    const auto program_path_with_var =
+        base::StrCat({L"%TEMP%\\", relative_program_path.value()});
+
+    EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
+        program_path_with_var, program_path));
+  }
+}
+
+TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContent) {
+  // Create the executable to be recognized.
+  base::ScopedTempDir temp_dir;
+
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath program_path, spaced_program_path;
+  CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
+                             &spaced_program_path);
+  const base::FilePath program_paths[] = {program_path, spaced_program_path};
+
+  for (const auto& program_path : program_paths) {
+    EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
+        program_path.value(), program_path));
+  }
+}
+
+TEST(DiskUtilTests, FilePathLess) {
+  base::FilePath path_a(L"c:\\a");
+  base::FilePath path_upper_a(L"c:\\A");
+  base::FilePath path_b(L"c:\\b");
+  FilePathLess file_path_less;
+  EXPECT_TRUE(file_path_less(path_a, path_b));
+  EXPECT_TRUE(file_path_less(path_upper_a, path_b));
+  EXPECT_FALSE(file_path_less(path_b, path_a));
+  EXPECT_FALSE(file_path_less(path_a, path_upper_a));
+  EXPECT_FALSE(file_path_less(path_upper_a, path_a));
+
+  std::map<base::FilePath, int, FilePathLess> collection;
+  collection[path_a] = 0;
+  EXPECT_NE(collection.find(path_a), collection.end());
+  EXPECT_NE(collection.find(path_upper_a), collection.end());
+  EXPECT_EQ(collection.find(path_b), collection.end());
+}
+
+TEST(DiskUtilTests, RetrieveDetailedFileInformation) {
+  base::ScopedPathOverride appdata_override(
+      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
+  base::FilePath appdata_folder;
+
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_folder));
+
+  base::FilePath temp_file(appdata_folder.Append(L"DUMMY.inactive"));
+  CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
+
+  bool whitelisted = false;
+  internal::FileInformation file_information;
+  RetrieveDetailedFileInformation(temp_file, &file_information, &whitelisted);
+
+  EXPECT_FALSE(whitelisted);
+
+  base::string16 sanitized_path = SanitizePath(temp_file);
+
+  EXPECT_EQ(sanitized_path, file_information.path);
+  EXPECT_FALSE(file_information.creation_date.empty());
+  EXPECT_FALSE(file_information.last_modified_date.empty());
+  EXPECT_FALSE(file_information.active_file);
+  EXPECT_EQ(kFileContentDigests[4], file_information.sha256);
+  EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
+  // The next fields are parsed from PE headers so they won't exist.
+  EXPECT_TRUE(file_information.company_name.empty());
+  EXPECT_TRUE(file_information.company_short_name.empty());
+  EXPECT_TRUE(file_information.product_name.empty());
+  EXPECT_TRUE(file_information.product_short_name.empty());
+  EXPECT_TRUE(file_information.internal_name.empty());
+  EXPECT_TRUE(file_information.original_filename.empty());
+  EXPECT_TRUE(file_information.file_description.empty());
+  EXPECT_TRUE(file_information.file_version.empty());
+}
+
+TEST(DiskUtilTests, RetrieveDetailedFileInformationNoFile) {
+  base::FilePath appdata_folder;
+
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_folder));
+
+  base::FilePath non_existent_file(
+      appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
+
+  bool whitelisted = false;
+  internal::FileInformation file_information;
+  RetrieveDetailedFileInformation(non_existent_file, &file_information,
+                                  &whitelisted);
+
+  EXPECT_FALSE(whitelisted);
+  EXPECT_TRUE(file_information.path.empty());
+  EXPECT_TRUE(file_information.creation_date.empty());
+  EXPECT_TRUE(file_information.last_modified_date.empty());
+  EXPECT_FALSE(file_information.active_file);
+  EXPECT_TRUE(file_information.sha256.empty());
+  EXPECT_EQ(0, file_information.size);
+  EXPECT_TRUE(file_information.company_name.empty());
+  EXPECT_TRUE(file_information.company_short_name.empty());
+  EXPECT_TRUE(file_information.product_name.empty());
+  EXPECT_TRUE(file_information.product_short_name.empty());
+  EXPECT_TRUE(file_information.internal_name.empty());
+  EXPECT_TRUE(file_information.original_filename.empty());
+  EXPECT_TRUE(file_information.file_description.empty());
+  EXPECT_TRUE(file_information.file_version.empty());
+}
+
+TEST(DiskUtilTests, RetrieveDetailedFileInformationWhitelisted) {
+  bool whitelisted = false;
+  internal::FileInformation file_information;
+
+  RetrieveDetailedFileInformation(GetSampleDLLPath(), &file_information,
+                                  &whitelisted,
+                                  base::BindOnce(&WhitelistSampleDLL));
+
+  EXPECT_TRUE(whitelisted);
+  EXPECT_TRUE(file_information.path.empty());
+  EXPECT_TRUE(file_information.creation_date.empty());
+  EXPECT_TRUE(file_information.last_modified_date.empty());
+  EXPECT_FALSE(file_information.active_file);
+  EXPECT_TRUE(file_information.sha256.empty());
+  EXPECT_EQ(0, file_information.size);
+  EXPECT_TRUE(file_information.company_name.empty());
+  EXPECT_TRUE(file_information.company_short_name.empty());
+  EXPECT_TRUE(file_information.product_name.empty());
+  EXPECT_TRUE(file_information.product_short_name.empty());
+  EXPECT_TRUE(file_information.internal_name.empty());
+  EXPECT_TRUE(file_information.original_filename.empty());
+  EXPECT_TRUE(file_information.file_description.empty());
+  EXPECT_TRUE(file_information.file_version.empty());
+}
+
+TEST(DiskUtilTests, RetrieveBasicFileInformation) {
+  base::ScopedPathOverride appdata_override(
+      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
+  base::FilePath appdata_folder;
+
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_folder));
+
+  base::FilePath temp_file(appdata_folder.Append(L"DUMMY.exe"));
+  CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
+
+  internal::FileInformation file_information;
+  RetrieveBasicFileInformation(temp_file, &file_information);
+
+  // The expected file path value should be sanitized.
+  EXPECT_EQ(SanitizePath(temp_file), file_information.path);
+  EXPECT_FALSE(file_information.creation_date.empty());
+  EXPECT_FALSE(file_information.last_modified_date.empty());
+  EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
+  EXPECT_TRUE(file_information.active_file);
+  // The next fields are not included in basic file information.
+  EXPECT_TRUE(file_information.sha256.empty());
+  EXPECT_TRUE(file_information.company_name.empty());
+  EXPECT_TRUE(file_information.company_short_name.empty());
+  EXPECT_TRUE(file_information.product_name.empty());
+  EXPECT_TRUE(file_information.product_short_name.empty());
+  EXPECT_TRUE(file_information.internal_name.empty());
+  EXPECT_TRUE(file_information.original_filename.empty());
+  EXPECT_TRUE(file_information.file_description.empty());
+  EXPECT_TRUE(file_information.file_version.empty());
+}
+
+TEST(DiskUtilTests, RetrieveBasicFileInformationNoFile) {
+  base::FilePath appdata_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_folder));
+
+  base::FilePath non_existent_file(
+      appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
+
+  internal::FileInformation file_information;
+  RetrieveBasicFileInformation(non_existent_file, &file_information);
+
+  EXPECT_TRUE(file_information.path.empty());
+  EXPECT_TRUE(file_information.creation_date.empty());
+  EXPECT_TRUE(file_information.last_modified_date.empty());
+  EXPECT_FALSE(file_information.active_file);
+  EXPECT_TRUE(file_information.sha256.empty());
+  EXPECT_EQ(0, file_information.size);
+  EXPECT_TRUE(file_information.company_name.empty());
+  EXPECT_TRUE(file_information.company_short_name.empty());
+  EXPECT_TRUE(file_information.product_name.empty());
+  EXPECT_TRUE(file_information.product_short_name.empty());
+  EXPECT_TRUE(file_information.internal_name.empty());
+  EXPECT_TRUE(file_information.original_filename.empty());
+  EXPECT_TRUE(file_information.file_description.empty());
+  EXPECT_TRUE(file_information.file_version.empty());
+}
+
+TEST(DiskUtilTests, FileInformationToString) {
+  base::string16 display_str = FileInformationToString(kFileInformation1);
+  EXPECT_EQ(kFileInformation1ExpectedString, display_str);
+}
+
+TEST(DiskUtilTests, FileInformationToStringEmpty) {
+  internal::FileInformation file_information;
+  EXPECT_TRUE(FileInformationToString(file_information).empty());
+}
+
+TEST(DiskUtilTests, TryToExpandPath_NonSystemNativePath) {
+  base::ScopedPathOverride appdata_override(
+      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
+  base::FilePath appdata_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
+                                     &appdata_folder));
+
+  base::FilePath non_existing_file(
+      appdata_folder.DirName().Append(L"non-existing-file.tmp"));
+  base::FilePath unused_expanded_path;
+  ASSERT_FALSE(TryToExpandPath(non_existing_file, &unused_expanded_path));
+
+  base::FilePath existing_file(appdata_folder.Append(L"existing-file.tmp"));
+  CreateFileWithContent(existing_file, kFileContent1, sizeof(kFileContent1));
+  base::FilePath expanded_path;
+  ASSERT_TRUE(TryToExpandPath(existing_file, &expanded_path));
+  ASSERT_EQ(existing_file.value(), expanded_path.value());
+
+  // TODO: Figure out how to test paths in C:\Windows\System32.
+}
+
+TEST(DiskUtilTests, TruncateLogFileToTail_FindsNewline) {
+  const char kFileContents[] = "File with utf8 \n\xe2\x82\xac \ntail";
+  const int kFileSize = strlen(kFileContents);
+  const char kTailContents[] = "\ntail";
+  const int kTailSize = strlen(kTailContents);
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
+  ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
+
+  // The tail threshold lands in the middle of a multi-byte character.
+  TruncateLogFileToTail(file_path, kTailSize + 3);
+
+  int64_t file_size;
+  ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
+  EXPECT_EQ(kTailSize, file_size);
+  std::string tail;
+  ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
+  EXPECT_EQ(kTailContents, tail);
+}
+
+TEST(DiskUtilTests, TruncateLogFileToTail_FileSmallerThanLimit) {
+  const char kFileContents[] = "I am file";
+  const int kFileSize = strlen(kFileContents);
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
+  ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
+
+  TruncateLogFileToTail(file_path, kFileSize * 2);
+
+  int64_t file_size;
+  ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
+  EXPECT_EQ(kFileSize, file_size);
+  std::string tail;
+  ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
+  EXPECT_EQ(kFileContents, tail);
+}
+
+TEST(DiskUtilTests, TruncateLogFileToTail_NotExisting) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
+
+  TruncateLogFileToTail(file_path, 42);
+
+  EXPECT_FALSE(base::PathExists(file_path));
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc b/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc
new file mode 100644
index 0000000..8b46d8c2
--- /dev/null
+++ b/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
+
+#include <shlobj.h>
+
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+base::string16 FirstComponent(const base::string16& original) {
+  return original.substr(0, original.find(L"\\"));
+}
+
+TEST(FilePathSanitizationTests, NormalizePath) {
+  base::FilePath expected_path =
+      base::FilePath(L"c:\\program files\\desktop.ini");
+  EXPECT_EQ(NormalizePath(base::FilePath(L"C:\\PROGRA~1\\DESKTOP.INI")),
+            expected_path);
+  EXPECT_EQ(NormalizePath(base::FilePath(L"c:\\pRoGrAm FiLeS\\desktop.INI")),
+            expected_path);
+  base::FilePath empty_path;
+  EXPECT_EQ(NormalizePath(empty_path), empty_path);
+}
+
+TEST(FilePathSanitizationTests, NormalizePathUnicode) {
+  EXPECT_EQ(
+      NormalizePath(
+          base::FilePath(L"C:\\\u03b1\u03c1\u03c7\u03b5\u03b9\u03b1 "
+                         L"\u03c0\u03c1\u03bf\u03b3\u03c1"
+                         L"\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2\\u03b5"
+                         L"\u03c0\u03b9\u03c6"
+                         L"\u03ac\u03bd\u03b5\u03b9\u03b1 "
+                         L"\u03b5\u03c1\u03b3\u03b1\u03c3\u03af"
+                         L"\u03b1\u03c2.iNi"))
+          .value(),
+      L"c:\\\u03b1\u03c1\u03c7\u03b5\u03b9\u03b1 \u03c0\u03c1\u03bf\u03b3\u03c1"
+      L"\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2\\u03b5\u03c0\u03b9\u03c6"
+      L"\u03ac\u03bd\u03b5\u03b9\u03b1 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af"
+      L"\u03b1\u03c2.ini");
+}
+TEST(FilePathSanitizationTests, SanitizePath) {
+  base::FilePath programfiles_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_PROGRAM_FILES),
+                                     &programfiles_folder));
+
+  base::FilePath absolute(L"C:\\Dummy\\Dummy.exe");
+  base::string16 result = SanitizePath(absolute);
+  EXPECT_EQ(NormalizePath(absolute).value(), result);
+
+  base::FilePath relative(programfiles_folder.Append(L"Dummy\\Dummy.exe"));
+  base::string16 sanitized_relative = SanitizePath(relative);
+  EXPECT_NE(sanitized_relative, relative.value());
+  EXPECT_EQ(L"CSIDL_PROGRAM_FILES\\dummy\\dummy.exe", sanitized_relative);
+
+  base::FilePath empty_path;
+  EXPECT_EQ(L"", SanitizePath(empty_path));
+}
+
+TEST(FilePathSanitizationTests, SanitizePathConsistency) {
+  // Loop over all the rewrite rules used by sanitize path to make sure all the
+  // rules work correctly. In particular this test verifies each rule is not
+  // masked by another.
+  base::FilePath arbitrary_path = NormalizePath(base::FilePath(L"Desktop.ini"));
+  for (auto* rule = sanitization_internal::rewrite_rules; rule->path != nullptr;
+       ++rule) {
+    base::FilePath expanded_path;
+    base::PathService::Get(rule->id, &expanded_path);
+    expanded_path = expanded_path.Append(arbitrary_path);
+    const auto sanitized_path = chrome_cleaner::SanitizePath(expanded_path);
+
+    // The FirstComponent here is the label string used to sanitize the path. It
+    // is extracted to verify the correct label string is being used.
+    //
+    // For example:
+    // C:\Program Files (x86)\Common Files\Desktop.ini
+    // maps to
+    // CSIDL_PROGRAM_FILES_COMMON (CSIDL_PROGRAM_FILES_COMMON\Desktop.ini)
+    // and shouldn't map to
+    // CSIDL_PROGRAM_FILES        (CSIDL_PROGRAM_FILES\Common Files\Desktop.ini)
+    // or it will clash with
+    // C:\Program Files (x86)\Desktop.ini
+    // which maps to
+    // CSIDL_PROGRAM_FILES        (CSIDL_PROGRAM_FILES\desktop.ini)
+    const auto first_dir = FirstComponent(sanitized_path);
+    if (first_dir != rule->path) {
+      ADD_FAILURE() << base::WideToUTF8(expanded_path.value())
+                    << " is being Sanitized to "
+                    << base::WideToUTF8(sanitized_path) << " instead of using "
+                    << rule->path;
+    }
+  }
+}
+
+TEST(FilePathSanitizationTests, SanitizeCommandLine) {
+  base::CommandLine switches =
+      base::CommandLine::FromString(L"dummy.exe --flag --arg=value");
+
+  base::CommandLine already_sanitized(switches);
+  already_sanitized.SetProgram(base::FilePath(L"c:\\dummy\\dummy.exe"));
+  base::string16 result = SanitizeCommandLine(already_sanitized);
+  EXPECT_EQ(already_sanitized.GetCommandLineString(), result);
+
+  base::FilePath programfiles_folder;
+  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_PROGRAM_FILES),
+                                     &programfiles_folder));
+  base::FilePath exe_in_programfiles =
+      programfiles_folder.Append(L"dummy\\dummy.exe");
+
+  base::CommandLine to_sanitize(switches);
+  to_sanitize.SetProgram(exe_in_programfiles);
+  base::string16 sanitized_cmd = SanitizeCommandLine(to_sanitize);
+  EXPECT_NE(to_sanitize.GetCommandLineString(), sanitized_cmd);
+  EXPECT_NE(sanitized_cmd.find(SanitizePath(exe_in_programfiles)),
+            base::string16::npos);
+}
+
+TEST(FilePathSanitizationTests, ExpandSpecialFolderPath) {
+  base::FilePath arbitrary_path(L"Desktop.ini");
+  for (auto* rule = sanitization_internal::rewrite_rules; rule->path != nullptr;
+       ++rule) {
+    // Skip non-CSIDL entries.
+    if (rule->id < sanitization_internal::PATH_CSIDL_START ||
+        rule->id >= sanitization_internal::PATH_CSIDL_END) {
+      continue;
+    }
+
+    // Fetch and validate expected path.
+    base::FilePath expected_path;
+    ASSERT_TRUE(base::PathService::Get(rule->id, &expected_path));
+    ASSERT_FALSE(expected_path.empty());
+    expected_path = expected_path.Append(arbitrary_path);
+
+    int csidl = rule->id - sanitization_internal::PATH_CSIDL_START;
+    base::FilePath expanded_path =
+        ExpandSpecialFolderPath(csidl, arbitrary_path);
+    EXPECT_EQ(expected_path, expanded_path)
+        << "Failed special folder path expansion. Got: \""
+        << base::WideToUTF8(expanded_path.value())
+        << "\", but expected: " << base::WideToUTF8(expected_path.value());
+  }
+}
+
+}  // namespace
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_path_set_unittest.cc b/chrome/chrome_cleaner/os/file_path_set_unittest.cc
new file mode 100644
index 0000000..ddb0ab8
--- /dev/null
+++ b/chrome/chrome_cleaner/os/file_path_set_unittest.cc
@@ -0,0 +1,168 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/file_path_set.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_util.h"
+#include "chrome/chrome_cleaner/test/test_file_util.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+const wchar_t kFileNameFull[] = L"C:\\Filename";
+const wchar_t kLongFileName[] = L"Long File Name.bla";
+const wchar_t kLongFileNameFull[] = L"C:\\Long File Name.bla";
+}  // namespace
+
+TEST(FilePathSetTests, Empty) {
+  FilePathSet file_paths;
+  // Start empty.
+  EXPECT_TRUE(file_paths.empty());
+  // Clear should be callable on empty sets.
+  file_paths.clear();
+}
+
+TEST(FilePathSetTests, InsertedOnce) {
+  FilePathSet file_paths;
+  // Same path should be inserted only once.
+  base::FilePath file_path1(kFileNameFull);
+  EXPECT_TRUE(file_paths.Insert(file_path1));
+  EXPECT_FALSE(file_paths.Insert(file_path1));
+  EXPECT_EQ(1UL, file_paths.size());
+  // But still should be found.
+  EXPECT_TRUE(file_paths.Contains(file_path1));
+}
+
+TEST(FilePathSetTests, EqualOperator) {
+  FilePathSet file_paths1;
+  base::FilePath file_path(kFileNameFull);
+  EXPECT_TRUE(file_paths1.Insert(file_path));
+  EXPECT_EQ(file_paths1, file_paths1);
+
+  FilePathSet file_paths2;
+  EXPECT_TRUE(file_paths2.Insert(file_path));
+  EXPECT_EQ(file_paths1, file_paths2);
+
+  base::FilePath long_file_path(kLongFileNameFull);
+  EXPECT_TRUE(file_paths1.Insert(long_file_path));
+  EXPECT_TRUE(file_paths2.Insert(long_file_path));
+  EXPECT_EQ(file_paths1, file_paths2);
+
+  base::FilePath other_path(L"C:\\other_path.txt");
+  EXPECT_TRUE(file_paths2.Insert(other_path));
+  // To avoid implementing operator!=();
+  EXPECT_FALSE(file_paths1 == file_paths2);
+}
+
+TEST(FilePathSetTests, LongName) {
+  FilePathSet file_paths;
+  // Long paths should also be found, even by their short version.
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath short_name_path;
+  base::FilePath long_name_path(
+      scoped_temp_dir.GetPath().Append(kLongFileName));
+  CreateFileAndGetShortName(long_name_path, &short_name_path);
+  EXPECT_TRUE(file_paths.Insert(long_name_path));
+  EXPECT_FALSE(file_paths.Insert(long_name_path));
+  EXPECT_FALSE(file_paths.Insert(short_name_path));
+  base::FilePath long_name_path_upper(
+      base::ToUpperASCII(long_name_path.value()));
+  EXPECT_FALSE(file_paths.Insert(long_name_path_upper));
+
+  // And they should be found-able in all its different forms.
+  EXPECT_TRUE(file_paths.Contains(long_name_path));
+  EXPECT_TRUE(file_paths.Contains(short_name_path));
+  EXPECT_TRUE(file_paths.Contains(long_name_path_upper));
+}
+
+TEST(FilePathSetTests, ShortName) {
+  FilePathSet file_paths;
+  // Short paths should also be found, even by their long version.
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath short_name_path;
+  base::FilePath long_name_path(
+      scoped_temp_dir.GetPath().Append(kLongFileName));
+  CreateFileAndGetShortName(long_name_path, &short_name_path);
+  EXPECT_TRUE(file_paths.Insert(short_name_path));
+  EXPECT_FALSE(file_paths.Insert(short_name_path));
+  EXPECT_FALSE(file_paths.Insert(long_name_path));
+  base::FilePath long_name_path_upper(
+      base::ToUpperASCII(long_name_path.value()));
+  EXPECT_FALSE(file_paths.Insert(long_name_path_upper));
+
+  // And they should be found-able in all its different forms.
+  EXPECT_TRUE(file_paths.Contains(long_name_path));
+  EXPECT_TRUE(file_paths.Contains(short_name_path));
+  EXPECT_TRUE(file_paths.Contains(long_name_path_upper));
+}
+
+TEST(FilePathSetTests, ProperOrder) {
+  // Ensure that all the items in a folder are listed before the folder.
+  const base::FilePath folder(L"C:\\folder");
+  base::FilePath file = folder.Append(L"file.exe");
+  base::FilePath sub_folder = folder.Append(L"sub_folder");
+  base::FilePath sub_file = sub_folder.Append(L"sub_file.txt");
+
+  FilePathSet file_paths;
+  EXPECT_TRUE(file_paths.Insert(folder));
+  EXPECT_TRUE(file_paths.Insert(file));
+  EXPECT_TRUE(file_paths.Insert(sub_folder));
+  EXPECT_TRUE(file_paths.Insert(sub_file));
+
+  const auto sorted_files = file_paths.ReverseSorted();
+  ASSERT_EQ(4UL, sorted_files.size());
+  EXPECT_EQ(sub_file, sorted_files[0]);
+  EXPECT_EQ(sub_folder, sorted_files[1]);
+  EXPECT_EQ(file, sorted_files[2]);
+  EXPECT_EQ(folder, sorted_files[3]);
+}
+
+TEST(FilePathMap, Find) {
+  // Long paths should also be found, even by their short version.
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath short_name_path;
+  base::FilePath long_name_path(
+      scoped_temp_dir.GetPath().Append(kLongFileName));
+  CreateFileAndGetShortName(long_name_path, &short_name_path);
+
+  FilePathMap<int> map;
+  EXPECT_TRUE(map.Insert(short_name_path, 42));
+
+  const int* found_value = nullptr;
+  ASSERT_NE(nullptr, found_value = map.Find(short_name_path));
+  EXPECT_EQ(42, *found_value);
+
+  ASSERT_NE(nullptr, found_value = map.Find(long_name_path));
+  EXPECT_EQ(42, *found_value);
+
+  EXPECT_EQ(nullptr, map.Find(base::FilePath(kFileNameFull)));
+}
+
+TEST(FilePathMap, DoNotInsertDuplicates) {
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath short_name_path;
+  base::FilePath long_name_path(
+      scoped_temp_dir.GetPath().Append(kLongFileName));
+  CreateFileAndGetShortName(long_name_path, &short_name_path);
+
+  FilePathMap<int> map;
+  EXPECT_TRUE(map.Insert(long_name_path, 42));
+  EXPECT_FALSE(map.Insert(long_name_path, 43));
+  EXPECT_FALSE(map.Insert(short_name_path, 44));
+  EXPECT_EQ(1u, map.map().size());
+
+  const int* found_value = nullptr;
+  EXPECT_NE(nullptr, found_value = map.Find(short_name_path));
+  EXPECT_EQ(42, *found_value);
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc b/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc
new file mode 100644
index 0000000..54642931
--- /dev/null
+++ b/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc
@@ -0,0 +1,159 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/file_removal_status_updater.h"
+
+#include "base/base_paths.h"
+#include "base/path_service.h"
+#include "base/strings/string_util.h"
+#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+constexpr wchar_t kFile1[] = L"file_one";
+constexpr wchar_t kFile2[] = L"file_two";
+
+class FileRemovalStatusUpdaterTest : public ::testing::Test {
+ protected:
+  FileRemovalStatusUpdaterTest() {
+    // Start each test with an empty map.
+    FileRemovalStatusUpdater::GetInstance()->Clear();
+  }
+
+  // Convenience accessors
+  FileRemovalStatusUpdater* instance_ = FileRemovalStatusUpdater::GetInstance();
+  const base::FilePath file_1_ = base::FilePath(kFile1);
+  const base::FilePath file_2_ = base::FilePath(kFile2);
+};
+
+}  // namespace
+
+TEST_F(FileRemovalStatusUpdaterTest, Clear) {
+  // Map should start empty.
+  EXPECT_TRUE(instance_->GetAllRemovalStatuses().empty());
+  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_1_));
+  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
+
+  instance_->UpdateRemovalStatus(file_1_, REMOVAL_STATUS_MATCHED_ONLY);
+
+  // Only file_1_ should be in the map.
+  EXPECT_EQ(1U, instance_->GetAllRemovalStatuses().size());
+  EXPECT_EQ(REMOVAL_STATUS_MATCHED_ONLY, instance_->GetRemovalStatus(file_1_));
+  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
+
+  instance_->Clear();
+
+  // Map should be empty again.
+  EXPECT_TRUE(instance_->GetAllRemovalStatuses().empty());
+  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_1_));
+  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
+}
+
+TEST_F(FileRemovalStatusUpdaterTest, UpdateRemovalStatus) {
+  // This function uses GetRemovalStatusOfSanitizedPath to cut down on the
+  // number of times it calls SanitizePath on the same paths, which is slow.
+  const base::string16 file_1_sanitized = SanitizePath(file_1_);
+  const base::string16 file_2_sanitized = SanitizePath(file_2_);
+
+  // Creates a vector of all RemovalStatus enum values to improve readability
+  // of loops in this test and ensure that all RemovalStatus enumerators are
+  // checked.
+  std::vector<RemovalStatus> all_removal_status;
+  for (int i = RemovalStatus_MIN; i <= RemovalStatus_MAX; ++i) {
+    // Status cannot be set to REMOVAL_STATUS_UNSPECIFIED - this is guarded by
+    // an assert.
+    RemovalStatus status = static_cast<RemovalStatus>(i);
+    if (status != REMOVAL_STATUS_UNSPECIFIED)
+      all_removal_status.push_back(status);
+  }
+
+  for (RemovalStatus removal_status : all_removal_status) {
+    // Repeatedly update the removal status of file_2_. file_1_'s status should
+    // not be touched.
+    for (RemovalStatus new_removal_status : all_removal_status) {
+      SCOPED_TRACE(::testing::Message()
+                   << "removal_status " << removal_status
+                   << ", new_removal_status " << new_removal_status);
+
+      // Initially, files should have removal status "unspecified".
+      ASSERT_TRUE(instance_->GetAllRemovalStatuses().empty());
+      ASSERT_EQ(REMOVAL_STATUS_UNSPECIFIED,
+                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
+      ASSERT_EQ(REMOVAL_STATUS_UNSPECIFIED,
+                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
+
+      // Any removal status can override "unspecified".
+      instance_->UpdateRemovalStatus(file_1_, removal_status);
+      instance_->UpdateRemovalStatus(file_2_, removal_status);
+      EXPECT_EQ(removal_status,
+                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
+      EXPECT_EQ(removal_status,
+                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
+
+      // Tests if attempts to override removal status obey the rules specified
+      // by GetRemovalStatusOfSanitizedPathOverridePermissionMap().
+      instance_->UpdateRemovalStatus(file_2_, new_removal_status);
+      const internal::RemovalStatusOverridePermissionMap& decisions_map =
+          internal::GetRemovalStatusOverridePermissionMap();
+      const bool can_override = decisions_map.find(removal_status)
+                                    ->second.find(new_removal_status)
+                                    ->second == internal::kOkToOverride;
+      EXPECT_EQ(can_override ? new_removal_status : removal_status,
+                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
+
+      // Updating file_2_ should not have touched file_1_.
+      EXPECT_EQ(removal_status,
+                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
+
+      // GetAllRemovalStatuses should agree with GetRemovalStatusOfSanitizedPath
+      // for all files.
+      FileRemovalStatusUpdater::SanitizedPathToRemovalStatusMap all_statuses =
+          instance_->GetAllRemovalStatuses();
+      EXPECT_EQ(2U, all_statuses.size());
+      for (const auto& path_and_status : all_statuses) {
+        base::string16 sanitized_path = path_and_status.first;
+        FileRemovalStatusUpdater::FileRemovalStatus status =
+            path_and_status.second;
+        EXPECT_EQ(instance_->GetRemovalStatusOfSanitizedPath(sanitized_path),
+                  status.removal_status);
+      }
+
+      // Empty the map for the next loop.
+      instance_->Clear();
+    }
+  }
+}
+
+TEST_F(FileRemovalStatusUpdaterTest, PathSanitization) {
+  base::FilePath home_dir;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_HOME, &home_dir));
+  base::FilePath path = home_dir.Append(L"UPPER_CASE_FILENAME");
+
+  instance_->UpdateRemovalStatus(path, REMOVAL_STATUS_REMOVED);
+
+  // Path should be accessible with any capitalization, sanitized or
+  // unsanitized.
+  base::string16 lowercase_path = base::ToLowerASCII(path.value());
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED, instance_->GetRemovalStatus(path));
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
+            instance_->GetRemovalStatus(base::FilePath(lowercase_path)));
+
+  base::string16 sanitized_path = SanitizePath(path);
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
+            instance_->GetRemovalStatusOfSanitizedPath(sanitized_path));
+
+  FileRemovalStatusUpdater::SanitizedPathToRemovalStatusMap all_statuses =
+      instance_->GetAllRemovalStatuses();
+  EXPECT_EQ(1U, all_statuses.size());
+  EXPECT_EQ(sanitized_path, all_statuses.begin()->first);
+  EXPECT_EQ(path, all_statuses.begin()->second.path);
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
+            all_statuses.begin()->second.removal_status);
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_remover_unittest.cc b/chrome/chrome_cleaner/os/file_remover_unittest.cc
new file mode 100644
index 0000000..dad51e1b
--- /dev/null
+++ b/chrome/chrome_cleaner/os/file_remover_unittest.cc
@@ -0,0 +1,405 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/os/file_remover.h"
+
+#include <stdint.h>
+#include <utility>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/test/scoped_path_override.h"
+#include "chrome/chrome_cleaner/logging/proto/removal_status.pb.h"
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "chrome/chrome_cleaner/os/file_removal_status_updater.h"
+#include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
+#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
+#include "chrome/chrome_cleaner/os/system_util.h"
+#include "chrome/chrome_cleaner/os/whitelisted_directory.h"
+#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
+#include "chrome/chrome_cleaner/test/resources/grit/test_resources.h"
+#include "chrome/chrome_cleaner/test/test_file_util.h"
+#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+using testing::_;
+using testing::Eq;
+using testing::Return;
+using ValidationStatus = FileRemoverAPI::DeletionValidationStatus;
+
+const wchar_t kRemoveFile1[] = L"remove_one.exe";
+const wchar_t kRemoveFile2[] = L"remove_two.exe";
+const wchar_t kRemoveFolder[] = L"remove";
+
+class FileRemoverTest : public ::testing::Test {
+ protected:
+  FileRemoverTest()
+      : default_file_remover_(
+            nullptr,
+            LayeredServiceProviderWrapper(),
+            /*deletion_allowed_paths=*/{},
+            base::BindRepeating(&FileRemoverTest::RebootRequired,
+                                base::Unretained(this))) {
+    FileRemovalStatusUpdater::GetInstance()->Clear();
+  }
+
+  void RebootRequired() { reboot_required_ = true; }
+
+  void TestBlacklistedRemoval(FileRemover* remover,
+                              const base::FilePath& path) {
+    DCHECK(remover);
+
+    EXPECT_EQ(ValidationStatus::FORBIDDEN, remover->CanRemove(path));
+
+    FileRemovalStatusUpdater* removal_status_updater =
+        FileRemovalStatusUpdater::GetInstance();
+
+    EXPECT_FALSE(remover->RemoveNow(path));
+    EXPECT_EQ(removal_status_updater->GetRemovalStatus(path),
+              REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+
+    removal_status_updater->Clear();
+    EXPECT_FALSE(remover->RegisterPostRebootRemoval(path));
+    EXPECT_EQ(removal_status_updater->GetRemovalStatus(path),
+              REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+
+    EXPECT_TRUE(base::PathExists(path));
+    EXPECT_FALSE(IsFileRegisteredForPostRebootRemoval(path));
+  }
+
+  FileRemover default_file_remover_;
+  bool reboot_required_ = false;
+};
+
+}  // namespace
+
+TEST_F(FileRemoverTest, RemoveNowValidFile) {
+  // Create a temporary empty file.
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  const base::FilePath file_path = temp.GetPath().Append(kRemoveFile1);
+  EXPECT_TRUE(CreateEmptyFile(file_path));
+
+  // Removing it must succeed.
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
+  EXPECT_FALSE(base::PathExists(file_path));
+  EXPECT_EQ(
+      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(file_path),
+      REMOVAL_STATUS_REMOVED);
+}
+
+TEST_F(FileRemoverTest, RemoveNowAbsentFile) {
+  // Create a non-existing file name.
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  FileRemovalStatusUpdater* removal_status_updater =
+      FileRemovalStatusUpdater::GetInstance();
+
+  const base::FilePath file_path = temp.GetPath().Append(kRemoveFile1);
+  EXPECT_FALSE(base::PathExists(file_path));
+
+  // Removing it must not generate an error.
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
+            REMOVAL_STATUS_NOT_FOUND);
+
+  // Ensure the non-existant files with non-existant parents don't generate an
+  // error.
+  base::FilePath file_path_deeper = file_path.Append(kRemoveFile2);
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path_deeper));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path_deeper),
+            REMOVAL_STATUS_NOT_FOUND);
+}
+
+TEST_F(FileRemoverTest, NoKnownFileRemoval) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  FileRemover remover(
+      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST),
+      LayeredServiceProviderWrapper(), /*deletion_allowed_paths=*/{},
+      base::DoNothing::Repeatedly());
+
+  // Copy the sample DLL to the temp folder.
+  base::FilePath dll_path = GetSampleDLLPath();
+  ASSERT_TRUE(base::PathExists(dll_path)) << dll_path.value();
+
+  base::FilePath target_dll_path(
+      temp_dir.GetPath().Append(dll_path.BaseName()));
+  ASSERT_TRUE(base::CopyFile(dll_path, target_dll_path));
+
+  TestBlacklistedRemoval(&remover, target_dll_path);
+}
+
+TEST_F(FileRemoverTest, NoSelfRemoval) {
+  base::FilePath exe_path = PreFetchedPaths::GetInstance()->GetExecutablePath();
+  TestBlacklistedRemoval(&default_file_remover_, exe_path);
+}
+
+TEST_F(FileRemoverTest, NoWhitelistedFileRemoval) {
+  base::FilePath program_files_dir =
+      PreFetchedPaths::GetInstance()->GetProgramFilesFolder();
+  TestBlacklistedRemoval(&default_file_remover_, program_files_dir);
+}
+
+TEST_F(FileRemoverTest, NoWhitelistFileTempRemoval) {
+  base::FilePath temp_dir;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
+  TestBlacklistedRemoval(&default_file_remover_, temp_dir);
+}
+
+TEST_F(FileRemoverTest, NoLSPRemoval) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath provider_path = temp.GetPath().Append(kRemoveFile1);
+  ASSERT_TRUE(CreateEmptyFile(provider_path));
+
+  TestLayeredServiceProvider lsp;
+  lsp.AddProvider(kGUID1, provider_path);
+
+  FileRemover remover(nullptr, lsp, /*deletion_allowed_paths=*/{},
+                      base::DoNothing::Repeatedly());
+
+  TestBlacklistedRemoval(&remover, provider_path);
+}
+
+TEST_F(FileRemoverTest, CanRemoveAbsolutePath) {
+  EXPECT_EQ(ValidationStatus::ALLOWED,
+            default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\bar")));
+}
+
+TEST_F(FileRemoverTest, NoRelativePathRemoval) {
+  EXPECT_EQ(ValidationStatus::FORBIDDEN,
+            default_file_remover_.CanRemove(base::FilePath(L"bar.txt")));
+}
+
+TEST_F(FileRemoverTest, NoDriveRemoval) {
+  EXPECT_EQ(ValidationStatus::FORBIDDEN,
+            default_file_remover_.CanRemove(base::FilePath(L"C:")));
+  EXPECT_EQ(ValidationStatus::FORBIDDEN,
+            default_file_remover_.CanRemove(base::FilePath(L"C:\\")));
+}
+
+TEST_F(FileRemoverTest, NoPathTraversal) {
+  EXPECT_EQ(
+      ValidationStatus::FORBIDDEN,
+      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\..\\bar")));
+  EXPECT_EQ(
+      ValidationStatus::FORBIDDEN,
+      default_file_remover_.CanRemove(base::FilePath(L"..\\foo\\bar.dll")));
+}
+
+TEST_F(FileRemoverTest, CorrectPathTraversalDetection) {
+  EXPECT_EQ(
+      ValidationStatus::ALLOWED,
+      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\..bar.dll")));
+  EXPECT_EQ(
+      ValidationStatus::ALLOWED,
+      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\bar..dll")));
+  EXPECT_EQ(
+      ValidationStatus::ALLOWED,
+      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo..\\bar.dll")));
+}
+
+TEST_F(FileRemoverTest, RemoveNowDoesNotDeleteFolders) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  // Create the folder and the files.
+  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
+  base::CreateDirectory(subfolder_path);
+  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
+  ASSERT_TRUE(CreateEmptyFile(file_path1));
+
+  // The folder should not be removed.
+  EXPECT_FALSE(default_file_remover_.RemoveNow(subfolder_path));
+  EXPECT_EQ(
+      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(subfolder_path),
+      REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+  EXPECT_TRUE(base::PathExists(subfolder_path));
+  EXPECT_TRUE(base::PathExists(file_path1));
+}
+
+TEST_F(FileRemoverTest, RemoveNowDeletesEmptyFolders) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  // Create the folder and the files.
+  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
+  base::CreateDirectory(subfolder_path);
+  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
+  ASSERT_TRUE(CreateEmptyFile(file_path1));
+  base::FilePath subsubfolder_path = subfolder_path.Append(kRemoveFolder);
+  base::CreateDirectory(subsubfolder_path);
+  base::FilePath file_path2 = subsubfolder_path.Append(kRemoveFile2);
+  ASSERT_TRUE(CreateEmptyFile(file_path2));
+
+  FileRemovalStatusUpdater* removal_status_updater =
+      FileRemovalStatusUpdater::GetInstance();
+
+  // Delete a file in a folder with other stuff, so the folder isn't deleted.
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path1));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path1),
+            REMOVAL_STATUS_REMOVED);
+  EXPECT_TRUE(base::PathExists(subfolder_path));
+  EXPECT_FALSE(base::PathExists(file_path1));
+  EXPECT_TRUE(base::PathExists(subsubfolder_path));
+  EXPECT_TRUE(base::PathExists(file_path2));
+
+  // Delete the file and ensure the two parent folders are deleted since they
+  // are now empty.
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path2));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path2),
+            REMOVAL_STATUS_REMOVED);
+  EXPECT_FALSE(base::PathExists(subfolder_path));
+  EXPECT_FALSE(base::PathExists(subsubfolder_path));
+  EXPECT_FALSE(base::PathExists(file_path2));
+}
+
+TEST_F(FileRemoverTest, RemoveNowDeletesEmptyFoldersNotTemp) {
+  base::ScopedPathOverride temp_override(base::DIR_TEMP);
+
+  base::FilePath scoped_temp_dir;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &scoped_temp_dir));
+
+  // Create a file in temp.
+  base::FilePath file_path = scoped_temp_dir.Append(kRemoveFile1);
+  ASSERT_TRUE(CreateEmptyFile(file_path));
+
+  // Delete the file and ensure Temp isn't deleted since it is whitelisted.
+  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
+  EXPECT_EQ(
+      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(file_path),
+      REMOVAL_STATUS_REMOVED);
+  EXPECT_FALSE(base::PathExists(file_path));
+  base::FilePath temp_dir;
+  ASSERT_TRUE(base::GetTempDir(&temp_dir));
+  EXPECT_TRUE(base::PathExists(temp_dir));
+}
+
+TEST_F(FileRemoverTest, RegisterPostRebootRemoval) {
+  FileRemovalStatusUpdater* removal_status_updater =
+      FileRemovalStatusUpdater::GetInstance();
+
+  // When trying to delete a whitelisted file, we should fail to register the
+  // file for removal, and no reboot should be required.
+  base::FilePath exe_path = PreFetchedPaths::GetInstance()->GetExecutablePath();
+  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(exe_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(exe_path),
+            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+  EXPECT_FALSE(reboot_required_);
+
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath file_path = temp.GetPath().Append(kRemoveFile2);
+
+  // When trying to delete an non-existant file, we should return success, but
+  // not require a reboot.
+  EXPECT_TRUE(default_file_remover_.RegisterPostRebootRemoval(file_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
+            REMOVAL_STATUS_NOT_FOUND);
+  EXPECT_FALSE(reboot_required_);
+
+  // When trying to delete a real file, we should return success and require a
+  // reboot.
+  ASSERT_TRUE(CreateEmptyFile(file_path));
+  EXPECT_TRUE(default_file_remover_.RegisterPostRebootRemoval(file_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
+            REMOVAL_STATUS_SCHEDULED_FOR_REMOVAL);
+  EXPECT_TRUE(reboot_required_);
+  EXPECT_TRUE(IsFileRegisteredForPostRebootRemoval(file_path));
+}
+
+TEST_F(FileRemoverTest, RegisterPostRebootRemoval_Directories) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  // Create an empty directory.
+  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
+  ASSERT_TRUE(base::CreateDirectory(subfolder_path));
+
+  FileRemovalStatusUpdater* removal_status_updater =
+      FileRemovalStatusUpdater::GetInstance();
+
+  // Directories shouldn't be registered for deletion.
+  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(subfolder_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(subfolder_path),
+            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+
+  // Put a file into the directory and ensure the non-empty directory still
+  // isn't registered for removal.
+  removal_status_updater->Clear();
+  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
+  ASSERT_TRUE(CreateEmptyFile(file_path1));
+  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(subfolder_path));
+  EXPECT_EQ(removal_status_updater->GetRemovalStatus(subfolder_path),
+            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
+}
+
+TEST_F(FileRemoverTest, NotActiveFileType) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
+  ASSERT_TRUE(
+      CreateFileInFolder(path.DirName(), path.BaseName().value().c_str()));
+
+  EXPECT_EQ(ValidationStatus::INACTIVE,
+            FileRemover::IsFileRemovalAllowed(path, {}, {}));
+  EXPECT_TRUE(default_file_remover_.RemoveNow(path));
+  EXPECT_EQ(REMOVAL_STATUS_NOT_REMOVED_INACTIVE_EXTENSION,
+            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
+  EXPECT_TRUE(base::PathExists(path));
+}
+
+TEST_F(FileRemoverTest, NotActiveFileAllowed) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
+  ASSERT_TRUE(
+      CreateFileInFolder(path.DirName(), path.BaseName().value().c_str()));
+
+  FileRemover remover(nullptr, LayeredServiceProviderWrapper(),
+                      {path.value().c_str()}, base::DoNothing::Repeatedly());
+
+  EXPECT_EQ(ValidationStatus::ALLOWED, FileRemover::IsFileRemovalAllowed(
+                                           path, {path.value().c_str()}, {}));
+  EXPECT_TRUE(remover.RemoveNow(path));
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
+            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
+  EXPECT_FALSE(base::PathExists(path));
+}
+
+TEST_F(FileRemoverTest, DosMzExecutable) {
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
+  constexpr char kMzExecutable[] = "MZ executable";
+  CreateFileWithContent(path, kMzExecutable, sizeof(kMzExecutable));
+  ASSERT_TRUE(base::PathExists(path));
+
+  FileRemover remover(nullptr, LayeredServiceProviderWrapper(),
+                      {path.value().c_str()}, base::DoNothing::Repeatedly());
+
+  EXPECT_EQ(ValidationStatus::ALLOWED,
+            FileRemover::IsFileRemovalAllowed(path, {}, {}));
+  EXPECT_TRUE(remover.RemoveNow(path));
+  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
+            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
+  EXPECT_FALSE(base::PathExists(path));
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn
index adc94eb..6dd920a 100644
--- a/chrome/chrome_cleaner/settings/BUILD.gn
+++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -8,7 +8,7 @@
   ]
 }
 
-static_library("settings") {
+source_set("settings") {
   sources = [
     "settings.cc",
     "settings.h",
@@ -28,14 +28,14 @@
   ]
 }
 
-static_library("matching_options") {
+source_set("matching_options") {
   sources = [
     "matching_options.cc",
     "matching_options.h",
   ]
 }
 
-static_library("default_matching_options") {
+source_set("default_matching_options") {
   sources = [
     "default_matching_options.cc",
     "default_matching_options.h",
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn
index e4609bb..421d318 100644
--- a/chrome/chrome_cleaner/test/BUILD.gn
+++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -28,23 +28,69 @@
   ]
 }
 
-static_library("test_util") {
+source_set("test_executables") {
   testonly = true
 
   sources = [
-    "test_file_util.cc",
-    "test_file_util.h",
-    "test_name_helper.cc",
-    "test_registry_util.cc",
-    "test_registry_util.h",
+    "test_executables.cc",
+    "test_executables.h",
+  ]
+
+  # Assume that every target that uses the test_executables header will run one
+  # of the executables, so make sure they are built.
+  data_deps = [
+    ":test_process",
+    ":test_service",
   ]
 
   deps = [
+    ":test_strings",
+    ":test_util",
     "//base:base",
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
+    "//chrome/chrome_cleaner/constants:common_strings",
+  ]
+}
+
+source_set("test_util") {
+  testonly = true
+
+  sources = [
+    "reboot_deletion_helper.cc",
+    "reboot_deletion_helper.h",
+    "test_file_util.cc",
+    "test_file_util.h",
+    "test_layered_service_provider.cc",
+    "test_layered_service_provider.h",
+    "test_name_helper.cc",
+    "test_name_helper.h",
+    "test_registry_util.cc",
+    "test_registry_util.h",
+    "test_util.cc",
+    "test_util.h",
+  ]
+
+  deps = [
+    ":test_pup_data",
+    ":test_strings",
+    "//base:base",
+    "//base/test:test_support",
+    "//chrome/chrome_cleaner/constants:common_strings",
+    "//chrome/chrome_cleaner/os:cleaner_os",
     "//chrome/chrome_cleaner/os:common_os",
-    "//chrome/chrome_cleaner/proto:shared_pup_enums_proto",
     "//chrome/chrome_cleaner/pup_data:pup_data_base",
+    "//chrome/chrome_cleaner/strings",
+    "//components/chrome_cleaner/public/constants:constants",
+    "//sandbox/win:sandbox",
+  ]
+
+  data_deps = [
+    ":empty_dll",
+    "//chrome/chrome_cleaner/test/resources:signed_empty_dll",
+  ]
+
+  public_deps = [
+    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
+    "//chrome/chrome_cleaner/proto:shared_pup_enums_proto",
     "//testing/gmock",
     "//testing/gtest",
   ]
@@ -80,3 +126,52 @@
     "//testing/gtest",
   ]
 }
+
+source_set("unittest_sources") {
+  testonly = true
+
+  sources = [
+    "reboot_deletion_helper_unittest.cc",
+    "test_util_unittest.cc",
+  ]
+
+  deps = [
+    ":test_util",
+    "//base",
+    "//base/test:test_support",
+    "//chrome/chrome_cleaner/os:common_os",
+    "//testing/gtest",
+  ]
+}
+
+executable("test_process") {
+  testonly = true
+
+  sources = [
+    "test_process_main.cc",
+  ]
+
+  deps = [
+    ":test_strings",
+    ":test_util",
+    "//base:base",
+    "//base/test:test_support",
+    "//build/win:default_exe_manifest",
+    "//chrome/chrome_cleaner/os:common_os",
+  ]
+}
+
+executable("test_service") {
+  testonly = true
+
+  sources = [
+    "test_service_main.cc",
+  ]
+
+  deps = [
+    ":test_strings",
+    "//base:base",
+    "//base/test:test_support",
+    "//build/win:default_exe_manifest",
+  ]
+}
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper.cc b/chrome/chrome_cleaner/test/reboot_deletion_helper.cc
new file mode 100644
index 0000000..7792cb1
--- /dev/null
+++ b/chrome/chrome_cleaner/test/reboot_deletion_helper.cc
@@ -0,0 +1,306 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
+
+#include <windows.h>
+
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/win/registry.h"
+#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
+#include "chrome/chrome_cleaner/os/registry_util.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+// The moves-pending-reboot is a MULTISZ registry value in the HKLM part of the
+// registry.
+const wchar_t kSessionManagerKey[] =
+    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
+const wchar_t kPendingFileRenameOps[] = L"PendingFileRenameOperations";
+
+const wchar_t kDoubleNullEntry[] = L"\0\0";
+
+// Convert the strings found in |buffer| to a list of string16s that is returned
+// in |value|. |buffer| is a string which contains a series of pairs of
+// null-terminated string16s followed by a terminating null character. |value|
+// is a pointer to an empty vector of pending moves. On success, this vector
+// contains all of the strings extracted from |buffer|.
+// Returns false if buffer does not meet the above specification.
+bool MultiSZToStringArray(const base::string16& buffer,
+                          std::vector<PendingMove>* value) {
+  DCHECK(value);
+  DCHECK(value->empty());
+
+  const base::char16* data = buffer.c_str();
+  const base::char16* data_end = data + buffer.size();
+
+  // Put null-terminated strings into the sequence.
+  while (data < data_end) {
+    // Parse the source path.
+    base::string16 str_from(data);
+    data += str_from.length() + 1;
+
+    // Parse the destination path. If the offset is at the end of the string,
+    // we assume the destination is empty. This may happen with corrupt registry
+    // values where there are missing trailing null characters.
+    base::string16 str_to;
+    if (data > data_end)
+      return false;
+    if (data < data_end)
+      str_to = data;
+
+    // Move to the next entry.
+    data += str_to.length() + 1;
+    value->push_back(std::make_pair(str_from, str_to));
+  }
+  return true;
+}
+
+// The inverse of MultiSZToStringArray, this function converts a list
+// of string pairs into a byte array format suitable for writing to the
+// kPendingFileRenameOps registry value. It concatenates the strings and
+// appends an additional terminating null character.
+void StringArrayToMultiSZ(const std::vector<PendingMove>& pending_moves,
+                          base::string16* buffer) {
+  DCHECK(buffer);
+  buffer->clear();
+
+  if (pending_moves.empty()) {
+    // Leave buffer empty if there are no strings.
+    return;
+  }
+
+  size_t total_wchars = 0;
+  std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
+  for (; iter != pending_moves.end(); ++iter) {
+    total_wchars += iter->first.length();
+    ++total_wchars;  // Space for the null char.
+    total_wchars += iter->second.length();
+    ++total_wchars;  // Space for the null char.
+  }
+  ++total_wchars;  // Space for the extra terminating null char.
+
+  buffer->resize(total_wchars);
+  base::char16* write_pointer =
+      reinterpret_cast<base::char16*>(&((*buffer)[0]));
+  // Keep an end pointer around for sanity checking.
+  base::char16* end_pointer = write_pointer + total_wchars;
+
+  std::vector<PendingMove>::const_iterator copy_iter(pending_moves.begin());
+  for (; copy_iter != pending_moves.end() && write_pointer < end_pointer;
+       ++copy_iter) {
+    // First copy the source string.
+    size_t string_length = copy_iter->first.length() + 1;
+    ::memcpy(write_pointer, copy_iter->first.c_str(),
+             string_length * sizeof(base::char16));
+    write_pointer += string_length;
+    // Now copy the destination string.
+    string_length = copy_iter->second.length() + 1;
+    ::memcpy(write_pointer, copy_iter->second.c_str(),
+             string_length * sizeof(base::char16));
+    write_pointer += string_length;
+
+    // We should never run off the end while in this loop.
+    DCHECK(write_pointer < end_pointer);
+  }
+  *write_pointer = L'\0';  // Explicitly set the final null char.
+  DCHECK(++write_pointer == end_pointer);
+}
+
+// A helper function for the win32 GetShortPathName that more conveniently
+// returns a FilePath. Note that if |path| is not present on the file system
+// then GetShortPathName will return |path| unchanged, unlike the win32
+// GetShortPathName which will return an error.
+base::FilePath GetShortPathName(const base::FilePath& path) {
+  base::string16 short_path;
+  DWORD length = ::GetShortPathName(
+      path.value().c_str(), base::WriteInto(&short_path, MAX_PATH), MAX_PATH);
+  DPLOG_IF(WARNING, length == 0 && ::GetLastError() != ERROR_PATH_NOT_FOUND)
+      << "GetShortPathName an unexpected result.";
+  if (length == 0) {
+    // GetShortPathName fails if the path is no longer present. Instead of
+    // returning an empty string, just return the original string. This will
+    // serve our purpose.
+    return path;
+  }
+
+  short_path.resize(length);
+  return base::FilePath(short_path);
+}
+
+base::FilePath GetShortPathNameWithoutPrefix(const base::FilePath& reg_path) {
+  // Stores the path stored in each entry.
+  base::string16 match_path(reg_path.value());
+
+  // First chomp the prefix since that will mess up GetShortPathName.
+  base::string16 prefix(L"\\??\\");
+  if (base::StartsWith(match_path, prefix,
+                       base::CompareCase::INSENSITIVE_ASCII))
+    match_path = match_path.substr(4);
+
+  // Get the short path name of the entry.
+  return GetShortPathName(base::FilePath(match_path));
+}
+
+}  // namespace
+
+bool IsFileRegisteredForPostRebootRemoval(const base::FilePath& file_path) {
+  base::FilePath short_path = GetShortPathName(NormalizePath(file_path));
+
+  PendingMoveVector pending_moves;
+  // This can only be called in tests, so CHECKing is ok since that ensures the
+  // test fails.
+  CHECK(GetPendingMoves(&pending_moves)) << "Unable to get pending moves";
+
+  for (PendingMoveVector::const_iterator iter(pending_moves.begin());
+       iter != pending_moves.end(); ++iter) {
+    if (!iter->second.empty()) {
+      // If the destination string is not empty, the pending operation is a move
+      // so this isn't a removal.
+      continue;
+    }
+
+    base::FilePath pending_path(
+        GetShortPathName(NormalizePath(base::FilePath(iter->first))));
+    pending_path = GetShortPathNameWithoutPrefix(pending_path);
+    if (base::FilePath::CompareEqualIgnoreCase(pending_path.value(),
+                                               short_path.value())) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool UnregisterPostRebootRemovals(const FilePathSet& paths) {
+  // Retrieve pending moves from the registry.
+  PendingMoveVector pending_moves;
+  if (!GetPendingMoves(&pending_moves))
+    return false;
+
+  // Build an index of short paths to remove.
+  UnorderedFilePathSet short_paths;
+  for (const auto& path : paths.file_paths()) {
+    short_paths.insert(GetShortPathName(path));
+  }
+
+  // Filter paths pending for deletion with the short paths index.
+  PendingMoveVector moves_to_keep;
+  for (PendingMoveVector::const_iterator iter(pending_moves.begin());
+       iter != pending_moves.end(); ++iter) {
+    if (!iter->second.empty()) {
+      // If the destination string is not empty, the pending operation is a move
+      // and must not be removed.
+      moves_to_keep.push_back(*iter);
+      continue;
+    }
+    base::FilePath pending_path(
+        GetShortPathName(NormalizePath(base::FilePath(iter->first))));
+    pending_path = GetShortPathNameWithoutPrefix(pending_path);
+    if (short_paths.find(pending_path) == short_paths.end())
+      moves_to_keep.push_back(*iter);
+  }
+
+  // Update the remaining pending moves to the registry.
+  if (!SetPendingMoves(moves_to_keep))
+    return false;
+
+  return true;
+}
+
+// Retrieves the list of pending moves from the registry and returns a vector
+// containing pairs of strings that represent the operations. If the list
+// contains only deletes then every other element will be an empty string
+// as per http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx.
+bool GetPendingMoves(PendingMoveVector* pending_moves) {
+  DCHECK(pending_moves);
+  pending_moves->clear();
+
+  // Get the current value of the key.
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_QUERY_VALUE);
+  HKEY session_manager_handle = session_manager_key.Handle();
+  if (!session_manager_handle ||
+      !session_manager_key.HasValue(kPendingFileRenameOps)) {
+    // If the key or the value is missing, that's totally acceptable.
+    return true;
+  }
+
+  // Read the content of the registry value to retrieve the pending moves.
+  base::string16 pending_moves_value;
+  uint32_t pending_moves_value_type;
+  if (!ReadRegistryValue(session_manager_key, kPendingFileRenameOps,
+                         &pending_moves_value, &pending_moves_value_type,
+                         nullptr)) {
+    DLOG(ERROR) << "Cannot read PendingRename registry value.";
+    return false;
+  }
+
+  if (pending_moves_value_type != REG_MULTI_SZ) {
+    DLOG(ERROR) << "Found PendingRename value of unexpected type.";
+    return false;
+  }
+
+  // We now have a buffer of bytes that is actually a sequence of
+  // null-terminated char16 strings terminated by an additional null character.
+  // Stick this into a vector of strings for clarity.
+  if (!MultiSZToStringArray(pending_moves_value, pending_moves)) {
+    DLOG(ERROR) << "Cannot decode PendingRename registry value.";
+    return false;
+  }
+
+  // Remove the last pending moves entry if it is empty. This entry is found on
+  // Vista+ but not on XP.
+  if (!pending_moves->empty() && pending_moves->back().first.empty() &&
+      pending_moves->back().second.empty()) {
+    pending_moves->pop_back();
+  }
+
+  return true;
+}
+
+bool SetPendingMoves(const PendingMoveVector& pending_moves) {
+  // Retrieve the key content into a buffer.
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
+  if (!session_manager_key.Handle()) {
+    // Couldn't open / create the key.
+    LOG(ERROR) << "Failed to open session manager key for writing.";
+    return false;
+  }
+
+  if (pending_moves.empty()) {
+    // No remaining moves. Don't bother writing that.
+    LONG delete_result = session_manager_key.DeleteValue(kPendingFileRenameOps);
+    return (delete_result == ERROR_SUCCESS ||
+            delete_result == ERROR_FILE_NOT_FOUND);
+  }
+
+  // Serialize pending moves as a sequence of bytes.
+  base::string16 buffer;
+  StringArrayToMultiSZ(pending_moves, &buffer);
+  if (buffer.empty())
+    return false;
+
+  // The pending moves format needs a null entry at the end which consists of
+  // two MULTISZ empty string.
+  base::string16 last_entry(kDoubleNullEntry, base::size(kDoubleNullEntry) - 1);
+  buffer = buffer + last_entry;
+
+  // Write back the serialized values into the registry key.
+  uint32_t size_in_bytes = buffer.size() * sizeof(base::char16);
+  if (session_manager_key.WriteValue(kPendingFileRenameOps, buffer.c_str(),
+                                     size_in_bytes,
+                                     REG_MULTI_SZ) != ERROR_SUCCESS) {
+    LOG(ERROR) << "Failed to update the " << kPendingFileRenameOps << " key.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper.h b/chrome/chrome_cleaner/test/reboot_deletion_helper.h
new file mode 100644
index 0000000..1a9165e9
--- /dev/null
+++ b/chrome/chrome_cleaner/test/reboot_deletion_helper.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
+#define CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
+
+#include <utility>
+#include <vector>
+
+#include "chrome/chrome_cleaner/os/file_path_set.h"
+
+namespace chrome_cleaner {
+
+// Holds the (source, destination) paths of a pending move. An empty
+// destination string means deletion instead of move.
+typedef std::pair<base::string16, base::string16> PendingMove;
+typedef std::vector<PendingMove> PendingMoveVector;
+
+// Returns true if the given file is registered to be deleted on the next
+// reboot.
+bool IsFileRegisteredForPostRebootRemoval(const base::FilePath& file_path);
+
+// Unregister all of the given files from being registered to be deleted after
+// the next reboot.
+bool UnregisterPostRebootRemovals(const FilePathSet& paths);
+
+// Get the list of all the pending post reboot moves.
+bool GetPendingMoves(PendingMoveVector* pending_moves);
+
+// Set all the pending moves for the nest reboot.
+bool SetPendingMoves(const PendingMoveVector& pending_moves);
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc b/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc
new file mode 100644
index 0000000..76f3742
--- /dev/null
+++ b/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc
@@ -0,0 +1,322 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/win/registry.h"
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+// The moves-pending-reboot is a MULTISZ registry value in the HKLM part of the
+// registry.
+const wchar_t kSessionManagerKey[] =
+    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
+const wchar_t kPendingFileRenameOps[] = L"PendingFileRenameOperations";
+
+const uint32_t kMaxRegistryValueLength = 1024;
+
+const wchar_t kRemoveFile1[] = L"remove_one";
+const wchar_t kRemoveFile2[] = L"remove_two";
+const wchar_t kRemoveFile3[] = L"remove_three";
+const wchar_t kRemoveFile4[] = L"remove_four";
+const wchar_t kRemoveFile5[] = L"remove_five";
+const wchar_t kDeleteFile[] = L"";
+const BYTE kNoNullInvalidString[] = {12, 13};
+const BYTE kMissingNullEntryString[] = {65, 0, 0, 0};
+const BYTE kOddSizeEntryString[] = {0, 65, 0, 66, 0xFF, 0, 0, 0, 0};
+const wchar_t kRemoveRawMultipleFiles[] =
+    L"remove_one\0\0remove_two\0remove_three\0\0\0";
+const wchar_t kRemoveRawEmpty0[] = L"";
+const wchar_t kRemoveRawEmpty1[] = L"\0";
+const wchar_t kRemoveRawEmpty2[] = L"\0\0";
+const wchar_t kRemoveRawCorrupt[] = L"file_with_no_ending_null";
+
+bool TestPendingFileRenameOperations(const wchar_t* content,
+                                     size_t content_size,
+                                     PendingMoveVector* pending_moves) {
+  DCHECK(content);
+  DCHECK(pending_moves);
+  pending_moves->clear();
+
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_ALL_ACCESS);
+  if (!session_manager_key.Handle()) {
+    PLOG(ERROR) << "Can't open session manager.";
+    return false;
+  }
+
+  // Write raw content of the registry value.
+  if (session_manager_key.WriteValue(kPendingFileRenameOps, content,
+                                     content_size,
+                                     REG_MULTI_SZ) != ERROR_SUCCESS) {
+    PLOG(ERROR) << "Can't write to registry value '" << kPendingFileRenameOps
+                << "' value: '" << content << "'.";
+    return false;
+  }
+
+  // Read back the pending moves.
+  if (!GetPendingMoves(pending_moves)) {
+    PLOG(ERROR) << "Can't read back or parse the registry value '"
+                << kPendingFileRenameOps << "'.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+TEST(RebootDeletionHelper, GetPendingMovesRawValue) {
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  PendingMoveVector pending_moves;
+  EXPECT_TRUE(
+      TestPendingFileRenameOperations(kRemoveRawEmpty0, 0, &pending_moves));
+  EXPECT_TRUE(pending_moves.empty());
+
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawEmpty0, sizeof(kRemoveRawEmpty0), &pending_moves));
+  EXPECT_TRUE(pending_moves.empty());
+
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawEmpty1, sizeof(kRemoveRawEmpty1), &pending_moves));
+  EXPECT_TRUE(pending_moves.empty());
+
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawEmpty2, sizeof(kRemoveRawEmpty2), &pending_moves));
+  EXPECT_TRUE(pending_moves.empty());
+
+  EXPECT_TRUE(TestPendingFileRenameOperations(kRemoveRawMultipleFiles,
+                                              sizeof(kRemoveRawMultipleFiles),
+                                              &pending_moves));
+  EXPECT_THAT(pending_moves,
+              testing::ElementsAre(std::make_pair(kRemoveFile1, kDeleteFile),
+                                   std::make_pair(kRemoveFile2, kRemoveFile3)));
+
+  const wchar_t kRemoveRawSingleFile[] = L"remove_one\0\0";
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawSingleFile, sizeof(kRemoveRawSingleFile), &pending_moves));
+  EXPECT_THAT(pending_moves,
+              testing::ElementsAre(std::make_pair(kRemoveFile1, kDeleteFile)));
+
+  const wchar_t kRemoveRawRename0[] = L"remove_one\0remove_two";
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawRename0, sizeof(kRemoveRawRename0), &pending_moves));
+  EXPECT_THAT(pending_moves,
+              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
+
+  const wchar_t kRemoveRawRename1[] = L"remove_one\0remove_two\0";
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawRename1, sizeof(kRemoveRawRename1), &pending_moves));
+  EXPECT_THAT(pending_moves,
+              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
+
+  const wchar_t kRemoveRawRename2[] = L"remove_one\0remove_two\0\0";
+  EXPECT_TRUE(TestPendingFileRenameOperations(
+      kRemoveRawRename2, sizeof(kRemoveRawRename2), &pending_moves));
+  EXPECT_THAT(pending_moves,
+              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
+
+  EXPECT_FALSE(TestPendingFileRenameOperations(
+      kRemoveRawCorrupt, sizeof(kRemoveRawCorrupt), &pending_moves));
+}
+
+TEST(RebootDeletionHelper, SetPendingMovesRawValue) {
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_ALL_ACCESS);
+  EXPECT_TRUE(session_manager_key.Handle());
+
+  // Write some pending moves.
+  PendingMoveVector pending_moves;
+  pending_moves.push_back(std::make_pair(kRemoveFile1, kDeleteFile));
+  pending_moves.push_back(std::make_pair(kRemoveFile2, kRemoveFile3));
+
+  EXPECT_TRUE(SetPendingMoves(pending_moves));
+
+  wchar_t buffer[kMaxRegistryValueLength];
+  DWORD buffer_size = kMaxRegistryValueLength;
+  DWORD buffer_type = REG_NONE;
+
+  // Validate the raw content of the registry value.
+  EXPECT_EQ(ERROR_SUCCESS,
+            session_manager_key.ReadValue(kPendingFileRenameOps, &buffer[0],
+                                          &buffer_size, &buffer_type));
+
+  EXPECT_EQ(buffer_size, sizeof(kRemoveRawMultipleFiles));
+  EXPECT_EQ(0, ::memcmp(kRemoveRawMultipleFiles, buffer, buffer_size));
+  EXPECT_EQ(REG_MULTI_SZ, buffer_type);
+}
+
+TEST(RebootDeletionHelper, SetPendingMovesValueWithEmptyInput) {
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_ALL_ACCESS);
+  EXPECT_TRUE(session_manager_key.Handle());
+
+  // Write raw content of the registry value.
+  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
+                               kPendingFileRenameOps, kRemoveRawMultipleFiles,
+                               sizeof(kRemoveRawMultipleFiles), REG_MULTI_SZ));
+
+  // Write an empty pending moves vector.
+  PendingMoveVector pending_moves;
+  SetPendingMoves(pending_moves);
+
+  // The registry value must be removed.
+  EXPECT_FALSE(session_manager_key.HasValue(kPendingFileRenameOps));
+}
+
+TEST(RebootDeletionHelper, GetAndSetPendingMoves) {
+  // Declare the scoped temp dir before the registry override manager because
+  // the recursive deletion of folders fail when running elevated while a
+  // registry override is active.
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  // Expect the registry key to be empty.
+  PendingMoveVector pending_moves;
+  EXPECT_TRUE(GetPendingMoves(&pending_moves));
+  ASSERT_TRUE(pending_moves.empty());
+
+  // Write back some moves into the registry key.
+  base::FilePath file_path1 = temp.GetPath().Append(kRemoveFile1);
+  base::FilePath file_path2 = temp.GetPath().Append(kRemoveFile2);
+  base::FilePath file_path3 = temp.GetPath().Append(kRemoveFile3);
+
+  pending_moves.push_back(
+      std::make_pair(file_path1.value(), file_path2.value()));
+  pending_moves.push_back(std::make_pair(file_path3.value(), kDeleteFile));
+
+  EXPECT_TRUE(SetPendingMoves(pending_moves));
+
+  // Read back the written moves.
+  PendingMoveVector written_moves;
+  EXPECT_TRUE(GetPendingMoves(&written_moves));
+
+  // Validate that moves before and after serialisation are the same.
+  EXPECT_THAT(written_moves, testing::ElementsAreArray(pending_moves));
+
+  // Write back an empty set of moves.
+  pending_moves.clear();
+  EXPECT_TRUE(SetPendingMoves(pending_moves));
+  EXPECT_TRUE(GetPendingMoves(&written_moves));
+  EXPECT_TRUE(written_moves.empty());
+}
+
+TEST(RebootDeletionHelper, GetInvalidPendingMoves) {
+  // Open the pending registry key to write into invalid data.
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
+                                        KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
+  EXPECT_TRUE(session_manager_key.Handle());
+
+  // Write an invalid pending moves registry key with a wrong type.
+  EXPECT_EQ(ERROR_SUCCESS,
+            session_manager_key.WriteValue(kPendingFileRenameOps, 0xCCCCCCCC));
+  PendingMoveVector pending_moves;
+  EXPECT_FALSE(GetPendingMoves(&pending_moves));
+
+  // Write an invalid pending moves registry key with an invalid string format.
+  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
+                               kPendingFileRenameOps, kNoNullInvalidString,
+                               sizeof(kNoNullInvalidString), REG_MULTI_SZ));
+  EXPECT_FALSE(GetPendingMoves(&pending_moves));
+
+  // Write an invalid string without the ending empty entry.
+  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
+                               kPendingFileRenameOps, kMissingNullEntryString,
+                               sizeof(kMissingNullEntryString), REG_MULTI_SZ));
+  EXPECT_FALSE(GetPendingMoves(&pending_moves));
+
+  // Write an invalid string with an odd number of bytes.
+  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
+                               kPendingFileRenameOps, kOddSizeEntryString,
+                               sizeof(kOddSizeEntryString), REG_MULTI_SZ));
+  EXPECT_TRUE(GetPendingMoves(&pending_moves));
+}
+
+TEST(RebootDeletionHelper, UnregisterPostRebootRemovals) {
+  // Declare the scoped temp dir before the registry override manager because
+  // the recursive deletion of folders fail when running elevated while a
+  // registry override is active.
+  base::ScopedTempDir temp;
+  ASSERT_TRUE(temp.CreateUniqueTempDir());
+
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  // Write some moves and renamings into the registry key.
+  base::FilePath file_path1 = temp.GetPath().Append(kRemoveFile1);
+  base::FilePath file_path2 = temp.GetPath().Append(kRemoveFile2);
+  base::FilePath file_path3 = temp.GetPath().Append(kRemoveFile3);
+  base::FilePath file_path4 = temp.GetPath().Append(kRemoveFile4);
+  base::FilePath file_path5 = temp.GetPath().Append(kRemoveFile5);
+
+  PendingMoveVector pending_moves;
+  pending_moves.push_back(std::make_pair(file_path1.value(), kDeleteFile));
+  pending_moves.push_back(std::make_pair(file_path2.value(), kDeleteFile));
+  pending_moves.push_back(std::make_pair(file_path3.value(), kDeleteFile));
+  pending_moves.push_back(
+      std::make_pair(file_path4.value(), file_path5.value()));
+
+  EXPECT_TRUE(SetPendingMoves(pending_moves));
+
+  // Unregister paths from the pending moves.
+  FilePathSet paths;
+  paths.Insert(file_path2);
+  paths.Insert(file_path3);
+  // A file renaming action must not be removed, even if a unregister is
+  // requested.
+  paths.Insert(file_path4);
+  EXPECT_TRUE(UnregisterPostRebootRemovals(paths));
+
+  // Read back the pending moves.
+  PendingMoveVector written_moves;
+  EXPECT_TRUE(GetPendingMoves(&written_moves));
+  EXPECT_THAT(written_moves,
+              testing::ElementsAre(
+                  std::make_pair(file_path1.value(), kDeleteFile),
+                  std::make_pair(file_path4.value(), file_path5.value())));
+}
+
+TEST(RebootDeletionHelper, UnregisterPostRebootRemovalsOfQualifiedPath) {
+  registry_util::RegistryOverrideManager registry_override;
+  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
+
+  // Add a pending deletion with a qualified path.
+  PendingMoveVector pending_moves;
+  pending_moves.push_back(
+      std::make_pair(L"\\??\\C:\\this_file_doesnt_exist", kDeleteFile));
+  EXPECT_TRUE(SetPendingMoves(pending_moves));
+
+  // Try to remove it with an unqualified path.
+  FilePathSet paths;
+  paths.Insert(base::FilePath(FILE_PATH_LITERAL("C:\\this_file_doesnt_exist")));
+  EXPECT_TRUE(UnregisterPostRebootRemovals(paths));
+
+  // Read back the pending moves.
+  PendingMoveVector written_moves;
+  EXPECT_TRUE(GetPendingMoves(&written_moves));
+  EXPECT_TRUE(written_moves.empty());
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/resources/BUILD.gn b/chrome/chrome_cleaner/test/resources/BUILD.gn
index aa31e346..f363a360 100644
--- a/chrome/chrome_cleaner/test/resources/BUILD.gn
+++ b/chrome/chrome_cleaner/test/resources/BUILD.gn
@@ -53,3 +53,13 @@
     ":compute_sample_dll_digest",
   ]
 }
+
+copy("signed_empty_dll") {
+  sources = [
+    "signed_dll/signed_empty_dll.dll",
+  ]
+
+  outputs = [
+    "$root_out_dir/signed_empty_dll.dll",
+  ]
+}
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/README.md b/chrome/chrome_cleaner/test/resources/signed_dll/README.md
new file mode 100644
index 0000000..fa57d67d
--- /dev/null
+++ b/chrome/chrome_cleaner/test/resources/signed_dll/README.md
@@ -0,0 +1,35 @@
+### Signed test files
+
+This directory contains a self-signed test certificate and its private key.
+
+1. cleaner_test_cert.crt and cleaner_test_key.key were generated with:
+
+   ```
+   openssl req -new -newkey rsa:4096 -x509 -sha256 -days 1095 -nodes -out cleaner_test_cert.crt -keyout cleaner_test_key.key
+   ```
+
+   Leave every entry blank except CN set to "Cleaner Test Cert".
+
+   openssl is bundled with Windows Git. A copy can be found in
+   depot_tools/win_tools-2_7_6_bin/git.
+
+1. cleaner_test_cert.pfx was generated with:
+
+   ```
+   openssl pkcs12 -in cleaner_test_cert.crt -inkey cleaner_test_key.key -export -out cleaner_test_cert.pfx
+   ```
+
+   Under Windows Git's bash shell, you need to use the "winpty" wrapper because
+   it asks for user input. Leave the password blank.
+
+1. signed_empty_dll.dll was generated using the
+   //chrome/chrome_cleaner/test:empty_dll target, and then signed with
+
+   ```
+   signtool.exe sign /fd sha256 /f cleaner_test_cert.pfx signed_empty_dll.dll
+   ```
+
+   A copy of signtool.exe can be found in depot_tools/win_toolchain/vs_files.
+
+   Under Windows Git's bash shell, don't forget to escape the arguments (use
+   "//fd" and "//f"). The error message if you don't escape them is cryptic.
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt
new file mode 100644
index 0000000..a43b1e04
--- /dev/null
+++ b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIFCzCCAvOgAwIBAgIJANsfwJbhowz8MA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNV
+BAMMEUNsZWFuZXIgVGVzdCBDZXJ0MB4XDTE4MDcyMDE1MjcxN1oXDTIxMDcxOTE1
+MjcxN1owHDEaMBgGA1UEAwwRQ2xlYW5lciBUZXN0IENlcnQwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQDDJXXzVyMjVU9IaufYZnbcfm+iDuKdIIStGIkP
+KVlT22cnUtSVDKykJy+SAmnzFN0tsMWyYPzTj3onfPQ6y+qAW+AhDpKCASHeMUJC
+VmPAa2mW06hEJpSRLLsBkUFV8jQgvgA0EZlBzIE9tTJXj3kTGry41Fb+Yh/RHRuV
+VXCVK5aYRtbZznLJOSkGri8k8dIqiVBOzI3Z83JD1RmfGisRSgvtg7SoQ8l+ZfQz
+bycw1wP4XJO+/NysksBW10Q5bB4XjwuPFURk+OGVlm/7WoaR6nFoQ0G9Z1YYh+pH
+FGlIYuoFngCznrwxXEAFtOVTXWVrumWhOKnHMEYkdiNPujzYekeu7ch8si/ThTH4
+m8Aphw8QAFQ2lKr9gAM/6fxSXhFUfo4juXtJF3Lz7CeLe7fY76e2NPaEwY7MyEuo
+vx6KXvemHFDJtqix2HCQCH/03TrAZNYavxWxAaH6DYpAuQRw9yUWdALFoSYVykQV
+vZ715yMtLRfT7Fi7UBK73G9G65rVbXPlDuB5uxwK48QA42PHT+u7QUY7BSKiJJBF
+6+C8BLnzVgH0ew0hFtGIUba2AYhV94RDkfTRUUq3ZuK1OmKtyC2XuHv7UXvrurlm
+BqhKl0yoACZnl3Jf3Fjouiq+Wh3IgzKvWCglYQUKQMvEHFnVk5Yu4Oh1s9xD5Mep
+PQ2JWQIDAQABo1AwTjAdBgNVHQ4EFgQUiRfCjDp9ApRzG2WbBPG/1z0jiIwwHwYD
+VR0jBBgwFoAUiRfCjDp9ApRzG2WbBPG/1z0jiIwwDAYDVR0TBAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEARRS1G7qAzz5wN8X6CSKFsBf3XXlw/De4fm8Z2Hs13GdP
+TMq8ASUgX3v+rlg/rKIiRov7sbPiaS3BpCwPfV/cCl5QVr3NWr/uqa5TPwYfb/y9
+vIWsHffD3HMp9wE7lxJLlbWQ1gX7CGYPbSJ4z+WnXg4f3KYu9Cjk1hUktpANT8gj
+p9vR7/kL9pEH70LWwTk8zDm6ibqkvSfEHP6wJpQBT6CiBfEB8x29F0klqQJ7jkh5
+wp4gFHQOTGmAdARvQOb788L1EWBIjuRgG0AmB2CoS+VwXl72xTMEWtMkitKtx0oP
+yvSXaGpW3/DcnxuWS7t0mtvNZMKmGj9rASeQcbqzGkpUmZkOHtB2msAsHVBakugb
+JsDnuwrYX5C7D8fIdDzHQPXXrZUjqb6qjOy58EVqYtqINcYzA9j766Cx4SJujmbR
+KrHU/9MAH39hcGrU/NW6mE8IYQ1SFpl8v2g7KdG0Er+ToTiCkOPrVJIst53G+0TG
+K6l81JfQ58J7ilFlcF0GWKaTZY+7d7889PgAvlfazxsUuioM48vQYUlA/ucbbyBN
+4nb/0q9kpY+tCiTZlFxCrmLNlspJHUvWUwbelUVtp+pjppbniMXXNwbOKvZltcoC
+K/Ownd8Z+5hsqDJcJdZmqO1bFNEI1RD8Oz4kFOso5LU8nItB78/lz3WnNLKHeS4=
+-----END CERTIFICATE-----
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx
new file mode 100644
index 0000000..c92f146
--- /dev/null
+++ b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx
Binary files differ
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key
new file mode 100644
index 0000000..e79bee9
--- /dev/null
+++ b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDDJXXzVyMjVU9I
+aufYZnbcfm+iDuKdIIStGIkPKVlT22cnUtSVDKykJy+SAmnzFN0tsMWyYPzTj3on
+fPQ6y+qAW+AhDpKCASHeMUJCVmPAa2mW06hEJpSRLLsBkUFV8jQgvgA0EZlBzIE9
+tTJXj3kTGry41Fb+Yh/RHRuVVXCVK5aYRtbZznLJOSkGri8k8dIqiVBOzI3Z83JD
+1RmfGisRSgvtg7SoQ8l+ZfQzbycw1wP4XJO+/NysksBW10Q5bB4XjwuPFURk+OGV
+lm/7WoaR6nFoQ0G9Z1YYh+pHFGlIYuoFngCznrwxXEAFtOVTXWVrumWhOKnHMEYk
+diNPujzYekeu7ch8si/ThTH4m8Aphw8QAFQ2lKr9gAM/6fxSXhFUfo4juXtJF3Lz
+7CeLe7fY76e2NPaEwY7MyEuovx6KXvemHFDJtqix2HCQCH/03TrAZNYavxWxAaH6
+DYpAuQRw9yUWdALFoSYVykQVvZ715yMtLRfT7Fi7UBK73G9G65rVbXPlDuB5uxwK
+48QA42PHT+u7QUY7BSKiJJBF6+C8BLnzVgH0ew0hFtGIUba2AYhV94RDkfTRUUq3
+ZuK1OmKtyC2XuHv7UXvrurlmBqhKl0yoACZnl3Jf3Fjouiq+Wh3IgzKvWCglYQUK
+QMvEHFnVk5Yu4Oh1s9xD5MepPQ2JWQIDAQABAoICAQCRoADXKK12DpFtjymYWU5V
+2JxhqQ3/B2c67NZK1CZu54mg1LUCzUR/8yYSpW5/EZDEKeg95xaEocsccKiov8ct
+JmKpCIDYNxQZBVVWv7UMwJs5DJXC1a+EbobW8ph5FJdF38OzF3bwnTXM4MzCfrRx
+R0CSBRMuHfd0S25sEChFiROGa0alnuQVuWweKhnQTgzx5Spiw08P2BXq/Llz+0ks
+S79+7QwBjSRuCJMlVss+LRYvXpZ6raPXvGN/6oBlAYOrPPn5OnuhhgCBapQCVFmb
+xgH/NkF2oAilobd4d4jhlb7hljkb0VbK1vaHy6hef5HRxHVWzDwWArY1O1u6gVYp
+PtN1ut/gFqEQRewwgZnN+rZP0Z2v1nL4s/0Nb8Y6BNtgEYHOnQZqHlq82JRCOlP8
+ezo+JkoZNZ9Aog/FVf85zkj02jxg0IIPYULQY66S3EWFT9mIHT+S+fiyKu3Y2Rra
+9h5/FlAhNcQY2uuOuKAXmS0Qz1pmv5mpgSrWmMDuYWGXsJ+Eq91IWR1bwSTdIztO
+jKfxzqNrhS1W8CfUHyAXan+yxaCni9AW9Qa7ADbSx49rhP+ihLd1PrXq1V+6LMGc
+MZ2rCL4xYgiZiFuYi89tqSUfJNVpzx0dQSDjOFv5yxGTf10rSxLAXmlN8wk466Ub
+SLLUQmcdwEqcnZT3fG26AQKCAQEA8oVNVM6zcaSyx64iC8ZfamlR/IZB4ARe9EY8
+3Im9D/Q7Z8qPcU2u4ZFDuynyxVhY24TfRKZhV7/Gv21eVbP/ChuobpEz7JaPEZhV
+GPIiTf8uKmvJ/YaQxJrx7MHDntL3SQForexo8cvfd8s7ZCge4hb4QgfxdESRGK7n
+EpaCrbNCMdSERSIA2HKswhypczdygKwVwm0XPae/YZeTP73/T8RdruD89NZcToTG
+vSTi6O6fdmVYGxkKb9TM49o4LJvm00AzlsV6hhoVGUJcqqFDrirxjOWJyWMFmJxb
+d7ZH3sHnX0Z6l91abSAwlUNoMg+ucPdQo+B+c7SPxKz9UQq64QKCAQEAzf4YB5q4
+1YBx2XRaJi8puSCCmnJKp+080pVxHrPOe0JqVa8HH4rVeMju34vFzLEk8Glvjc7u
+iRkqBTkU38wjTY70H+rj35njhrXMnuKDrmBMgezQAONZLpej44SjzSyF6djnBlxs
+a6cP9UuWKdts7hiUyqzGA55nMb7PAE8tG9lPh0FWktAnQYtT0Rn58D/WF5uy0c8h
+aPtUgrgExAvBNJpPAtnq7XOG75Iny5s91i8EXFDkIlTXYQp+0f+U6Qf75yE7BHzB
+TbuKI4Qo9/w3GMW1hMlBBydFwSJckmlP/fwVpfHog5+rHDZG2aHcphK23bO/tvJV
+/6yahwx1nz7VeQKCAQAN6QVxetWiDA9RErTTNhKc+OOB93Vp0vZbTngJMkFM2/ZY
+Uq79kbYZLArVfmd1WEboeGuR9XUZ4l8U9cH2aneTbdiwVtXCmTQljzY6UxESpjNQ
+rZQNXZ2KGVUM/mQpBPK4FkOZzjiKveXYaijC6uYyk5yztN7ti01DPCz2zPk7209N
+qmHX0UZ5I8Ky84/okuKXbMdmunkdyTRZ9aa1fkFZouq4sCDyLiVnP4hiqu307FLr
+KI7wJvSJS4xg+VBFhr+rmEAdQsBvVqmlJEBKbSuDnuTx7uyDR5G3mihI6oSey0Jp
+HZLEiSa5oaIHvbEJRgr8YcMXUzYNjuq8Hiv9bP8hAoIBAQCuDuOdIVbHSSZqWY+H
+LljyDg9tk9+Tb7nyMsaH6+Uwb9lMF35MX9KrohV+HSwBHzoYTu8tA0q52+KO0UHb
+LTIzafTMN31fRjhkbp+9LaeZI9PiAQlthq2n2ghoyn5icxmglF/6FwSiHmM0oS78
+pWWw9mJbs4wKKMIH3bQqDb0PCBvULRiLK4nQL3ued3WjVT2Ba1W5RW10uNIbNoUI
+ZupVmYHj5eFFzVWaf4RS3hVtMwNbQhrTC5+GZwjsRys7kTyAe6rTytrH5Qz/n7/C
+c4LW0tDjp+7jrYKahH92U7h845IjS3puJe+/AfnyEXxRdATC5wy6+KBET0Ovk46c
+Bcr5AoIBAEFA+NHs3omya+XLjed6fxRg6Bi14wIpMLCQbg7H+P4SXfSZLUk3e+zh
+gUjMG7vwzHGp7a5CJcL+Q7y4S5dcmwrgV4JNr4211P6HmehqaVjX3GJa79qe6wuB
+tD60Fh2cYg0DRZ555E60T/kxerwPQ5JEwr8tVkK6hcEyMIWPFmSB90E+cmIGmrzM
+kEvAEqlPVWc3uzFymH60yVbdUDAF8nSlBwjXa4RuXlLePflI4sAD3xSb+DRn/k0B
+cDKIrwpL+lCuIdWs1ARzQ1KKNQ80tKCAy8pPd4ZtVEgTdxiJfbpi+dlW65mLL/G5
+wU4oaRK0RLzuQ79pYtXPcXBbIBRm7Zo=
+-----END PRIVATE KEY-----
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll b/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll
new file mode 100755
index 0000000..c9fa53b
--- /dev/null
+++ b/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll
Binary files differ
diff --git a/chrome/chrome_cleaner/test/test_executables.cc b/chrome/chrome_cleaner/test/test_executables.cc
new file mode 100644
index 0000000..f92500559
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_executables.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/test/test_executables.h"
+
+#include "base/base_paths.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/win/win_util.h"
+#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+
+namespace chrome_cleaner {
+
+// If you add another test executable here, also add it to the data_deps in
+// the "test_executables" target of chrome_cleaner/test/BUILD.gn.
+
+const base::char16 kTestServiceExecutableName[] = L"test_service.exe";
+const base::char16 kTestProcessExecutableName[] = L"test_process.exe";
+
+base::Process LongRunningProcess(base::CommandLine* cmd) {
+  base::FilePath exe_dir;
+  if (!base::PathService::Get(base::DIR_EXE, &exe_dir)) {
+    LOG(ERROR) << "Failed to get the executable path, unable to create always "
+                  "running process";
+    return base::Process();
+  }
+
+  base::FilePath exe_path =
+      exe_dir.Append(chrome_cleaner::kTestProcessExecutableName);
+  base::CommandLine command_line(exe_path);
+  // This will ensure this new process will run for one minute before dying.
+  command_line.AppendSwitchASCII(chrome_cleaner::kTestSleepMinutesSwitch, "1");
+
+  std::unique_ptr<base::WaitableEvent> init_done_event =
+      chrome_cleaner::CreateInheritableEvent(
+          base::WaitableEvent::ResetPolicy::AUTOMATIC,
+          base::WaitableEvent::InitialState::NOT_SIGNALED);
+  command_line.AppendSwitchNative(
+      chrome_cleaner::kInitDoneNotifierSwitch,
+      base::UintToString16(
+          base::win::HandleToUint32(init_done_event->handle())));
+
+  if (cmd)
+    *cmd = command_line;
+
+  base::LaunchOptions launch_options;
+  launch_options.handles_to_inherit.push_back(init_done_event->handle());
+  base::Process result = base::LaunchProcess(command_line, launch_options);
+
+  if (!init_done_event->TimedWait(base::TimeDelta::FromSeconds(10))) {
+    LOG(ERROR) << "Process did not signal";
+    result.Terminate(/*exit_code=*/1, /*wait=*/false);
+    return base::Process();
+  }
+
+  return result;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_executables.h b/chrome/chrome_cleaner/test/test_executables.h
new file mode 100644
index 0000000..ca6a2af1
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_executables.h
@@ -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.
+
+#ifndef CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
+#define CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
+
+#include "base/command_line.h"
+#include "base/process/process.h"
+#include "base/strings/string16.h"
+
+namespace chrome_cleaner {
+
+// The name of the service executable used for tests.
+extern const base::char16 kTestServiceExecutableName[];
+
+// The name of the executable used for tests.
+extern const base::char16 kTestProcessExecutableName[];
+
+// Creates a process that will run for a minute, which is long enough to be
+// killed by a reasonably fast unit or integration test.
+// Populates |command_line| with the used command line if it is not nullptr.
+base::Process LongRunningProcess(base::CommandLine* command_line);
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
diff --git a/chrome/chrome_cleaner/test/test_layered_service_provider.cc b/chrome/chrome_cleaner/test/test_layered_service_provider.cc
new file mode 100644
index 0000000..a792fc6
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_layered_service_provider.cc
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
+
+namespace chrome_cleaner {
+
+TestLayeredServiceProvider::TestLayeredServiceProvider() = default;
+
+TestLayeredServiceProvider::~TestLayeredServiceProvider() = default;
+
+int TestLayeredServiceProvider::EnumProtocols(int* protocols,
+                                              WSAPROTOCOL_INFOW* protocol_info,
+                                              DWORD* nb_protocol_info,
+                                              int* error) const {
+  // We don't use the protocols argument yet.
+  DCHECK(!protocols);
+  DCHECK(nb_protocol_info);
+  DCHECK(error);
+  size_t bytes_needed = protocol_info_.size() * sizeof(WSAPROTOCOL_INFOW);
+  if (*nb_protocol_info < bytes_needed) {
+    *nb_protocol_info = bytes_needed;
+    *error = WSAENOBUFS;
+    return SOCKET_ERROR;
+  }
+  *nb_protocol_info = bytes_needed;
+  std::map<GUID, base::FilePath, GUIDLess>::const_iterator iter =
+      protocol_info_.begin();
+  for (size_t i = 0; iter != protocol_info_.end(); ++iter, ++i) {
+    protocol_info[i].ProviderId = iter->first;
+  }
+  return protocol_info_.size();
+}
+
+int TestLayeredServiceProvider::GetProviderPath(GUID* provider_id,
+                                                wchar_t* provider_dll_path,
+                                                int* provider_dll_path_len,
+                                                int* error) const {
+  DCHECK(provider_id);
+  DCHECK(provider_dll_path);
+  DCHECK(provider_dll_path_len);
+  DCHECK(error);
+  std::map<GUID, base::FilePath, GUIDLess>::const_iterator iter =
+      protocol_info_.find(*provider_id);
+  if (iter == protocol_info_.end()) {
+    *error = WSAEINVAL;
+    return SOCKET_ERROR;
+  }
+  if (*provider_dll_path_len <
+      static_cast<int>(iter->second.value().size() + 1)) {
+    *error = WSAEFAULT;
+    return SOCKET_ERROR;
+  }
+  ::wcsncpy(provider_dll_path, iter->second.value().c_str(),
+            iter->second.value().size());
+  provider_dll_path[iter->second.value().size()] = L'\0';
+  return 0;
+}
+
+void TestLayeredServiceProvider::AddProvider(const GUID& provider_id,
+                                             const base::FilePath& path) {
+  protocol_info_[provider_id] = path;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_layered_service_provider.h b/chrome/chrome_cleaner/test/test_layered_service_provider.h
new file mode 100644
index 0000000..dc32939
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_layered_service_provider.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
+#define CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
+
+#include <map>
+
+#include "base/files/file_path.h"
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "chrome/chrome_cleaner/os/layered_service_provider_api.h"
+
+namespace chrome_cleaner {
+
+class TestLayeredServiceProvider : public LayeredServiceProviderAPI {
+ public:
+  TestLayeredServiceProvider();
+  ~TestLayeredServiceProvider() override;
+
+  int EnumProtocols(int* protocols,
+                    WSAPROTOCOL_INFOW* protocol_info,
+                    DWORD* nb_protocol_info,
+                    int* error) const override;
+
+  int GetProviderPath(GUID* provider_id,
+                      wchar_t* provider_dll_path,
+                      int* provider_dll_path_len,
+                      int* error) const override;
+
+  void AddProvider(const GUID& provider_id, const base::FilePath& path);
+
+ private:
+  std::map<GUID, base::FilePath, GUIDLess> protocol_info_;
+};
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
diff --git a/chrome/chrome_cleaner/test/test_main.cc b/chrome/chrome_cleaner/test/test_main.cc
index 316aba8..f551a25 100644
--- a/chrome/chrome_cleaner/test/test_main.cc
+++ b/chrome/chrome_cleaner/test/test_main.cc
@@ -2,22 +2,76 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
-#include "chrome/chrome_cleaner/os/initializer.h"
-#include "chrome/chrome_cleaner/pup_data/pup_data.h"
-#include "chrome/chrome_cleaner/test/test_uws_catalog.h"
+#include "base/win/scoped_com_initializer.h"
+#include "chrome/chrome_cleaner/os/rebooter.h"
+#include "chrome/chrome_cleaner/os/secure_dll_loading.h"
+#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
+#include "chrome/chrome_cleaner/os/task_scheduler.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+#include "sandbox/win/src/sandbox_factory.h"
+
+namespace {
+
+bool IsSandboxedProcess() {
+  static const bool is_sandboxed_process =
+      (sandbox::SandboxFactory::GetTargetServices() != nullptr);
+  return is_sandboxed_process;
+}
+
+}  // namespace
 
 int main(int argc, char** argv) {
+  // This must be executed as soon as possible to reduce the number of dlls that
+  // the code might try to load before we can lock things down.
+  //
+  // We enable secure DLL loading in the test suite to be sure that it doesn't
+  // affect the behaviour of functionality that's tested.
+  chrome_cleaner::EnableSecureDllLoading();
+
   base::TestSuite test_suite(argc, argv);
 
-  chrome_cleaner::PUPData::InitializePUPData(
-      {&chrome_cleaner::TestUwSCatalog::GetInstance()});
-  chrome_cleaner::InitializeOSUtils();
+  if (!chrome_cleaner::SetupTestConfigs())
+    return 1;
 
-  return base::LaunchUnitTests(
+  if (!chrome_cleaner::CheckTestPrivileges())
+    return 1;
+
+  // Make sure tests will not end up in an infinite reboot loop.
+  if (chrome_cleaner::Rebooter::IsPostReboot())
+    return 0;
+
+  // ScopedCOMInitializer keeps COM initialized in a specific scope. We don't
+  // want to initialize it for sandboxed processes, so manage its lifetime with
+  // a unique_ptr, which will call ScopedCOMInitializer's destructor when it
+  // goes out of scope below.
+  std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer;
+
+  if (!IsSandboxedProcess()) {
+    scoped_com_initializer = std::make_unique<base::win::ScopedCOMInitializer>(
+        base::win::ScopedCOMInitializer::kMTA);
+    bool success = chrome_cleaner::InitializeCOMSecurity();
+    DCHECK(success) << "InitializeCOMSecurity() failed.";
+
+    success = chrome_cleaner::TaskScheduler::Initialize();
+    DCHECK(success) << "TaskScheduler::Initialize() failed.";
+  }
+
+  // Some tests will fail if two tests try to launch test_process.exe
+  // simultaneously, so run the tests serially. This will still shard them and
+  // distribute the shards to different swarming bots, but tests will run
+  // serially on each bot.
+  const int result = base::LaunchUnitTestsSerially(
       argc, argv,
       base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
+
+  if (!IsSandboxedProcess())
+    chrome_cleaner::TaskScheduler::Terminate();
+
+  return result;
 }
diff --git a/chrome/chrome_cleaner/test/test_process_main.cc b/chrome/chrome_cleaner/test/test_process_main.cc
new file mode 100644
index 0000000..de664d6
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_process_main.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "chrome/chrome_cleaner/os/initializer.h"
+#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
+#include "chrome/chrome_cleaner/os/secure_dll_loading.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+#include "chrome/chrome_cleaner/test/test_util.h"
+
+namespace {
+
+constexpr base::char16 kLogFileExtension[] = L"log";
+
+}  // namespace
+
+int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) {
+  // This must be executed as soon as possible to reduce the number of dlls that
+  // the code might try to load before we can lock things down.
+  chrome_cleaner::EnableSecureDllLoading();
+
+  base::AtExitManager at_exit;
+
+  bool success = base::CommandLine::Init(0, nullptr);
+  DCHECK(success);
+
+  if (!chrome_cleaner::SetupTestConfigs())
+    return 1;
+
+  // Initialize the logging settings to set a specific log file name.
+  base::FilePath exe_file_path =
+      chrome_cleaner::PreFetchedPaths::GetInstance()->GetExecutablePath();
+
+  base::FilePath log_file_path(
+      exe_file_path.ReplaceExtension(kLogFileExtension));
+  logging::LoggingSettings logging_settings;
+  logging_settings.logging_dest = logging::LOG_TO_FILE;
+  logging_settings.log_file = log_file_path.value().c_str();
+  success = logging::InitLogging(logging_settings);
+  DCHECK(success);
+
+  LOG(INFO) << "Process Started.";
+
+  chrome_cleaner::NotifyInitializationDoneForTesting();
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(
+          chrome_cleaner::kTestForceOverwriteZoneIdentifier)) {
+    LOG(INFO) << "Process is overwriting the zone identifier.";
+    chrome_cleaner::OverwriteZoneIdentifier(exe_file_path);
+  }
+
+  if (command_line->HasSwitch(chrome_cleaner::kTestSleepMinutesSwitch)) {
+    std::string value = command_line->GetSwitchValueASCII(
+        chrome_cleaner::kTestSleepMinutesSwitch);
+    int sleep_minutes = 0;
+    if (base::StringToInt(value, &sleep_minutes) && sleep_minutes > 0) {
+      LOG(INFO) << "Process is sleeping for " << sleep_minutes << " minutes";
+      ::Sleep(base::TimeDelta::FromMinutes(sleep_minutes).InMilliseconds());
+    } else {
+      LOG(ERROR) << "Invalid sleep delay value " << value;
+    }
+    NOTREACHED();
+    return 1;
+  }
+
+  if (command_line->HasSwitch(chrome_cleaner::kTestEventToSignal)) {
+    LOG(INFO) << "Process is signaling event '"
+              << chrome_cleaner::kTestEventToSignal << "'";
+    base::string16 event_name =
+        command_line->GetSwitchValueNative(chrome_cleaner::kTestEventToSignal);
+    base::win::ScopedHandle handle(
+        ::OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name.c_str()));
+    PLOG_IF(ERROR, !handle.IsValid())
+        << "Cannot create event '" << chrome_cleaner::kTestEventToSignal << "'";
+    base::WaitableEvent event(std::move(handle));
+    event.Signal();
+  }
+
+  // TODO(pmbureau): Add more behavior to test processes termination.
+
+  LOG(INFO) << "Process ended.";
+  return 0;
+}
diff --git a/chrome/chrome_cleaner/test/test_service_main.cc b/chrome/chrome_cleaner/test/test_service_main.cc
new file mode 100644
index 0000000..20afd27
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_service_main.cc
@@ -0,0 +1,153 @@
+// 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 <windows.h>
+
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/string16.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+
+namespace {
+
+class TestService {
+ public:
+  TestService() {
+    service_status_.dwCurrentState = SERVICE_START_PENDING;
+    service_status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    service_status_.dwWaitHint =
+        TestTimeouts::action_max_timeout().InMilliseconds();
+    service_stop_event_ = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+  }
+
+  void SignalStopEvent() { ::SetEvent(service_stop_event_); }
+  void WaitForStopEvent() {
+    ::WaitForSingleObject(service_stop_event_, INFINITE);
+  }
+
+  void SetControlsAccepted(DWORD control) {
+    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
+    service_status_.dwControlsAccepted = control;
+  }
+
+  void SetStatusHandle(SERVICE_STATUS_HANDLE status_handle) {
+    CHECK(status_handle);
+    status_handle_ = status_handle;
+  }
+
+  DWORD GetServiceStatusState() {
+    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
+    return service_status_.dwCurrentState;
+  }
+
+  void SetServiceStatusState(DWORD state) {
+    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
+    DCHECK(status_handle_);
+    service_status_.dwCurrentState = state;
+    if (::SetServiceStatus(status_handle_, &service_status_) == FALSE)
+      LOG(ERROR) << "Cannot set service status state.";
+  }
+
+ private:
+  SERVICE_STATUS_HANDLE status_handle_ = 0;
+  SERVICE_STATUS service_status_ = {};
+  HANDLE service_stop_event_ = INVALID_HANDLE_VALUE;
+  THREAD_CHECKER(service_status_thread_checker_);
+};
+
+DWORD WINAPI ServiceCtrlHandler(DWORD control,
+                                DWORD /* event_type */,
+                                LPVOID /* event_data */,
+                                LPVOID context) {
+  TestService* service = reinterpret_cast<TestService*>(context);
+  DCHECK(service);
+  if (control == SERVICE_CONTROL_STOP)
+    service->SignalStopEvent();
+  return 0;
+}
+
+void WINAPI ServiceMain(DWORD argc, LPTSTR* argv) {
+  TestService service;
+
+  // Registers a function to handle extended service control requests.
+  SERVICE_STATUS_HANDLE status_handle =
+      RegisterServiceCtrlHandlerEx(L"", ServiceCtrlHandler, &service);
+  service.SetStatusHandle(status_handle);
+
+  // Tell the service controller the current service has started.
+  service.SetServiceStatusState(SERVICE_START_PENDING);
+  LOG(INFO) << "Service status is 'start pending'.";
+
+  // Tell the service controller the current service is running.
+  service.SetControlsAccepted(SERVICE_ACCEPT_STOP);
+  service.SetServiceStatusState(SERVICE_RUNNING);
+  LOG(INFO) << "Service status is 'running'.";
+
+  // The body of the service wait until a stop signal is received.
+  LOG(INFO) << "Service is waiting to be stopped.";
+  service.WaitForStopEvent();
+
+  // TODO(pmbureau): Add more kind of worker that may protect against service
+  //     termination and validate service termination.
+
+  // Tell the service controller the current service is stopped.
+  service.SetServiceStatusState(SERVICE_STOP_PENDING);
+  LOG(INFO) << "Service status is 'stop pending'.";
+
+  service.SetServiceStatusState(SERVICE_STOPPED);
+  // Do not attempt to perform any additional work after calling
+  // SetServiceStatus with SERVICE_STOPPED, because the service process can be
+  // terminated at any time.
+}
+
+constexpr base::char16 kLogFileExtension[] = L"log";
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  base::AtExitManager at_exit;
+
+  bool success = base::CommandLine::Init(0, nullptr);
+  DCHECK(success);
+
+  TestTimeouts::Initialize();
+
+  // Initialize the logging settings to set a specific log file name.
+  base::FilePath exe_file_path;
+  success = base::PathService::Get(base::FILE_EXE, &exe_file_path);
+  DCHECK(success);
+
+  base::FilePath log_file_path(
+      exe_file_path.ReplaceExtension(kLogFileExtension));
+  logging::LoggingSettings logging_settings;
+  logging_settings.logging_dest = logging::LOG_TO_FILE;
+  logging_settings.log_file = log_file_path.value().c_str();
+  success = logging::InitLogging(logging_settings);
+  DCHECK(success);
+
+  LOG(INFO) << "Service Started.";
+
+  // Service main.
+
+  // SERVICE_TABLE_ENTRY::lpServiceName takes a non-const string.
+  base::char16 empty_string[] = L"";
+
+  SERVICE_TABLE_ENTRY dispatch_table[] = {{empty_string, ServiceMain},
+                                          {nullptr, nullptr}};
+
+  if (::StartServiceCtrlDispatcher(dispatch_table) == FALSE) {
+    LOG(ERROR) << "StartServiceCtrlDispatcher failed.";
+    return 1;
+  }
+
+  LOG(INFO) << "Service ended.";
+  return 0;
+}
diff --git a/chrome/chrome_cleaner/test/test_util.cc b/chrome/chrome_cleaner/test/test_util.cc
new file mode 100644
index 0000000..ac643fd
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_util.cc
@@ -0,0 +1,314 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_cleaner/test/test_util.h"
+
+#include <stdint.h>
+#include <windows.h>
+
+#include <algorithm>
+#include <iterator>
+#include <set>
+#include <utility>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "chrome/chrome_cleaner/os/initializer.h"
+#include "chrome/chrome_cleaner/os/post_reboot_registration.h"
+#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
+#include "chrome/chrome_cleaner/os/scoped_disable_wow64_redirection.h"
+#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
+#include "chrome/chrome_cleaner/os/whitelisted_directory.h"
+#include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h"
+#include "chrome/chrome_cleaner/strings/string_util.h"
+#include "chrome/chrome_cleaner/test/test_file_util.h"
+#include "chrome/chrome_cleaner/test/test_strings.h"
+#include "chrome/chrome_cleaner/test/test_uws_catalog.h"
+#include "sandbox/win/src/sandbox_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+bool SetupTestConfigs() {
+  return SetupTestConfigsWithCatalogs({&TestUwSCatalog::GetInstance()});
+}
+
+bool SetupTestConfigsWithCatalogs(const PUPData::UwSCatalogs& catalogs) {
+  if (!InitializeOSUtils())
+    return false;
+
+  PUPData::InitializePUPData(catalogs);
+
+  PreFetchedPaths::GetInstance()->DisableForTesting();
+  base::PathService::DisableCache();
+
+  WhitelistedDirectory::GetInstance()->DisableCache();
+
+  return true;
+}
+
+ScopedIsPostReboot::ScopedIsPostReboot() {
+  // This switch will be removed by scoped_command_line_'s destructor when it
+  // goes out of scope.
+  scoped_command_line_.GetProcessCommandLine()->AppendSwitch(kPostRebootSwitch);
+}
+
+bool RunOnceCommandLineContains(const base::string16& product_shortname,
+                                const wchar_t* sub_string) {
+  DCHECK(sub_string);
+  PostRebootRegistration post_reboot(product_shortname);
+  base::string16 run_once_value = post_reboot.RunOnceOnRestartRegisteredValue();
+  return String16ContainsCaseInsensitive(run_once_value, sub_string);
+}
+
+bool RunOnceOverrideCommandLineContains(const std::string& cleanup_id,
+                                        const wchar_t* sub_string) {
+  DCHECK(sub_string);
+
+  base::string16 reg_value;
+  base::win::RegKey run_once_key(
+      HKEY_CURRENT_USER,
+      PostRebootRegistration::GetPostRebootSwitchKeyPath().c_str(), KEY_READ);
+  if (run_once_key.Valid()) {
+    // There is no need to check the return value, since ReadValue will leave
+    // |reg_value| empty on error.
+    run_once_key.ReadValue(base::UTF8ToUTF16(cleanup_id).c_str(), &reg_value);
+  }
+
+  return String16ContainsCaseInsensitive(reg_value, sub_string);
+}
+
+bool RegisterTestTask(TaskScheduler* task_scheduler,
+                      TaskScheduler::TaskInfo* task_info) {
+  const wchar_t name[] = L"Chrome Cleaner Test task";
+  const wchar_t description[] =
+      L"Chrome Cleaner Test Task Used Just For Testing";
+
+  const base::FilePath exe_path =
+      PreFetchedPaths::GetInstance()->GetExecutablePath();
+
+  TaskScheduler::TaskExecAction action{
+      exe_path, base::FilePath(), L"argument",
+  };
+
+  base::CommandLine command_line(action.application_path);
+  command_line.AppendArgNative(action.arguments);
+  if (!task_scheduler->RegisterTask(
+          name, description, command_line,
+          chrome_cleaner::TaskScheduler::TRIGGER_TYPE_HOURLY, false)) {
+    LOG(ERROR) << "Failed to register test task";
+    return false;
+  }
+
+  task_info->name = name;
+  task_info->description = description;
+  task_info->exec_actions.push_back(action);
+  return true;
+}
+
+void AppendTestSwitches(base::CommandLine* command_line) {
+  command_line->AppendSwitch(kNoRecoveryComponentSwitch);
+  command_line->AppendSwitch(kNoCrashUploadSwitch);
+  command_line->AppendSwitch(kNoReportUploadSwitch);
+  command_line->AppendSwitch(kNoSelfDeleteSwitch);
+}
+
+void ExpectDiskFootprint(const PUPData::PUP& pup,
+                         const base::FilePath& expected_path) {
+  for (const auto& path : pup.expanded_disk_footprints.file_paths()) {
+    if (PathEqual(expected_path, path))
+      return;
+  }
+  ADD_FAILURE() << "Expected file: " << expected_path.value();
+}
+
+// Expect the scheduled task footprint to be found in |pup|.
+void ExpectScheduledTaskFootprint(const PUPData::PUP& pup,
+                                  const wchar_t* task_name) {
+  DCHECK(task_name);
+  for (const auto& footprint : pup.expanded_scheduled_tasks) {
+    if (footprint == task_name)
+      return;
+  }
+  ADD_FAILURE() << "Expected schedule task not found: '" << task_name << "'.";
+}
+
+bool StringContainsCaseInsensitive(const std::string& value,
+                                   const std::string& substring) {
+  return std::search(
+             value.begin(), value.end(), substring.begin(), substring.end(),
+             base::CaseInsensitiveCompareASCII<std::string::value_type>()) !=
+         value.end();
+}
+
+LoggingOverride::LoggingOverride() {
+  DCHECK(!active_logging_messages_);
+  active_logging_messages_ = &logging_messages_;
+  logging::SetLogMessageHandler(&LogMessageHandler);
+}
+
+LoggingOverride::~LoggingOverride() {
+  logging::SetLogMessageHandler(nullptr);
+  logging_messages_.clear();
+  DCHECK_EQ(active_logging_messages_, &logging_messages_);
+  active_logging_messages_ = nullptr;
+}
+
+bool LoggingOverride::LoggingMessagesContain(const std::string& sub_string) {
+  for (const auto& line : logging_messages_) {
+    if (StringContainsCaseInsensitive(line, sub_string))
+      return true;
+  }
+  return false;
+}
+
+bool LoggingOverride::LoggingMessagesContain(const std::string& sub_string1,
+                                             const std::string& sub_string2) {
+  for (const auto& line : logging_messages_) {
+    if (StringContainsCaseInsensitive(line, sub_string1) &&
+        StringContainsCaseInsensitive(line, sub_string2))
+      return true;
+  }
+  return false;
+}
+
+std::vector<std::string>* LoggingOverride::active_logging_messages_ = nullptr;
+
+bool IsSubsetOf(const FilePathSet& set1,
+                const FilePathSet& set2,
+                const std::string& unexpected_path_log_message) {
+  bool is_subset = true;
+  for (const base::FilePath& file_path : set1.file_paths()) {
+    if (!set2.Contains(file_path)) {
+      LOG(ERROR) << unexpected_path_log_message << ": '" << file_path.value()
+                 << "'";
+      is_subset = false;
+    }
+  }
+  return is_subset;
+}
+
+void ExpectEqualFilePathSets(const FilePathSet& matched_files,
+                             const FilePathSet& expected_files) {
+  EXPECT_TRUE(IsSubsetOf(matched_files, expected_files,
+                         "Unexpected file in matched footprints"));
+  EXPECT_TRUE(
+      IsSubsetOf(expected_files, matched_files, "Missing expected footprint"));
+}
+
+base::FilePath GetWow64RedirectedSystemPath() {
+  std::vector<wchar_t> buffer;
+  size_t size_needed = MAX_PATH;
+  while (size_needed > buffer.size()) {
+    buffer.resize(size_needed);
+    size_needed = ::GetSystemWow64DirectoryW(buffer.data(), buffer.size());
+    if (size_needed == 0) {
+      PLOG(ERROR) << "Could not get system Wow64 directory";
+      return base::FilePath();
+    }
+  }
+  buffer.push_back(L'\0');
+  return base::FilePath(buffer.data());
+}
+
+base::FilePath GetSampleDLLPath() {
+  // The sample DLL should be next to the executable because it is generated at
+  // build time.
+  base::FilePath exe_dir;
+  base::PathService::Get(base::DIR_EXE, &exe_dir);
+  return exe_dir.Append(L"empty_dll.dll");
+}
+
+base::FilePath GetSignedSampleDLLPath() {
+  // The signed sample DLL should be next to the executable because it's copied
+  // there at build time.
+  base::FilePath exe_dir;
+  base::PathService::Get(base::DIR_EXE, &exe_dir);
+  return exe_dir.Append(L"signed_empty_dll.dll");
+}
+
+ScopedTempDirNoWow64::ScopedTempDirNoWow64() = default;
+
+ScopedTempDirNoWow64::~ScopedTempDirNoWow64() {
+  // Since the temp dir was created with Wow64 disabled, it must be deleted
+  // with Wow64 disabled.
+  ScopedDisableWow64Redirection disable_wow64_redirection;
+  ANALYZER_ALLOW_UNUSED(Delete());
+
+  // The parent's destructor will call Delete again, without disabling Wow64,
+  // which could delete a directory with the same name in SysWOW64. So make
+  // sure the path is cleared even if the Delete call above failed.
+  Take();
+}
+
+bool ScopedTempDirNoWow64::CreateUniqueSystem32TempDir() {
+  ScopedDisableWow64Redirection disable_wow64_redirection;
+  base::FilePath system_path;
+  if (!base::PathService::Get(base::DIR_SYSTEM, &system_path)) {
+    PLOG(ERROR) << "Unable to get system32 path";
+    return false;
+  }
+  // Note that on 32-bit Windows this check will always succeed because
+  // GetWow64RedirectedSystemPath returns an empty string. This is correct
+  // because Wow64 redirection isn't supported on 32-bit Windows, so the system
+  // path is guaranteed not to be redirected.
+  DCHECK(system_path != GetWow64RedirectedSystemPath());
+  return CreateUniqueTempDirUnderPath(system_path);
+}
+
+bool ScopedTempDirNoWow64::CreateEmptyFileInUniqueSystem32TempDir(
+    const base::string16& file_name) {
+  if (!CreateUniqueSystem32TempDir())
+    return false;
+  ScopedDisableWow64Redirection disable_wow64_redirection;
+  return CreateEmptyFile(GetPath().Append(file_name));
+}
+
+std::unique_ptr<base::WaitableEvent> CreateInheritableEvent(
+    base::WaitableEvent::ResetPolicy reset_policy,
+    base::WaitableEvent::InitialState initial_state) {
+  SECURITY_ATTRIBUTES attributes = {sizeof(SECURITY_ATTRIBUTES)};
+  attributes.bInheritHandle = true;
+
+  HANDLE handle = ::CreateEvent(
+      &attributes, reset_policy == base::WaitableEvent::ResetPolicy::MANUAL,
+      initial_state == base::WaitableEvent::InitialState::SIGNALED, nullptr);
+  if (handle == nullptr || handle == INVALID_HANDLE_VALUE) {
+    PLOG(ERROR) << "Could not create inheritable event";
+    return std::unique_ptr<base::WaitableEvent>();
+  }
+  base::win::ScopedHandle event_handle(handle);
+  return std::make_unique<base::WaitableEvent>(std::move(event_handle));
+}
+
+bool CheckTestPrivileges() {
+  // Check for administrator privileges, unless running in the sandbox.
+  const bool is_sandboxed_process =
+      (sandbox::SandboxFactory::GetTargetServices() != nullptr);
+  if (!is_sandboxed_process && !chrome_cleaner::HasAdminRights()) {
+    LOG(ERROR) << "Some Chrome Cleanup tests need administrator privileges.";
+    return false;
+  }
+
+  // All programs run under the msys git shell have debug privileges (!), which
+  // breaks the assumptions of some of the tests. So drop that privilege unless
+  // actually running under a debugger.
+  if (!::IsDebuggerPresent() &&
+      !chrome_cleaner::ReleaseDebugRightsPrivileges()) {
+    PLOG(ERROR) << "Failed to release debug privileges";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_util.h b/chrome/chrome_cleaner/test/test_util.h
new file mode 100644
index 0000000..c0cd0139
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_util.h
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
+#define CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/process/process.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_command_line.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_handle.h"
+#include "chrome/chrome_cleaner/os/task_scheduler.h"
+#include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h"
+#include "chrome/chrome_cleaner/pup_data/pup_data.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace chrome_cleaner {
+
+// Setup all configs required by tests (like disabling path caching). This
+// should be done in the main function of the test binary, not by individual
+// tests.
+//
+// Returns false if setup fails. Tests shouldn't be run if the setup fails.
+bool SetupTestConfigs();
+
+// Sets up all test configs, as SetupTestConfigs, using the given list of
+// |catalogs| instead of TestUwSCatalog.
+bool SetupTestConfigsWithCatalogs(const PUPData::UwSCatalogs& catalogs);
+
+// While this class is in scope, Rebooter::IsPostReboot will return true.
+class ScopedIsPostReboot {
+ public:
+  ScopedIsPostReboot();
+
+ private:
+  base::test::ScopedCommandLine scoped_command_line_;
+};
+
+class LoggingOverride {
+ public:
+  LoggingOverride();
+  ~LoggingOverride();
+
+  // Intercepts all log messages.
+  static bool LogMessageHandler(int severity,
+                                const char* file,
+                                int line,
+                                size_t message_start,
+                                const std::string& str) {
+    DCHECK(active_logging_messages_);
+    active_logging_messages_->push_back(str);
+    return false;
+  }
+
+  // Returns true if one of the messages contains |sub_string|.
+  bool LoggingMessagesContain(const std::string& sub_string);
+
+  // Returns true if one of the messages contains both |sub_string| and
+  // |sub_string2|.
+  bool LoggingMessagesContain(const std::string& sub_string1,
+                              const std::string& sub_string2);
+
+  // Remove all the log messages.
+  void FlushMessages() { logging_messages_.clear(); }
+
+  std::vector<std::string> logging_messages_;
+  static std::vector<std::string>* active_logging_messages_;
+};
+
+// Validate that the run once on restart registry value contains the given
+// |sub_string|.
+bool RunOnceCommandLineContains(const base::string16& product_shortname,
+                                const wchar_t* sub_string);
+
+// Validate that the run once on restart switch-containing registry value
+// contains the given |sub_string|.
+bool RunOnceOverrideCommandLineContains(const std::string& cleanup_id,
+                                        const wchar_t* sub_string);
+
+// Register a task with the given task scheduler. If the task is successfully
+// added, |task_info| will contain all the information about the task.
+// Callers are responsible for deleting the test task.
+bool RegisterTestTask(TaskScheduler* task_scheduler,
+                      TaskScheduler::TaskInfo* task_info);
+
+// Append switches to the command line that is used to run cleaner or reporter
+// in tests. Switches will disable logs upload, profile reset and other side
+// effects.
+void AppendTestSwitches(base::CommandLine* command_line);
+
+// Expect the |expected_path| to be found in expanded disk footprint of |pup|.
+void ExpectDiskFootprint(const PUPData::PUP& pup,
+                         const base::FilePath& expected_path);
+
+// Expect the scheduled task footprint to be found in |pup|.
+void ExpectScheduledTaskFootprint(const PUPData::PUP& pup,
+                                  const wchar_t* task_name);
+
+// This function is the 8 bits version of String16ContainsCaseInsensitive in
+// chrome_cleaner/string_util. Since it's only used in tests, we decided not to
+// move it to the main lib.
+bool StringContainsCaseInsensitive(const std::string& value,
+                                   const std::string& substring);
+
+// Expect two FilePathSets to be equal. Log files that are matched in excess
+// or expected files that are missing.
+void ExpectEqualFilePathSets(const FilePathSet& matched_files,
+                             const FilePathSet& expected_files);
+
+// Returns the path that base::DIR_SYSTEM is transparently redirected to under
+// Wow64. Note that on 32-bit Windows this will always return the empty string
+// because base::DIR_SYSTEM is not redirected.
+base::FilePath GetWow64RedirectedSystemPath();
+
+// Returns the path to a sample DLL file that can be used in tests.
+base::FilePath GetSampleDLLPath();
+
+// Returns the path to a signed sample DLL file that can be used in tests.
+base::FilePath GetSignedSampleDLLPath();
+
+// A ScopedTempDir with the ability to create and delete subdirs of
+// c:\windows\system32, which are Wow64-redirected by default. This turns off
+// Wow64 redirection so the subdir is created in the real c:\windows\system32
+// even in binaries that would normally be redirected to c:\windows\SysWOW64.
+class ScopedTempDirNoWow64 : protected base::ScopedTempDir {
+ public:
+  ScopedTempDirNoWow64();
+  ~ScopedTempDirNoWow64();
+
+  // Creates a unique subdirectory under system32, bypassing Wow64 redirection,
+  // and takes ownership of it.
+  bool CreateUniqueSystem32TempDir() WARN_UNUSED_RESULT;
+
+  // Convenience function to call CreateUniqueSystem32TempDir and create an
+  // empty file with the given |file_name| in the resulting directory.
+  bool CreateEmptyFileInUniqueSystem32TempDir(const base::string16& file_name)
+      WARN_UNUSED_RESULT;
+
+  using base::ScopedTempDir::Delete;
+  using base::ScopedTempDir::GetPath;
+  using base::ScopedTempDir::IsValid;
+  using base::ScopedTempDir::Take;
+
+  // Do not give access to CreateUniqueTempDir, CreateUniqueTempDirUnderPath,
+  // or Set because they can set the temp dir path to a non-Wow64-redirected
+  // directory.
+};
+
+std::unique_ptr<base::WaitableEvent> CreateInheritableEvent(
+    base::WaitableEvent::ResetPolicy reset_policy,
+    base::WaitableEvent::InitialState initial_state);
+
+// Check that the test has administrator privileges, but not debug privileges.
+// This function drops unneeded privileges if possible, but won't try to raise
+// privileges. Returns false if the privileges could not be made correct.
+bool CheckTestPrivileges();
+
+// Accepts PUPData::PUP parameters with id equals to |expected_id|.
+MATCHER_P(PupHasId, expected_id, "") {
+  return arg->signature().id == expected_id;
+}
+
+// Accepts PUPData::PUP parameters with |size| expanded disk footprints.
+MATCHER_P(PupHasFileListSize, size, "") {
+  return arg->expanded_disk_footprints.size() == static_cast<size_t>(size);
+}
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
diff --git a/chrome/chrome_cleaner/test/test_util_unittest.cc b/chrome/chrome_cleaner/test/test_util_unittest.cc
new file mode 100644
index 0000000..b893c47cd
--- /dev/null
+++ b/chrome/chrome_cleaner/test/test_util_unittest.cc
@@ -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.
+
+#include "chrome/chrome_cleaner/test/test_util.h"
+
+#include "chrome/chrome_cleaner/os/disk_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+// The following include is needed to use EXPECT_NONFATAL_FAILURE.
+#include "testing/gtest/include/gtest/gtest-spi.h"
+
+namespace chrome_cleaner {
+
+namespace {
+const wchar_t kFileName1[] = L"test_path1";
+const wchar_t kFileName2[] = L"test_path2";
+
+}  // namespace
+
+TEST(TestUtilTest, ExpectEqualFilePathSets) {
+  // Messages are logged to a vector for testing.
+  LoggingOverride logger;
+  FilePathSet matched_files;
+  FilePathSet expected_files;
+
+  matched_files.Insert(base::FilePath(kFileName1));
+  EXPECT_NONFATAL_FAILURE(
+      ExpectEqualFilePathSets(matched_files, expected_files), "");
+  EXPECT_TRUE(logger.LoggingMessagesContain(
+      "Unexpected file in matched footprints: 'test_path1'"));
+
+  logger.FlushMessages();
+  expected_files.Insert(base::FilePath(kFileName1));
+  ExpectEqualFilePathSets(matched_files, expected_files);
+
+  logger.FlushMessages();
+  expected_files.Insert(base::FilePath(kFileName2));
+  EXPECT_NONFATAL_FAILURE(
+      ExpectEqualFilePathSets(matched_files, expected_files), "");
+  EXPECT_TRUE(logger.LoggingMessagesContain(
+      "Missing expected footprint: 'test_path2'"));
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 93a2a77d..ebded7c8 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -425,25 +425,30 @@
 };
 const size_t kNumberOfChromeHostURLs = arraysize(kChromeHostURLs);
 
-const char* const kChromeDebugURLs[] = {content::kChromeUIBadCastCrashURL,
-                                        content::kChromeUIBrowserCrashURL,
-                                        content::kChromeUICrashURL,
-                                        content::kChromeUIDumpURL,
-                                        content::kChromeUIKillURL,
-                                        content::kChromeUIHangURL,
-                                        content::kChromeUIShorthangURL,
-                                        content::kChromeUIGpuCleanURL,
-                                        content::kChromeUIGpuCrashURL,
-                                        content::kChromeUIGpuHangURL,
-                                        content::kChromeUIMemoryExhaustURL,
-                                        content::kChromeUIPpapiFlashCrashURL,
-                                        content::kChromeUIPpapiFlashHangURL,
-#if defined(OS_ANDROID)
-                                        content::kChromeUIGpuJavaCrashURL,
-                                        kChromeUIJavaCrashURL,
+const char* const kChromeDebugURLs[] = {
+    content::kChromeUIBadCastCrashURL,
+    content::kChromeUIBrowserCrashURL,
+    content::kChromeUICrashURL,
+    content::kChromeUIDumpURL,
+    content::kChromeUIKillURL,
+    content::kChromeUIHangURL,
+    content::kChromeUIShorthangURL,
+    content::kChromeUIGpuCleanURL,
+    content::kChromeUIGpuCrashURL,
+    content::kChromeUIGpuHangURL,
+    content::kChromeUIMemoryExhaustURL,
+    content::kChromeUIPpapiFlashCrashURL,
+    content::kChromeUIPpapiFlashHangURL,
+#if defined(OS_WIN)
+    content::kChromeUIBrowserHeapCorruptionURL,
+    content::kChromeUIHeapCorruptionCrashURL,
 #endif
-                                        kChromeUIQuitURL,
-                                        kChromeUIRestartURL};
+#if defined(OS_ANDROID)
+    content::kChromeUIGpuJavaCrashURL,
+    kChromeUIJavaCrashURL,
+#endif
+    kChromeUIQuitURL,
+    kChromeUIRestartURL};
 const size_t kNumberOfChromeDebugURLs = arraysize(kChromeDebugURLs);
 
 }  // namespace chrome
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d35b7f9..bb474de 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1605,6 +1605,7 @@
         "../browser/chromeos/login/bluetooth_host_pairing_browsertest.cc",
         "../browser/chromeos/login/crash_restore_browsertest.cc",
         "../browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc",
+        "../browser/chromeos/login/demo_mode/demo_session_browsertest.cc",
         "../browser/chromeos/login/demo_mode/demo_setup_test_utils.h",
         "../browser/chromeos/login/demo_setup_browsertest.cc",
         "../browser/chromeos/login/enable_debugging_browsertest.cc",
@@ -1644,9 +1645,9 @@
         "../browser/chromeos/login/screens/mock_eula_screen.h",
         "../browser/chromeos/login/screens/mock_wrong_hwid_screen.cc",
         "../browser/chromeos/login/screens/mock_wrong_hwid_screen.h",
+        "../browser/chromeos/login/screens/network_screen_browsertest.cc",
         "../browser/chromeos/login/screens/update_screen_browsertest.cc",
         "../browser/chromeos/login/screens/user_selection_screen_browsertest.cc",
-        "../browser/chromeos/login/screens/welcome_screen_browsertest.cc",
         "../browser/chromeos/login/session/chrome_session_manager_browsertest.cc",
         "../browser/chromeos/login/session_login_browsertest.cc",
         "../browser/chromeos/login/signin/device_id_browsertest.cc",
diff --git a/chrome/test/data/media/picture-in-picture/window-size.html b/chrome/test/data/media/picture-in-picture/window-size.html
index 4dbb071..2f7a116 100644
--- a/chrome/test/data/media/picture-in-picture/window-size.html
+++ b/chrome/test/data/media/picture-in-picture/window-size.html
@@ -73,10 +73,10 @@
   }
 
   function changeVideoSrc() {
-    video.addEventListener('loadedmetadata', function() {
-      window.domAutomationController.send(true);
-    }, { once: true });
     video.src = video.src;
+    video.play()
+    .then(_ => { window.domAutomationController.send(true); })
+    .catch(e => { window.domAutomationController.send(false); });
   }
 </script>
 </html>
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index 2a69925a..6c48cea 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -914,7 +914,14 @@
   return incognito_browser_;
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest, Basic) {
+// Test is flaky on Linux. (https://crbug.com/853167)
+#if defined(OS_LINUX)
+#define MAYBE_Basic DISABLED_Basic
+#else
+#define MAYBE_Basic Basic
+#endif
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest,
+                       MAYBE_Basic) {
   RunBasicTest();
 }
 
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index e7c98b2..8b0d898 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -146,7 +146,8 @@
                  const std::string& path_to_onc) {
     std::unique_ptr<base::DictionaryValue> policy =
         path_to_onc.empty()
-            ? onc::ReadDictionaryFromJson(onc::kEmptyUnencryptedConfiguration)
+            ? base::DictionaryValue::From(onc::ReadDictionaryFromJson(
+                  onc::kEmptyUnencryptedConfiguration))
             : test_utils::ReadTestDictionary(path_to_onc);
 
     base::ListValue validated_network_configs;
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index 328707382..258fa5b1 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -162,14 +162,11 @@
     if (proxy_config_str.empty())
       return true;
 
-    std::unique_ptr<base::DictionaryValue> proxy_config_dict(
+    std::unique_ptr<base::Value> proxy_config_dict(
         onc::ReadDictionaryFromJson(proxy_config_str));
     if (proxy_config_dict) {
-      // Warning: The DictionaryValue returned from
-      // ReadDictionaryFromJson/JSONParser is an optimized derived class that
-      // doesn't allow releasing ownership of nested values. A Swap in the wrong
-      // order leads to memory access errors.
-      proxy_config_.MergeDictionary(proxy_config_dict.get());
+      proxy_config_.MergeDictionary(
+          base::DictionaryValue::From(std::move(proxy_config_dict)).get());
     } else {
       NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
     }
diff --git a/chromeos/network/network_state_test.cc b/chromeos/network/network_state_test.cc
index 15a3b67..a65cd93 100644
--- a/chromeos/network/network_state_test.cc
+++ b/chromeos/network/network_state_test.cc
@@ -62,7 +62,8 @@
   last_created_service_path_ = "";
 
   std::unique_ptr<base::DictionaryValue> shill_json_dict =
-      onc::ReadDictionaryFromJson(shill_json_string);
+      base::DictionaryValue::From(
+          onc::ReadDictionaryFromJson(shill_json_string));
   if (!shill_json_dict) {
     LOG(ERROR) << "Error parsing json: " << shill_json_string;
     return last_created_service_path_;
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc
index f9baff2..d8c0a535 100644
--- a/chromeos/network/onc/onc_translator_shill_to_onc.cc
+++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -623,10 +623,10 @@
   if (shill_dictionary_->GetStringWithoutPathExpansion(
           shill::kProxyConfigProperty, &proxy_config_str) &&
       !proxy_config_str.empty()) {
-    std::unique_ptr<base::DictionaryValue> proxy_config_value(
+    std::unique_ptr<base::Value> proxy_config_value(
         ReadDictionaryFromJson(proxy_config_str));
     if (proxy_config_value) {
-      std::unique_ptr<base::DictionaryValue> proxy_settings =
+      std::unique_ptr<base::Value> proxy_settings =
           ConvertProxyConfigToOncProxySettings(std::move(proxy_config_value));
       if (proxy_settings) {
         onc_object_->SetWithoutPathExpansion(
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 273a9ad..6aa6ee3 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -167,13 +167,9 @@
 }
 
 // Fills HexSSID fields in all entries in the |network_configs| list.
-void FillInHexSSIDFieldsInNetworks(base::ListValue* network_configs) {
-  for (auto& entry : *network_configs) {
-    base::DictionaryValue* network = nullptr;
-    entry.GetAsDictionary(&network);
-    DCHECK(network);
-    FillInHexSSIDFieldsInOncObject(kNetworkConfigurationSignature, network);
-  }
+void FillInHexSSIDFieldsInNetworks(base::Value* network_configs) {
+  for (auto& network : network_configs->GetList())
+    FillInHexSSIDFieldsInOncObject(kNetworkConfigurationSignature, &network);
 }
 
 // Given a GUID->PEM certificate mapping |certs_by_guid|, looks up the PEM
@@ -626,30 +622,45 @@
       ->GetGlobalConfigFromPolicy(username_hash);
 }
 
+bool GetStringFromDictionary(const base::Value& dict,
+                             const char* key,
+                             std::string* result) {
+  const base::Value* value = dict.FindKey(key);
+  if (!value || !value->is_string())
+    return false;
+  *result = value->GetString();
+  return true;
+}
+
+bool GetIntFromDictionary(const base::Value& dict,
+                          const char* key,
+                          int* result) {
+  const base::Value* value = dict.FindKey(key);
+  if (!value || !value->is_int())
+    return false;
+  *result = value->GetInt();
+  return true;
+}
+
 }  // namespace
 
 const char kEmptyUnencryptedConfiguration[] =
     "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[],"
     "\"Certificates\":[]}";
 
-std::unique_ptr<base::DictionaryValue> ReadDictionaryFromJson(
-    const std::string& json) {
+std::unique_ptr<base::Value> ReadDictionaryFromJson(const std::string& json) {
   std::string error;
   std::unique_ptr<base::Value> root = base::JSONReader::ReadAndReturnError(
       json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error);
-
-  base::DictionaryValue* dict_ptr = nullptr;
-  if (!root || !root->GetAsDictionary(&dict_ptr)) {
+  if (!root || !root->is_dict()) {
     NET_LOG(ERROR) << "Invalid JSON Dictionary: " << error;
     return nullptr;
   }
-  ignore_result(root.release());
-  return base::WrapUnique(dict_ptr);
+  return root;
 }
 
-std::unique_ptr<base::DictionaryValue> Decrypt(
-    const std::string& passphrase,
-    const base::DictionaryValue& root) {
+std::unique_ptr<base::Value> Decrypt(const std::string& passphrase,
+                                     const base::Value& root) {
   const int kKeySizeInBits = 256;
   const int kMaxIterationCount = 500000;
   std::string onc_type;
@@ -662,15 +673,15 @@
   int iterations;
   std::string ciphertext;
 
-  if (!root.GetString(encrypted::kCiphertext, &ciphertext) ||
-      !root.GetString(encrypted::kCipher, &cipher) ||
-      !root.GetString(encrypted::kHMAC, &hmac) ||
-      !root.GetString(encrypted::kHMACMethod, &hmac_method) ||
-      !root.GetString(encrypted::kIV, &initial_vector) ||
-      !root.GetInteger(encrypted::kIterations, &iterations) ||
-      !root.GetString(encrypted::kSalt, &salt) ||
-      !root.GetString(encrypted::kStretch, &stretch_method) ||
-      !root.GetString(toplevel_config::kType, &onc_type) ||
+  if (!GetStringFromDictionary(root, encrypted::kCiphertext, &ciphertext) ||
+      !GetStringFromDictionary(root, encrypted::kCipher, &cipher) ||
+      !GetStringFromDictionary(root, encrypted::kHMAC, &hmac) ||
+      !GetStringFromDictionary(root, encrypted::kHMACMethod, &hmac_method) ||
+      !GetStringFromDictionary(root, encrypted::kIV, &initial_vector) ||
+      !GetIntFromDictionary(root, encrypted::kIterations, &iterations) ||
+      !GetStringFromDictionary(root, encrypted::kSalt, &salt) ||
+      !GetStringFromDictionary(root, encrypted::kStretch, &stretch_method) ||
+      !GetStringFromDictionary(root, toplevel_config::kType, &onc_type) ||
       onc_type != toplevel_config::kEncryptedConfiguration) {
     NET_LOG(ERROR) << "Encrypted ONC malformed.";
     return nullptr;
@@ -737,8 +748,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<base::DictionaryValue> new_root =
-      ReadDictionaryFromJson(plaintext);
+  std::unique_ptr<base::Value> new_root = ReadDictionaryFromJson(plaintext);
   if (!new_root) {
     NET_LOG(ERROR) << "Property dictionary malformed.";
     return nullptr;
@@ -804,34 +814,34 @@
 }
 
 void FillInHexSSIDFieldsInOncObject(const OncValueSignature& signature,
-                                    base::DictionaryValue* onc_object) {
+                                    base::Value* onc_object) {
+  DCHECK(onc_object->is_dict());
   if (&signature == &kWiFiSignature)
     FillInHexSSIDField(onc_object);
 
   // Recurse into nested objects.
-  for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
-       it.Advance()) {
-    base::DictionaryValue* inner_object = nullptr;
-    if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
+  for (auto it : onc_object->DictItems()) {
+    if (!it.second.is_dict())
       continue;
 
     const OncFieldSignature* field_signature =
-        GetFieldSignature(signature, it.key());
+        GetFieldSignature(signature, it.first);
     if (!field_signature)
       continue;
 
     FillInHexSSIDFieldsInOncObject(*field_signature->value_signature,
-                                   inner_object);
+                                   &it.second);
   }
 }
 
-void FillInHexSSIDField(base::DictionaryValue* wifi_fields) {
-  std::string ssid_string;
-  if (wifi_fields->HasKey(::onc::wifi::kHexSSID) ||
-      !wifi_fields->GetStringWithoutPathExpansion(::onc::wifi::kSSID,
-                                                  &ssid_string)) {
+void FillInHexSSIDField(base::Value* wifi_fields) {
+  if (wifi_fields->FindKey(::onc::wifi::kHexSSID))
     return;
-  }
+  base::Value* ssid =
+      wifi_fields->FindKeyOfType(::onc::wifi::kSSID, base::Value::Type::STRING);
+  if (!ssid)
+    return;
+  std::string ssid_string = ssid->GetString();
   if (ssid_string.empty()) {
     NET_LOG(ERROR) << "Found empty SSID field.";
     return;
@@ -890,8 +900,7 @@
   if (onc_blob.empty())
     return true;
 
-  std::unique_ptr<base::DictionaryValue> toplevel_onc =
-      ReadDictionaryFromJson(onc_blob);
+  std::unique_ptr<base::Value> toplevel_onc = ReadDictionaryFromJson(onc_blob);
   if (!toplevel_onc) {
     LOG(ERROR) << "ONC loaded from " << GetSourceAsString(onc_source)
                << " is not a valid JSON dictionary.";
@@ -900,9 +909,9 @@
 
   // Check and see if this is an encrypted ONC file. If so, decrypt it.
   std::string onc_type;
-  toplevel_onc->GetStringWithoutPathExpansion(toplevel_config::kType,
-                                              &onc_type);
-  if (onc_type == toplevel_config::kEncryptedConfiguration) {
+  if (GetStringFromDictionary(*toplevel_onc, toplevel_config::kType,
+                              &onc_type) &&
+      onc_type == toplevel_config::kEncryptedConfiguration) {
     toplevel_onc = Decrypt(passphrase, *toplevel_onc);
     if (!toplevel_onc) {
       LOG(ERROR) << "Couldn't decrypt the ONC from "
@@ -923,8 +932,10 @@
   validator.SetOncSource(onc_source);
 
   Validator::Result validation_result;
+  std::unique_ptr<base::DictionaryValue> toplevel_onc_dict =
+      base::DictionaryValue::From(std::move(toplevel_onc));
   toplevel_onc = validator.ValidateAndRepairObject(
-      &kToplevelConfigurationSignature, *toplevel_onc, &validation_result);
+      &kToplevelConfigurationSignature, *toplevel_onc_dict, &validation_result);
 
   if (from_policy) {
     UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation",
@@ -942,40 +953,49 @@
     return false;
   }
 
-  base::ListValue* validated_certs = nullptr;
-  if (certificates && toplevel_onc->GetListWithoutPathExpansion(
-                          toplevel_config::kCertificates, &validated_certs)) {
-    certificates->Swap(validated_certs);
+  if (certificates) {
+    base::Value* validated_certs = toplevel_onc->FindKeyOfType(
+        toplevel_config::kCertificates, base::Value::Type::LIST);
+    if (validated_certs)
+      certificates->GetList().swap(validated_certs->GetList());
   }
 
-  base::ListValue* validated_networks = nullptr;
   // Note that this processing is performed even if |network_configs| is
   // nullptr, because ResolveServerCertRefsInNetworks could affect the return
   // value of the function (which is supposed to aggregate validation issues in
   // all segments of the ONC blob).
-  if (toplevel_onc->GetListWithoutPathExpansion(
-          toplevel_config::kNetworkConfigurations, &validated_networks)) {
-    FillInHexSSIDFieldsInNetworks(validated_networks);
+  base::Value* validated_networks = toplevel_onc->FindKeyOfType(
+      toplevel_config::kNetworkConfigurations, base::Value::Type::LIST);
+  base::ListValue* validated_networks_list;
+  if (validated_networks &&
+      validated_networks->GetAsList(&validated_networks_list)) {
+    FillInHexSSIDFieldsInNetworks(validated_networks_list);
 
     CertPEMsByGUIDMap server_and_ca_certs =
         GetServerAndCACertsByGUID(*certificates);
 
     if (!ResolveServerCertRefsInNetworks(server_and_ca_certs,
-                                         validated_networks)) {
+                                         validated_networks_list)) {
       LOG(ERROR) << "Some certificate references in the ONC policy for source "
                  << GetSourceAsString(onc_source) << " could not be resolved.";
       success = false;
     }
 
     if (network_configs)
-      network_configs->Swap(validated_networks);
+      network_configs->Swap(validated_networks_list);
   }
 
-  base::DictionaryValue* validated_global_config = nullptr;
-  if (global_network_config && toplevel_onc->GetDictionaryWithoutPathExpansion(
-                                   toplevel_config::kGlobalNetworkConfiguration,
-                                   &validated_global_config)) {
-    global_network_config->Swap(validated_global_config);
+  if (global_network_config) {
+    base::Value* validated_global_config = toplevel_onc->FindKeyOfType(
+        toplevel_config::kGlobalNetworkConfiguration,
+        base::Value::Type::DICTIONARY);
+    if (validated_global_config) {
+      base::DictionaryValue* validated_global_config_dict = nullptr;
+      if (validated_global_config->GetAsDictionary(
+              &validated_global_config_dict)) {
+        global_network_config->Swap(validated_global_config_dict);
+      }
+    }
   }
 
   return success;
@@ -1086,15 +1106,15 @@
   return proxy_dict;
 }
 
-std::unique_ptr<base::DictionaryValue> ConvertProxyConfigToOncProxySettings(
-    std::unique_ptr<base::DictionaryValue> proxy_config_value) {
-  // Create a ProxyConfigDictionary from the DictionaryValue.
-  auto proxy_config =
-      std::make_unique<ProxyConfigDictionary>(std::move(proxy_config_value));
+std::unique_ptr<base::Value> ConvertProxyConfigToOncProxySettings(
+    std::unique_ptr<base::Value> proxy_config_value) {
+  // Create a ProxyConfigDictionary from the dictionary.
+  auto proxy_config = std::make_unique<ProxyConfigDictionary>(
+      base::DictionaryValue::From(std::move(proxy_config_value)));
 
   // Create the result DictionaryValue and populate it.
-  std::unique_ptr<base::DictionaryValue> proxy_settings(
-      new base::DictionaryValue);
+  auto proxy_settings =
+      std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
   ProxyPrefs::ProxyMode mode;
   if (!proxy_config->GetMode(&mode))
     return nullptr;
@@ -1118,35 +1138,35 @@
       break;
     }
     case ProxyPrefs::MODE_FIXED_SERVERS: {
-      proxy_settings->SetString(::onc::proxy::kType, ::onc::proxy::kManual);
-      std::unique_ptr<base::DictionaryValue> manual(new base::DictionaryValue);
+      proxy_settings->SetKey(::onc::proxy::kType,
+                             base::Value(::onc::proxy::kManual));
+      base::DictionaryValue manual;
       std::string proxy_rules_string;
       if (proxy_config->GetProxyServer(&proxy_rules_string)) {
         net::ProxyConfig::ProxyRules proxy_rules;
         proxy_rules.ParseFromString(proxy_rules_string);
         SetProxyForScheme(proxy_rules, url::kFtpScheme, ::onc::proxy::kFtp,
-                          manual.get());
+                          &manual);
         SetProxyForScheme(proxy_rules, url::kHttpScheme, ::onc::proxy::kHttp,
-                          manual.get());
+                          &manual);
         SetProxyForScheme(proxy_rules, url::kHttpsScheme, ::onc::proxy::kHttps,
-                          manual.get());
+                          &manual);
         SetProxyForScheme(proxy_rules, kSocksScheme, ::onc::proxy::kSocks,
-                          manual.get());
+                          &manual);
       }
-      proxy_settings->SetWithoutPathExpansion(::onc::proxy::kManual,
-                                              std::move(manual));
+      proxy_settings->SetKey(::onc::proxy::kManual, std::move(manual));
 
       // Convert the 'bypass_list' string into dictionary entries.
       std::string bypass_rules_string;
       if (proxy_config->GetBypassList(&bypass_rules_string)) {
         net::ProxyBypassRules bypass_rules;
         bypass_rules.ParseFromString(bypass_rules_string);
-        std::unique_ptr<base::ListValue> exclude_domains(new base::ListValue);
+        base::ListValue exclude_domains;
         for (const auto& rule : bypass_rules.rules())
-          exclude_domains->AppendString(rule->ToString());
-        if (!exclude_domains->empty()) {
-          proxy_settings->SetWithoutPathExpansion(::onc::proxy::kExcludeDomains,
-                                                  std::move(exclude_domains));
+          exclude_domains.AppendString(rule->ToString());
+        if (!exclude_domains.empty()) {
+          proxy_settings->SetKey(::onc::proxy::kExcludeDomains,
+                                 std::move(exclude_domains));
         }
       }
       break;
diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h
index 0c4e46f0..0d0cec4 100644
--- a/chromeos/network/onc/onc_utils.h
+++ b/chromeos/network/onc/onc_utils.h
@@ -43,17 +43,17 @@
 typedef std::map<std::string, std::string> CertPEMsByGUIDMap;
 
 // Parses |json| according to the JSON format. If |json| is a JSON formatted
-// dictionary, the function returns the dictionary as a DictionaryValue.
-// Otherwise returns NULL.
-CHROMEOS_EXPORT std::unique_ptr<base::DictionaryValue> ReadDictionaryFromJson(
+// dictionary, the function returns the dictionary value, otherwise returns
+// null.
+CHROMEOS_EXPORT std::unique_ptr<base::Value> ReadDictionaryFromJson(
     const std::string& json);
 
 // Decrypts the given EncryptedConfiguration |onc| (see the ONC specification)
 // using |passphrase|. The resulting UnencryptedConfiguration is returned. If an
-// error occurs, returns NULL.
-CHROMEOS_EXPORT std::unique_ptr<base::DictionaryValue> Decrypt(
+// error occurs, returns null.
+CHROMEOS_EXPORT std::unique_ptr<base::Value> Decrypt(
     const std::string& passphrase,
-    const base::DictionaryValue& onc);
+    const base::Value& onc);
 
 // For logging only: strings not user facing.
 CHROMEOS_EXPORT std::string GetSourceAsString(::onc::ONCSource source);
@@ -77,12 +77,12 @@
 // specification. The object of |onc_object| is modified in place.
 CHROMEOS_EXPORT void FillInHexSSIDFieldsInOncObject(
     const OncValueSignature& signature,
-    base::DictionaryValue* onc_object);
+    base::Value* onc_object);
 
 // If the SSID field is set, but HexSSID is not, converts the contents of the
 // SSID field to UTF-8 encoding, creates the hex representation and assigns the
 // result to HexSSID.
-CHROMEOS_EXPORT void FillInHexSSIDField(base::DictionaryValue* wifi_fields);
+CHROMEOS_EXPORT void FillInHexSSIDField(base::Value* wifi_fields);
 
 // Creates a copy of |onc_object| with all values of sensitive fields replaced
 // by |mask|. To find sensitive fields, signature and field name are checked
@@ -146,9 +146,9 @@
 
 // Translates |proxy_config_value|, which must be a valid ProxyConfig dictionary
 // (see proxy_config_dictionary.h) to an ONC ProxySettings dictionary.
-CHROMEOS_EXPORT std::unique_ptr<base::DictionaryValue>
+CHROMEOS_EXPORT std::unique_ptr<base::Value>
 ConvertProxyConfigToOncProxySettings(
-    std::unique_ptr<base::DictionaryValue> proxy_config_value);
+    std::unique_ptr<base::Value> proxy_config_value);
 
 // Replaces user-specific string placeholders in |network_configs|, which must
 // be a list of ONC NetworkConfigurations. Currently only user name placeholders
diff --git a/chromeos/network/onc/onc_utils_unittest.cc b/chromeos/network/onc/onc_utils_unittest.cc
index a65da7cf..2764fd6 100644
--- a/chromeos/network/onc/onc_utils_unittest.cc
+++ b/chromeos/network/onc/onc_utils_unittest.cc
@@ -44,37 +44,37 @@
 namespace onc {
 
 TEST(ONCDecrypterTest, BrokenEncryptionIterations) {
-  std::unique_ptr<base::DictionaryValue> encrypted_onc =
+  std::unique_ptr<base::Value> encrypted_onc =
       test_utils::ReadTestDictionary("broken-encrypted-iterations.onc");
 
-  std::unique_ptr<base::DictionaryValue> decrypted_onc =
+  std::unique_ptr<base::Value> decrypted_onc =
       Decrypt("test0000", *encrypted_onc);
 
-  EXPECT_EQ(NULL, decrypted_onc.get());
+  EXPECT_EQ(nullptr, decrypted_onc.get());
 }
 
 TEST(ONCDecrypterTest, BrokenEncryptionZeroIterations) {
-  std::unique_ptr<base::DictionaryValue> encrypted_onc =
+  std::unique_ptr<base::Value> encrypted_onc =
       test_utils::ReadTestDictionary("broken-encrypted-zero-iterations.onc");
 
   std::string error;
-  std::unique_ptr<base::DictionaryValue> decrypted_onc =
+  std::unique_ptr<base::Value> decrypted_onc =
       Decrypt("test0000", *encrypted_onc);
 
-  EXPECT_EQ(NULL, decrypted_onc.get());
+  EXPECT_EQ(nullptr, decrypted_onc.get());
 }
 
 TEST(ONCDecrypterTest, LoadEncryptedOnc) {
-  std::unique_ptr<base::DictionaryValue> encrypted_onc =
+  std::unique_ptr<base::Value> encrypted_onc =
       test_utils::ReadTestDictionary("encrypted.onc");
-  std::unique_ptr<base::DictionaryValue> expected_decrypted_onc =
+  std::unique_ptr<base::Value> expected_decrypted_onc =
       test_utils::ReadTestDictionary("decrypted.onc");
 
   std::string error;
-  std::unique_ptr<base::DictionaryValue> actual_decrypted_onc =
+  std::unique_ptr<base::Value> actual_decrypted_onc =
       Decrypt("test0000", *encrypted_onc);
 
-  base::DictionaryValue emptyDict;
+  base::Value emptyDict;
   EXPECT_TRUE(test_utils::Equals(expected_decrypted_onc.get(),
                                  actual_decrypted_onc.get()));
 }
@@ -216,8 +216,8 @@
     test_case->GetDictionary("ONC_ProxySettings", &onc_proxy_settings);
 
     std::unique_ptr<base::DictionaryValue> actual_proxy_settings =
-        ConvertProxyConfigToOncProxySettings(
-            shill_proxy_config->CreateDeepCopy());
+        base::DictionaryValue::From(ConvertProxyConfigToOncProxySettings(
+            shill_proxy_config->CreateDeepCopy()));
     EXPECT_TRUE(
         test_utils::Equals(onc_proxy_settings, actual_proxy_settings.get()));
   }
diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc
index 1cc113b8f..8432e48 100644
--- a/chromeos/network/onc/onc_validator_unittest.cc
+++ b/chromeos/network/onc/onc_validator_unittest.cc
@@ -28,7 +28,7 @@
   // validation is stored, so that expectations can be checked afterwards using
   // one of the Expect* functions below.
   void Validate(bool strict,
-                std::unique_ptr<base::DictionaryValue> onc_object,
+                std::unique_ptr<base::Value> onc_object,
                 const OncValueSignature* signature,
                 bool managed_onc,
                 ::onc::ONCSource onc_source) {
@@ -41,7 +41,7 @@
       validator.reset(new Validator(false, false, false, managed_onc));
     }
     validator->SetOncSource(onc_source);
-    original_object_ = std::move(onc_object);
+    original_object_ = base::DictionaryValue::From(std::move(onc_object));
     repaired_object_ = validator->ValidateAndRepairObject(signature,
                                                           *original_object_,
                                                           &validation_result_);
diff --git a/chromeos/network/shill_property_util.cc b/chromeos/network/shill_property_util.cc
index e24ee92..5005a2e 100644
--- a/chromeos/network/shill_property_util.cc
+++ b/chromeos/network/shill_property_util.cc
@@ -197,7 +197,7 @@
     return std::unique_ptr<NetworkUIData>();
   if (ui_data_str.empty())
     return std::make_unique<NetworkUIData>();
-  std::unique_ptr<base::DictionaryValue> ui_data_dict(
+  std::unique_ptr<base::Value> ui_data_dict(
       chromeos::onc::ReadDictionaryFromJson(ui_data_str));
   if (!ui_data_dict)
     return std::unique_ptr<NetworkUIData>();
diff --git a/components/arc/arc_features.cc b/components/arc/arc_features.cc
index bbe8f96..58639ae 100644
--- a/components/arc/arc_features.cc
+++ b/components/arc/arc_features.cc
@@ -19,7 +19,8 @@
 // Controls whether we should delete all ARC data before transitioning a user
 // from regular to child account.
 const base::Feature kCleanArcDataOnRegularToChildTransitionFeature{
-    "ArcCleanDataOnRegularToChildTransition", base::FEATURE_ENABLED_BY_DEFAULT};
+    "ArcCleanDataOnRegularToChildTransition",
+    base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Controls whether ARC handles child->regular account transition.
 const base::Feature kEnableChildToRegularTransitionFeature{
diff --git a/components/autofill/core/common/autofill_regex_constants.cc b/components/autofill/core/common/autofill_regex_constants.cc
index dcdb9c4..d861aa9e 100644
--- a/components/autofill/core/common/autofill_regex_constants.cc
+++ b/components/autofill/core/common/autofill_regex_constants.cc
@@ -160,14 +160,14 @@
 const char kNameOnCardContextualRe[] = "name";
 const char kCardNumberRe[] =
     "(add)?(?:card|cc|acct).?(?:number|#|no|num|field)"
-    "|(?<!telefon|haus)nummer"  // de-DE
-    "|credito|numero|número"    // es
-    "|numéro"                   // fr-FR
-    "|カード番号"               // ja-JP
-    "|Номер.*карты"             // ru
-    "|信用卡号|信用卡号码"      // zh-CN
-    "|信用卡卡號"               // zh-TW
-    "|카드";                    // ko-KR
+    "|(?<!telefon|haus)nummer"                             // de-DE
+    "|カード番号"                                          // ja-JP
+    "|Номер.*карты"                                        // ru
+    "|信用卡号|信用卡号码"                                 // zh-CN
+    "|信用卡卡號"                                          // zh-TW
+    "|카드"                                                // ko-KR
+    "|(numero|número|numéro)(?!.*(document|fono|phone))";  // es/pt/fr
+
 const char kCardCvcRe[] =
     "verification|card.?identification|security.?code|card.?code"
     "|security.?value"
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index d4fa4c3..ec55236d 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -76,11 +76,6 @@
       "//third_party/breakpad:client",
       "//third_party/crashpad/crashpad/snapshot",
     ]
-
-    # Clang's -mstackrealign doesn't work well with
-    # linux_syscall_support.h hand written asm syscalls.
-    # See https://crbug.com/556393
-    configs -= [ "//build/config/compiler:clang_stackrealign" ]
   }
 
   if (is_win) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 93063bb..dd49dcc 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -18,7 +18,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
-#include "build/build_config.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
 #include "components/data_reduction_proxy/core/browser/data_usage_store.h"
@@ -30,10 +29,6 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "net/base/mime_util.h"
 
-#if defined(OS_ANDROID)
-#include "base/android/application_status_listener.h"
-#endif
-
 namespace data_reduction_proxy {
 
 namespace {
@@ -1448,10 +1443,6 @@
                         content_type, data_used_kb);
   } else {
     bool is_app_foreground = true;
-#if defined(OS_ANDROID)
-    is_app_foreground = base::android::ApplicationStatusListener::GetState() ==
-                        base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES;
-#endif
     if (is_app_foreground) {
       AddToDictionaryPref(pref_service_,
                           prefs::kThisWeekServicesDownstreamForegroundKB,
diff --git a/components/download/database/BUILD.gn b/components/download/database/BUILD.gn
index 73d775e..946d154 100644
--- a/components/download/database/BUILD.gn
+++ b/components/download/database/BUILD.gn
@@ -9,6 +9,7 @@
 
 source_set("database") {
   sources = [
+    "download_db.cc",
     "download_db.h",
     "download_db_conversions.cc",
     "download_db_conversions.h",
diff --git a/components/download/database/download_db.cc b/components/download/database/download_db.cc
new file mode 100644
index 0000000..b54602f
--- /dev/null
+++ b/components/download/database/download_db.cc
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/database/download_db.h"
+
+#include "base/callback.h"
+#include "components/download/database/download_db_entry.h"
+
+namespace download {
+
+DownloadDB::DownloadDB() = default;
+
+DownloadDB::~DownloadDB() = default;
+
+void DownloadDB::Initialize(InitializeCallback callback) {
+  std::move(callback).Run(true);
+}
+
+void DownloadDB::AddOrReplace(const DownloadDBEntry& entry) {}
+
+void DownloadDB::AddOrReplaceEntries(
+    const std::vector<DownloadDBEntry>& entry) {}
+
+void DownloadDB::LoadEntries(LoadEntriesCallback callback) {
+  std::move(callback).Run(true,
+                          std::make_unique<std::vector<DownloadDBEntry>>());
+}
+
+void DownloadDB::Remove(const std::string& guid) {}
+
+}  // namespace download
diff --git a/components/download/database/download_db.h b/components/download/database/download_db.h
index 4400854ac..c77cf2e8 100644
--- a/components/download/database/download_db.h
+++ b/components/download/database/download_db.h
@@ -23,27 +23,23 @@
       std::unique_ptr<std::vector<DownloadDBEntry>> entries)>;
   using InitializeCallback = base::OnceCallback<void(bool success)>;
 
-  virtual ~DownloadDB() = default;
-
-  // Returns whether or not this object is initialized and can be interracted
-  // with.
-  virtual bool IsInitialized() = 0;
+  DownloadDB();
+  virtual ~DownloadDB();
 
   // Initializes this db asynchronously, callback will be run on completion.
-  virtual void Initialize(InitializeCallback callback) = 0;
+  virtual void Initialize(InitializeCallback callback);
 
   // Adds or updates |entry| in the storage.
-  virtual void AddOrReplace(const DownloadDBEntry& entry) = 0;
+  virtual void AddOrReplace(const DownloadDBEntry& entry);
 
   // Adds or updates multiple entries in the storage.
-  virtual void AddOrReplaceEntries(
-      const std::vector<DownloadDBEntry>& entry) = 0;
+  virtual void AddOrReplaceEntries(const std::vector<DownloadDBEntry>& entry);
 
   // Retrieves all entries with the given |download_namespace|.
-  virtual void LoadEntries(LoadEntriesCallback callback) = 0;
+  virtual void LoadEntries(LoadEntriesCallback callback);
 
   // Removes the Entry associated with |guid| from the storage.
-  virtual void Remove(const std::string& guid) = 0;
+  virtual void Remove(const std::string& guid);
 };
 
 }  // namespace download
diff --git a/components/download/database/download_db_impl.cc b/components/download/database/download_db_impl.cc
index f33b52a..6a03442 100644
--- a/components/download/database/download_db_impl.cc
+++ b/components/download/database/download_db_impl.cc
@@ -18,6 +18,8 @@
 
 namespace {
 
+const int kMaxNumInitializeAttempts = 3;
+
 const char kDatabaseClientName[] = "DownloadDB";
 using ProtoKeyVector = std::vector<std::string>;
 using ProtoEntryVector = std::vector<download_pb::DownloadDBEntry>;
@@ -58,6 +60,7 @@
       db_(std::move(db)),
       is_initialized_(false),
       download_namespace_(download_namespace),
+      num_initialize_attempts_(0),
       weak_factory_(this) {}
 
 DownloadDBImpl::~DownloadDBImpl() = default;
@@ -68,6 +71,7 @@
 
 void DownloadDBImpl::Initialize(InitializeCallback callback) {
   DCHECK(!IsInitialized());
+
   // These options reduce memory consumption.
   leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
   options.reuse_logs = false;
@@ -144,6 +148,10 @@
 
 void DownloadDBImpl::OnDatabaseInitialized(InitializeCallback callback,
                                            bool success) {
+  if (!success) {
+    DestroyAndReinitialize(std::move(callback));
+    return;
+  }
   is_initialized_ = success;
   std::move(callback).Run(success);
 }
@@ -155,7 +163,11 @@
     return;
   }
 
-  Initialize(std::move(callback));
+  num_initialize_attempts_++;
+  if (num_initialize_attempts_ >= kMaxNumInitializeAttempts)
+    std::move(callback).Run(false);
+  else
+    Initialize(std::move(callback));
 }
 
 void DownloadDBImpl::OnUpdateDone(bool success) {
diff --git a/components/download/database/download_db_impl.h b/components/download/database/download_db_impl.h
index fe1a07c2..6da126e4 100644
--- a/components/download/database/download_db_impl.h
+++ b/components/download/database/download_db_impl.h
@@ -33,7 +33,6 @@
   ~DownloadDBImpl() override;
 
   // DownloadDB implementation.
-  bool IsInitialized() override;
   void Initialize(InitializeCallback callback) override;
   void AddOrReplace(const DownloadDBEntry& entry) override;
   void AddOrReplaceEntries(
@@ -44,6 +43,8 @@
  private:
   friend class DownloadDBTest;
 
+  bool IsInitialized();
+
   void DestroyAndReinitialize(InitializeCallback callback);
 
   // Returns the key of the db entry.
@@ -80,6 +81,9 @@
   // Namespace of this db.
   DownloadNamespace download_namespace_;
 
+  // Number of initialize attempts.
+  int num_initialize_attempts_;
+
   base::WeakPtrFactory<DownloadDBImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadDBImpl);
diff --git a/components/download/database/download_db_impl_unittest.cc b/components/download/database/download_db_impl_unittest.cc
index 6c35db9..cd582a2 100644
--- a/components/download/database/download_db_impl_unittest.cc
+++ b/components/download/database/download_db_impl_unittest.cc
@@ -62,6 +62,8 @@
     loaded_entries->swap(*entries);
   }
 
+  bool IsInitialized() { return download_db_->IsInitialized(); }
+
   void PrepopulateSampleEntries() {
     DownloadDBEntry first = CreateDownloadDBEntry();
     DownloadDBEntry second = CreateDownloadDBEntry();
@@ -93,25 +95,25 @@
 
 TEST_F(DownloadDBTest, InitializeSucceeded) {
   CreateDatabase();
-  ASSERT_FALSE(download_db_->IsInitialized());
+  ASSERT_FALSE(IsInitialized());
 
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
 
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
   ASSERT_TRUE(init_success_);
 }
 
 TEST_F(DownloadDBTest, InitializeFailed) {
   CreateDatabase();
-  ASSERT_FALSE(download_db_->IsInitialized());
+  ASSERT_FALSE(IsInitialized());
 
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(false);
 
-  ASSERT_FALSE(download_db_->IsInitialized());
+  ASSERT_FALSE(IsInitialized());
   ASSERT_FALSE(init_success_);
 }
 
@@ -121,7 +123,7 @@
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
 
   std::vector<DownloadDBEntry> loaded_entries;
   download_db_->LoadEntries(base::BindOnce(
@@ -141,7 +143,7 @@
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
 
   DownloadDBEntry entry = CreateDownloadDBEntry();
   download_db_->AddOrReplace(entry);
@@ -172,7 +174,7 @@
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
 
   InProgressInfo in_progress_info;
   in_progress_info.current_path =
@@ -209,7 +211,7 @@
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
 
   download_db_->Remove(first.GetGuid());
   db_->UpdateCallback(true);
@@ -230,7 +232,7 @@
   download_db_->Initialize(
       base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
   db_->InitCallback(true);
-  ASSERT_TRUE(download_db_->IsInitialized());
+  ASSERT_TRUE(IsInitialized());
 
   std::vector<DownloadDBEntry> loaded_entries;
   download_db_->LoadEntries(base::BindOnce(
diff --git a/components/download/internal/common/BUILD.gn b/components/download/internal/common/BUILD.gn
index 5121397..0f957ee 100644
--- a/components/download/internal/common/BUILD.gn
+++ b/components/download/internal/common/BUILD.gn
@@ -33,6 +33,7 @@
     "download_task_runner.cc",
     "download_ukm_helper.cc",
     "download_url_loader_factory_getter.cc",
+    "download_url_loader_factory_getter_impl.cc",
     "download_utils.cc",
     "download_worker.cc",
     "download_worker.h",
diff --git a/components/download/internal/common/download_db_cache.cc b/components/download/internal/common/download_db_cache.cc
index b514e4e..4dd6d46 100644
--- a/components/download/internal/common/download_db_cache.cc
+++ b/components/download/internal/common/download_db_cache.cc
@@ -120,7 +120,9 @@
 DownloadDBCache::DownloadDBCache(std::unique_ptr<DownloadDB> download_db)
     : initialized_(false),
       download_db_(std::move(download_db)),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  DCHECK(download_db_);
+}
 
 DownloadDBCache::~DownloadDBCache() = default;
 
@@ -175,7 +177,7 @@
 void DownloadDBCache::RemoveEntry(const std::string& guid) {
   entries_.erase(guid);
   updated_guids_.erase(guid);
-  if (download_db_)
+  if (initialized_)
     download_db_->Remove(guid);
 }
 
@@ -188,15 +190,13 @@
     DCHECK(entry);
     entries.emplace_back(entry.value());
   }
-  download_db_->AddOrReplaceEntries(entries);
+  if (initialized_)
+    download_db_->AddOrReplaceEntries(entries);
 }
 
 void DownloadDBCache::OnDownloadUpdated(DownloadItem* download) {
   // TODO(crbug.com/778425): Properly handle fail/resume/retry for downloads
   // that are in the INTERRUPTED state for a long time.
-  if (!download_db_)
-    return;
-
   base::Optional<DownloadDBEntry> current = RetrieveEntry(download->GetGuid());
   bool fetch_error_body = GetFetchErrorBody(current);
   DownloadUrlParameters::RequestHeadersType request_header_type =
@@ -217,25 +217,22 @@
     download_db_->LoadEntries(
         base::BindOnce(&DownloadDBCache::OnDownloadDBEntriesLoaded,
                        weak_factory_.GetWeakPtr(), std::move(callback)));
+  } else {
+    OnDownloadDBEntriesLoaded(std::move(callback), false,
+                              std::make_unique<std::vector<DownloadDBEntry>>());
   }
-  // TODO(qinmin): Recreate the database if |success| is false.
-  // http://crbug.com/847661.
 }
 
 void DownloadDBCache::OnDownloadDBEntriesLoaded(
     InitializeCallback callback,
     bool success,
     std::unique_ptr<std::vector<DownloadDBEntry>> entries) {
-  if (success) {
-    initialized_ = true;
-    for (auto& entry : *entries) {
-      CleanUpInProgressEntry(entry);
-      entries_[entry.download_info->guid] = entry;
-    }
-    std::move(callback).Run(std::move(entries));
+  initialized_ = success;
+  for (auto& entry : *entries) {
+    CleanUpInProgressEntry(entry);
+    entries_[entry.download_info->guid] = entry;
   }
-  // TODO(qinmin): Recreate the database if |success| is false.
-  // http://crbug.com/847661.
+  std::move(callback).Run(std::move(entries));
 }
 
 void DownloadDBCache::SetTimerTaskRunnerForTesting(
diff --git a/content/browser/download/download_url_loader_factory_getter_impl.cc b/components/download/internal/common/download_url_loader_factory_getter_impl.cc
similarity index 84%
rename from content/browser/download/download_url_loader_factory_getter_impl.cc
rename to components/download/internal/common/download_url_loader_factory_getter_impl.cc
index e26386c..83c5b93 100644
--- a/content/browser/download/download_url_loader_factory_getter_impl.cc
+++ b/components/download/internal/common/download_url_loader_factory_getter_impl.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/download/download_url_loader_factory_getter_impl.h"
+#include "components/download/public/common/download_url_loader_factory_getter_impl.h"
 
-namespace content {
+namespace download {
 
 DownloadURLLoaderFactoryGetterImpl::DownloadURLLoaderFactoryGetterImpl(
     std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory)
@@ -22,4 +22,4 @@
   return url_loader_factory_;
 }
 
-}  // namespace content
+}  // namespace download
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc
index ca5a426..f8d8ba4 100644
--- a/components/download/internal/common/in_progress_download_manager.cc
+++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -279,9 +279,12 @@
           switches::kEnableDownloadDB)) {
     // TODO(qinmin): migrate all the data from InProgressCache into
     // |download_db_|.
-    download_db_cache_ =
-        std::make_unique<DownloadDBCache>(std::make_unique<DownloadDBImpl>(
-            DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD, metadata_cache_dir));
+    download_db_cache_ = std::make_unique<DownloadDBCache>(
+        metadata_cache_dir.empty()
+            ? std::make_unique<DownloadDB>()
+            : std::make_unique<DownloadDBImpl>(
+                  DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD,
+                  metadata_cache_dir));
     download_db_cache_->Initialize(base::BindOnce(
         &InProgressDownloadManager::OnInitialized, weak_factory_.GetWeakPtr()));
   } else {
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
index 5c8c8717..6d3b1e9 100644
--- a/components/download/public/common/BUILD.gn
+++ b/components/download/public/common/BUILD.gn
@@ -46,6 +46,7 @@
     "download_task_runner.h",
     "download_ukm_helper.h",
     "download_url_loader_factory_getter.h",
+    "download_url_loader_factory_getter_impl.h",
     "download_url_parameters.cc",
     "download_url_parameters.h",
     "download_utils.h",
diff --git a/content/browser/download/download_url_loader_factory_getter_impl.h b/components/download/public/common/download_url_loader_factory_getter_impl.h
similarity index 74%
rename from content/browser/download/download_url_loader_factory_getter_impl.h
rename to components/download/public/common/download_url_loader_factory_getter_impl.h
index d002dbb..dcfb250 100644
--- a/content/browser/download/download_url_loader_factory_getter_impl.h
+++ b/components/download/public/common/download_url_loader_factory_getter_impl.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
-#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
 
 #include "components/download/public/common/download_url_loader_factory_getter.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
-namespace content {
+namespace download {
 
 // Class for retrieving a fixed SharedURLLoaderFactory.
-class DownloadURLLoaderFactoryGetterImpl
-    : public download::DownloadURLLoaderFactoryGetter {
+class COMPONENTS_DOWNLOAD_EXPORT DownloadURLLoaderFactoryGetterImpl
+    : public DownloadURLLoaderFactoryGetter {
  public:
   explicit DownloadURLLoaderFactoryGetterImpl(
       std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory);
@@ -34,6 +34,6 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadURLLoaderFactoryGetterImpl);
 };
 
-}  // namespace content
+}  // namespace download
 
-#endif  // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
diff --git a/components/nux/show_promo_delegate.h b/components/nux/show_promo_delegate.h
index 3b69bd13..6b935566 100644
--- a/components/nux/show_promo_delegate.h
+++ b/components/nux/show_promo_delegate.h
@@ -5,17 +5,21 @@
 #ifndef COMPONENTS_NUX_SHOW_PROMO_DELEGATE_H_
 #define COMPONENTS_NUX_SHOW_PROMO_DELEGATE_H_
 
+#include <memory>
+
 namespace bookmarks {
 class BookmarkNode;
 }  // namespace bookmarks
 
 class ShowPromoDelegate {
  public:
+  virtual ~ShowPromoDelegate() = default;
+
   // Shows a promotional popup for the specified bookmark node.
   virtual void ShowForNode(const bookmarks::BookmarkNode* node) = 0;
 
- protected:
-  virtual ~ShowPromoDelegate() = default;
+  // Return an instance of the promo delegate.
+  static std::unique_ptr<ShowPromoDelegate> CreatePromoDelegate();
 };
 
 #endif  //  COMPONENTS_NUX_SHOW_PROMO_DELEGATE_H_
diff --git a/components/nux_google_apps/BUILD.gn b/components/nux_google_apps/BUILD.gn
index 723fb7d..d9187c1 100644
--- a/components/nux_google_apps/BUILD.gn
+++ b/components/nux_google_apps/BUILD.gn
@@ -9,8 +9,8 @@
     sources = [
       "constants.cc",
       "constants.h",
-      "webui.cc",
-      "webui.h",
+      "google_apps_handler.cc",
+      "google_apps_handler.h",
     ]
 
     public_deps = [
@@ -20,6 +20,8 @@
     ]
 
     deps = [
+      "//components/bookmarks/browser",
+      "//components/bookmarks/common",
       "//components/pref_registry",
       "//components/prefs",
       "//components/resources",
diff --git a/components/nux_google_apps/DEPS b/components/nux_google_apps/DEPS
index 1a6893c..c3d7d1a 100644
--- a/components/nux_google_apps/DEPS
+++ b/components/nux_google_apps/DEPS
@@ -1,5 +1,8 @@
 include_rules = [
+  "+components/bookmarks",
   "+components/grit",
+  "+components/prefs",
+  "+components/nux",
   "+components/strings/grit/components_strings.h",
   "+content/public/browser",
 ]
diff --git a/components/nux_google_apps/google_apps_handler.cc b/components/nux_google_apps/google_apps_handler.cc
new file mode 100644
index 0000000..d07cb26
--- /dev/null
+++ b/components/nux_google_apps/google_apps_handler.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/nux_google_apps/google_apps_handler.h"
+
+#include "base/bind.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/grit/components_resources.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/nux/show_promo_delegate.h"
+#include "components/nux_google_apps/constants.h"
+#include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+namespace nux_google_apps {
+
+// Strings in costants not translated because this is an experiment.
+// Translate before wide release.
+
+constexpr const char* kGoogleAppNames[] = {
+    "Gmail", "YouTube", "Maps", "Translate", "News", "Chrome Web Store",
+};
+
+constexpr const char* kGoogleAppUrls[] = {
+    "https://gmail.com",       "https://youtube.com",
+    "https://maps.google.com", "https://translate.google.com",
+    "https://news.google.com", "https://chrome.google.com/webstore",
+};
+
+static_assert(base::size(kGoogleAppNames) == base::size(kGoogleAppUrls),
+              "names and urls must match");
+
+constexpr const size_t kGoogleAppCount = 6;
+
+GoogleAppsHandler::GoogleAppsHandler(PrefService* prefs,
+                                     bookmarks::BookmarkModel* bookmark_model)
+    : prefs_(prefs), bookmark_model_(bookmark_model) {}
+
+GoogleAppsHandler::~GoogleAppsHandler() {}
+
+void GoogleAppsHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "addGoogleApps",
+      base::BindRepeating(&GoogleAppsHandler::HandleAddBookmarks,
+                          base::Unretained(this)));
+}
+
+void GoogleAppsHandler::HandleAddBookmarks(const base::ListValue* args) {
+  // Add bookmarks for all selected apps.
+  int bookmarkIndex = 0;
+  for (size_t i = 0; i < kGoogleAppCount; ++i) {
+    bool selected = false;
+    CHECK(args->GetBoolean(i, &selected));
+    if (selected) {
+      bookmark_model_->AddURL(
+          bookmark_model_->bookmark_bar_node(), bookmarkIndex++,
+          base::ASCIIToUTF16(kGoogleAppNames[i]), GURL(kGoogleAppUrls[i]));
+    }
+  }
+
+  // Enable bookmark bar.
+  prefs_->SetBoolean(bookmarks::prefs::kShowBookmarkBar, true);
+
+  // Wait to show bookmark bar.
+  // TODO(hcarmona): Any advice here would be helpful.
+
+  // Show bookmark bubble.
+  ShowPromoDelegate::CreatePromoDelegate()->ShowForNode(
+      bookmark_model_->bookmark_bar_node()->GetChild(0));
+}
+
+void GoogleAppsHandler::AddSources(content::WebUIDataSource* html_source) {
+  // Localized strings.
+  html_source->AddLocalizedString("noThanks", IDS_NO_THANKS);
+  html_source->AddLocalizedString("getStarted",
+                                  IDS_NUX_GOOGLE_APPS_GET_STARTED);
+  html_source->AddLocalizedString("nuxDescription",
+                                  IDS_NUX_GOOGLE_APPS_DESCRIPTION);
+
+  // Add required resources.
+  html_source->AddResourcePath("apps", IDR_NUX_GOOGLE_APPS_HTML);
+  html_source->AddResourcePath("apps/nux_google_apps.js",
+                               IDR_NUX_GOOGLE_APPS_JS);
+
+  html_source->AddResourcePath("apps/nux_google_apps_proxy.html",
+                               IDR_NUX_GOOGLE_APPS_PROXY_HTML);
+  html_source->AddResourcePath("apps/nux_google_apps_proxy.js",
+                               IDR_NUX_GOOGLE_APPS_PROXY_JS);
+
+  html_source->AddResourcePath("apps/apps_chooser.html",
+                               IDR_NUX_GOOGLE_APPS_CHOOSER_HTML);
+  html_source->AddResourcePath("apps/apps_chooser.js",
+                               IDR_NUX_GOOGLE_APPS_CHOOSER_JS);
+
+  // Add icons
+  html_source->AddResourcePath("apps/chrome_store_1x.png",
+                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X);
+  html_source->AddResourcePath("apps/chrome_store_2x.png",
+                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X);
+  html_source->AddResourcePath("apps/gmail_1x.png",
+                               IDR_NUX_GOOGLE_APPS_GMAIL_1X);
+  html_source->AddResourcePath("apps/gmail_2x.png",
+                               IDR_NUX_GOOGLE_APPS_GMAIL_2X);
+  html_source->AddResourcePath("apps/maps_1x.png", IDR_NUX_GOOGLE_APPS_MAPS_1X);
+  html_source->AddResourcePath("apps/maps_2x.png", IDR_NUX_GOOGLE_APPS_MAPS_2X);
+  html_source->AddResourcePath("apps/news_1x.png", IDR_NUX_GOOGLE_APPS_NEWS_1X);
+  html_source->AddResourcePath("apps/news_2x.png", IDR_NUX_GOOGLE_APPS_NEWS_2X);
+  html_source->AddResourcePath("apps/translate_1x.png",
+                               IDR_NUX_GOOGLE_APPS_TRANSLATE_1X);
+  html_source->AddResourcePath("apps/translate_2x.png",
+                               IDR_NUX_GOOGLE_APPS_TRANSLATE_2X);
+  html_source->AddResourcePath("apps/youtube_1x.png",
+                               IDR_NUX_GOOGLE_APPS_YOUTUBE_1X);
+  html_source->AddResourcePath("apps/youtube_2x.png",
+                               IDR_NUX_GOOGLE_APPS_YOUTUBE_2X);
+}
+
+}  // namespace nux_google_apps
\ No newline at end of file
diff --git a/components/nux_google_apps/google_apps_handler.h b/components/nux_google_apps/google_apps_handler.h
new file mode 100644
index 0000000..7b6245d
--- /dev/null
+++ b/components/nux_google_apps/google_apps_handler.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_NUX_GOOGLE_APPS_GOOGLE_APPS_HANDLER_H_
+#define COMPONENTS_NUX_GOOGLE_APPS_GOOGLE_APPS_HANDLER_H_
+
+#include "base/macros.h"
+#include "base/values.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+class PrefService;
+
+namespace bookmarks {
+class BookmarkModel;
+}  // namespace bookmarks
+
+namespace content {
+class WebUIDataSource;
+}  // namespace content
+
+namespace nux_google_apps {
+
+class GoogleAppsHandler : public content::WebUIMessageHandler {
+ public:
+  GoogleAppsHandler(PrefService* prefs,
+                    bookmarks::BookmarkModel* bookmark_model);
+  ~GoogleAppsHandler() override;
+
+  // WebUIMessageHandler:
+  void RegisterMessages() override;
+
+  // Callback for JS API that will add bookmarks.
+  void HandleAddBookmarks(const base::ListValue* args);
+
+  // Adds webui sources.
+  static void AddSources(content::WebUIDataSource* html_source);
+
+ private:
+  // Weak reference.
+  PrefService* prefs_;
+
+  // Weak reference.
+  bookmarks::BookmarkModel* bookmark_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(GoogleAppsHandler);
+};
+
+}  // namespace nux_google_apps
+
+#endif  // COMPONENTS_NUX_GOOGLE_APPS_GOOGLE_APPS_HANDLER_H_
diff --git a/components/nux_google_apps/resources/BUILD.gn b/components/nux_google_apps/resources/BUILD.gn
index aa232167..c2ce565 100644
--- a/components/nux_google_apps/resources/BUILD.gn
+++ b/components/nux_google_apps/resources/BUILD.gn
@@ -18,5 +18,10 @@
 js_library("nux_google_apps") {
   deps = [
     ":apps_chooser",
+    ":nux_google_apps_proxy",
   ]
 }
+
+js_library("nux_google_apps_proxy") {
+  deps = []
+}
diff --git a/components/nux_google_apps/resources/apps_chooser.js b/components/nux_google_apps/resources/apps_chooser.js
index cac520c..87c50fe 100644
--- a/components/nux_google_apps/resources/apps_chooser.js
+++ b/components/nux_google_apps/resources/apps_chooser.js
@@ -60,6 +60,20 @@
         ];
       },
     },
+
+    hasAppsSelected: {
+      type: Boolean,
+      notify: true,
+      value: true,
+    }
+  },
+
+  /**
+   * Returns an array of booleans for each selected app.
+   * @return {Array<boolean>}
+   */
+  getSelectedAppList() {
+    return this.appList.map(a => a.selected)
   },
 
   /**
@@ -69,5 +83,11 @@
    */
   onAppClick_: function(e) {
     e.model.set('item.selected', !e.model.item.selected);
+    this.hasAppsSelected = this.computeHasAppsSelected_();
+  },
+
+  /** @private {boolean} */
+  computeHasAppsSelected_: function() {
+    return this.appList.some(a => a.selected);
   },
 });
diff --git a/components/nux_google_apps/resources/nux_google_apps.html b/components/nux_google_apps/resources/nux_google_apps.html
index 74a77f0f..0dcd72f 100644
--- a/components/nux_google_apps/resources/nux_google_apps.html
+++ b/components/nux_google_apps/resources/nux_google_apps.html
@@ -7,6 +7,7 @@
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://welcome/apps/apps_chooser.html">
+<link rel="import" href="chrome://welcome/apps/nux_google_apps_proxy.html">
 
 <dom-module id="nux-google-apps">
   <template>
@@ -65,11 +66,15 @@
       <h1>$i18n{headerText}</h1>
       <div class="description">$i18n{nuxDescription}</div>
 
-      <apps-chooser></apps-chooser>
+      <apps-chooser id="appChooser" has-apps-selected="{{hasAppsSelected_}}">
+      </apps-chooser>
 
       <div class="button-bar">
-        <paper-button>$i18n{noThanks}</paper-button>
-        <paper-button class="action-button">$i18n{getStarted}</paper-button>
+        <paper-button on-click="onNoThanksClicked_">
+          $i18n{noThanks}
+        </paper-button>
+        <paper-button class="action-button" disabled$="[[!hasAppsSelected_]]"
+            on-click="onGetStartedClicked_">$i18n{getStarted}</paper-button>
       </div>
     </div>
   </template>
diff --git a/components/nux_google_apps/resources/nux_google_apps.js b/components/nux_google_apps/resources/nux_google_apps.js
index 9f7a8ea..ee8bedf9 100644
--- a/components/nux_google_apps/resources/nux_google_apps.js
+++ b/components/nux_google_apps/resources/nux_google_apps.js
@@ -4,4 +4,21 @@
 
 Polymer({
   is: 'nux-google-apps',
+
+  properties: {
+    /** @private */
+    hasAppsSelected_: Boolean,
+  },
+
+  /** @private */
+  onNoThanksClicked_: function() {
+    window.location.replace('chrome://newtab');
+  },
+
+  /** @private */
+  onGetStartedClicked_: function() {
+    let selectedApps = this.$.appChooser.getSelectedAppList();
+    nux.NuxGoogleAppsProxyImpl.getInstance().addGoogleApps(selectedApps);
+    window.location.replace('chrome://newtab');
+  },
 });
diff --git a/components/nux_google_apps/resources/nux_google_apps_proxy.html b/components/nux_google_apps/resources/nux_google_apps_proxy.html
new file mode 100644
index 0000000..604b825
--- /dev/null
+++ b/components/nux_google_apps/resources/nux_google_apps_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="nux_google_apps_proxy.js"></script>
\ No newline at end of file
diff --git a/components/nux_google_apps/resources/nux_google_apps_proxy.js b/components/nux_google_apps/resources/nux_google_apps_proxy.js
new file mode 100644
index 0000000..48d63ceb
--- /dev/null
+++ b/components/nux_google_apps/resources/nux_google_apps_proxy.js
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('nux', function() {
+  /** @interface */
+  class NuxGoogleAppsProxy {
+    /**
+     * Adds the selected apps to the bookmark bar.
+     * @param {!Array<boolean>} selectedApps
+     */
+    addGoogleApps(selectedApps) {}
+  }
+
+  /** @implements {NuxGoogleAppsProxy} */
+  class NuxGoogleAppsProxyImpl {
+    /** @override */
+    addGoogleApps(selectedApps) {
+      chrome.send('addGoogleApps', selectedApps);
+    }
+  }
+
+  cr.addSingletonGetter(NuxGoogleAppsProxyImpl);
+
+  return {
+    NuxGoogleAppsProxy: NuxGoogleAppsProxy,
+    NuxGoogleAppsProxyImpl: NuxGoogleAppsProxyImpl,
+  };
+});
\ No newline at end of file
diff --git a/components/nux_google_apps/webui.cc b/components/nux_google_apps/webui.cc
deleted file mode 100644
index 425c242..0000000
--- a/components/nux_google_apps/webui.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/nux_google_apps/webui.h"
-
-#include "base/metrics/field_trial_params.h"
-#include "components/grit/components_resources.h"
-#include "components/grit/components_scaled_resources.h"
-#include "components/nux_google_apps/constants.h"
-#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/web_ui_data_source.h"
-
-namespace nux_google_apps {
-
-void AddSources(content::WebUIDataSource* html_source) {
-  // Localized strings.
-  html_source->AddLocalizedString("noThanks", IDS_NO_THANKS);
-  html_source->AddLocalizedString("getStarted",
-                                  IDS_NUX_GOOGLE_APPS_GET_STARTED);
-  html_source->AddLocalizedString("nuxDescription",
-                                  IDS_NUX_GOOGLE_APPS_DESCRIPTION);
-
-  // Add required resources.
-  html_source->AddResourcePath("apps", IDR_NUX_GOOGLE_APPS_HTML);
-  html_source->AddResourcePath("apps/nux_google_apps.js",
-                               IDR_NUX_GOOGLE_APPS_JS);
-
-  html_source->AddResourcePath("apps/apps_chooser.html",
-                               IDR_NUX_GOOGLE_APPS_CHOOSER_HTML);
-  html_source->AddResourcePath("apps/apps_chooser.js",
-                               IDR_NUX_GOOGLE_APPS_CHOOSER_JS);
-
-  // Add icons
-  html_source->AddResourcePath("apps/chrome_store_1x.png",
-                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X);
-  html_source->AddResourcePath("apps/chrome_store_2x.png",
-                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X);
-  html_source->AddResourcePath("apps/gmail_1x.png",
-                               IDR_NUX_GOOGLE_APPS_GMAIL_1X);
-  html_source->AddResourcePath("apps/gmail_2x.png",
-                               IDR_NUX_GOOGLE_APPS_GMAIL_2X);
-  html_source->AddResourcePath("apps/maps_1x.png", IDR_NUX_GOOGLE_APPS_MAPS_1X);
-  html_source->AddResourcePath("apps/maps_2x.png", IDR_NUX_GOOGLE_APPS_MAPS_2X);
-  html_source->AddResourcePath("apps/news_1x.png", IDR_NUX_GOOGLE_APPS_NEWS_1X);
-  html_source->AddResourcePath("apps/news_2x.png", IDR_NUX_GOOGLE_APPS_NEWS_2X);
-  html_source->AddResourcePath("apps/translate_1x.png",
-                               IDR_NUX_GOOGLE_APPS_TRANSLATE_1X);
-  html_source->AddResourcePath("apps/translate_2x.png",
-                               IDR_NUX_GOOGLE_APPS_TRANSLATE_2X);
-  html_source->AddResourcePath("apps/youtube_1x.png",
-                               IDR_NUX_GOOGLE_APPS_YOUTUBE_1X);
-  html_source->AddResourcePath("apps/youtube_2x.png",
-                               IDR_NUX_GOOGLE_APPS_YOUTUBE_2X);
-}
-
-}  // namespace nux_google_apps
diff --git a/components/nux_google_apps/webui.h b/components/nux_google_apps/webui.h
deleted file mode 100644
index e9c752a1..0000000
--- a/components/nux_google_apps/webui.h
+++ /dev/null
@@ -1,17 +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 COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
-#define COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
-
-#include "base/macros.h"
-#include "content/public/browser/web_ui_data_source.h"
-
-namespace nux_google_apps {
-
-void AddSources(content::WebUIDataSource* html_source);
-
-}  // namespace nux_google_apps
-
-#endif  // COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
diff --git a/components/policy/resources/policy_templates_ar.xtb b/components/policy/resources/policy_templates_ar.xtb
index 514de32..a0e125b7 100644
--- a/components/policy/resources/policy_templates_ar.xtb
+++ b/components/policy/resources/policy_templates_ar.xtb
@@ -242,6 +242,13 @@
       وبخلاف ذلك، إذا وجب حدوث توافق مع أحد الخوادم التي تحتوي على أخطاء، فقد يتم تعيين هذه السياسة إلى "tls1.1". وهذا إجراء مؤقت ومن المفترض أن يتم إصلاح الخادم بسرعة.</translation>
 <translation id="1864269674877167562">‏إذا تم تعيين هذه السياسة إلى "string" فارغ أو لم تتم تهيئتها، فلن يعرض <ph name="PRODUCT_OS_NAME" /> أي خيار إكمال تلقائي أثناء تدفق تسجيل دخول المستخدم.
       إذا تم تعيين هذه السياسة إلى "string" يمثل اسم نطاق، فسيعرض <ph name="PRODUCT_OS_NAME" /> خيار الإكمال التلقائي أثناء تسجيل دخول المستخدم، ما يسمح للمستخدم بكتابة اسم المستخدم التابع له بدون إضافة اسم النطاق. وسيتمكن المستخدم من استبدال إضافة اسم النطاق هذه.</translation>
+<translation id="1864382791685519617">‏تفعّل هذه السياسة توقع الشبكة في <ph name="PRODUCT_NAME" /> وتمنع المستخدمين من تغيير هذا الإعداد.
+
+      ويتحكم ذلك في الجلب المُسبَق لنظام أسماء النطاقات والاتصال المُسبق عبر بروتوكول التحكم بالنقل (TCP) وطبقة المقابس الآمنة والعرض المُسبَق لصفحات الويب.
+
+      في حال تحديد هذه السياسة، لن يتمكن المستخدمون من تغيير هذا الإعداد أو إلغائه في <ph name="PRODUCT_NAME" />.
+
+      وفي حال ترك هذه السياسة غير مُحدَّدة، سيتم تفعيل توقع الشبكة، ولكن سيظل المستخدم قادرًا على تغييره.</translation>
 <translation id="1865417998205858223">الأذونات الرئيسية</translation>
 <translation id="186719019195685253">إجراء يمكن اتخاذه عند الوصول إلى حد التأخير "بعيد" أثناء التشغيل على طاقة التيار المتردد</translation>
 <translation id="187819629719252111">للسماح بالدخول إلى الملفات المحلية على الجهاز من خلال السماح لـ <ph name="PRODUCT_NAME" /> بعرض مربعات حوار تحديد الملفات. إذا تم تفعيل هذا الإعداد، يتمكن المستخدمون من فتح مربعات حوار تحديد الملفات كالعادة. إذا تم إيقاف هذا الإعداد، فعند إجراء المستخدم أي إجراء من شأنه أن يؤدي إلى ظهور مربع حوار تحديد ملف (مثل، استيراد الإشارات المرجعية وتحميل الملفات وحفظ الروابط وما إلى ذلك)، يتم عرض رسالة بدلاً من ذلك ويكون من المفترض أن ينقر المستخدم على "إلغاء" في مربع حوار تحديد الملف. إذا لم يتم تعيين الإعداد، يتمكن المستخدمون من فتح مربعات حوار تحديد الملفات كالعادة.</translation>
@@ -684,12 +691,14 @@
        في حال عدم تعيين هذه السياسة، تكون <ph name="PRINTERS_ALLOW_ALL" /> هي السياسة المفروضة.
       </translation>
 <translation id="2908277604670530363">أقصى عدد من الاتصالات المتزامنة للخادم الوكيل</translation>
+<translation id="2951386431828317490">تفعيل "الملء التلقائي" للملفات الشخصية</translation>
 <translation id="2956777931324644324">‏تم إيقاف هذه السياسة اعتبارًا من <ph name="PRODUCT_NAME" /> الإصدار 36.
 تحدد إذا ما كان يجب تفعيل إضافة شهادات تعتمد على نطاق TLS.
 يتم استخدام هذا الإعداد لتفعيل إضافة شهادات تعتمد على نطاق TLS للاختبار. سيتم حذف هذا الإعداد التجريبي مستقبلاً.</translation>
 <translation id="2957506574938329824">عدم السماح لأي موقع بطلب الدخول إلى أجهزة بلوتوث عبر واجهة برمجة تطبيقات بلوتوث الويب</translation>
 <translation id="2957513448235202597">نوع الحساب لمصادقة <ph name="HTTP_NEGOTIATE" /></translation>
 <translation id="2959898425599642200">قواعد تجاوز الخادم الوكيل</translation>
+<translation id="2960128438010718932">الجدول الزمني المرحلي لتطبيق تحديث جديد</translation>
 <translation id="2960691910306063964">تفعيل المصادقة دون رقم تعريف شخصي أو إيقافها لمضيفات الوصول البعيد</translation>
 <translation id="2976002782221275500">لتحديد المدة الزمنية التي تنقضي بدون تعامل المستخدم مع الجهاز، والتي بعد انقضائها يتم تعتيم الشاشة عند استخدام طاقة البطارية.
 
@@ -730,6 +739,7 @@
       وبغض النظر عن سبب أو كيفية تعيين هذه السياسة، فإنه يتعذر تغيير إعداد WPAD من خلال المستخدمين.</translation>
 <translation id="3072045631333522102">شاشة التوقف المراد استخدامها على شاشة تسجيل الدخول في وضع البيع بالتجزئة</translation>
 <translation id="3072847235228302527">تعيين بنود الخدمة لحساب محلي على الجهاز</translation>
+<translation id="3077183141551274418">تفعيل دورات حياة علامات التبويب أو إيقافها</translation>
 <translation id="3086995894968271156">‏تهيئة مستقبِل Cast في <ph name="PRODUCT_NAME" />.</translation>
 <translation id="3088796212846734853">‏تسمح لك بإعداد قائمة بأنماط عناوين url التي تحدّد المواقع الإلكترونية المسموح لها بعرض الصور.
 
@@ -1279,6 +1289,11 @@
       يتم جلب هذه الاقتراحات عن بُعد من خوادم Google.
 
       وإذا تم ضبط هذه السياسة على "false"، لن يتم جلب الاقتراحات أو عرضها.</translation>
+<translation id="4788252609789586009">تفعّل هذه السياسة ميزة "الملء التلقائي" في <ph name="PRODUCT_NAME" /> وتسمح للمستخدمين بإكمال معلومات بطاقة الائتمان في نماذج الويب تلقائيًا باستخدام المعلومات المخزنة مسبقًا.
+
+      في حال إيقاف هذا الإعداد، لن تقترح ميزة "الملء التلقائي" معلومات بطاقة الائتمان أو تملأها مطلقًا ولن تحفظ معلومات بطاقة الائتمان الإضافية التي قد يرسلها المستخدم أثناء تصفُّح الويب.
+
+      وفي حال تفعيل هذا الإعداد أو عدم تحديد قيمة، سيتمكن المستخدم من التحكُّم في ميزة "الملء التلقائي" لبطاقات الائتمان في واجهة المستخدم.</translation>
 <translation id="4791031774429044540">‏تفعيل ميزة الدخول إلى المؤشر الكبير.
 
           في حالة تعيين هذه السياسة على "true"، سيتم تفعيل المؤشر الكبير على الدوام.
@@ -1403,6 +1418,11 @@
 <translation id="519247340330463721">تهيئة السياسات المتعلقة بالتصفح الآمن.</translation>
 <translation id="5192837635164433517">لتفعيل استخدام صفحات الأخطاء البديلة المضمنة في <ph name="PRODUCT_NAME" /> (مثل "لم يتم العثور على الصفحة") ومنع المستخدمين من تغيير هذا الإعداد. إذا تم تفعيل هذا الإعداد، فسيتم استخدام صفحات الأخطاء البديلة. إذا تم إيقاف هذا الإعداد، فلن يتم استخدام صفحات الأخطاء البديلة مطلقًا. إذا تم تفعيل هذا الإعداد أو إيقافه، فلن يتمكن المستخدمون من تغيير هذا الإعداد أو تجاوزه في <ph name="PRODUCT_NAME" />. إذا تم ترك هذه السياسة بدون تعيين، فسيتم تفعيل هذا الإعداد وسيتمكن المستخدم من تغييره.</translation>
 <translation id="5196805177499964601">‏حظر وضع مطوّر البرامج. إذا تم تعيين هذه السياسة على True فسيمنع <ph name="PRODUCT_OS_NAME" /> الجهاز من بدء التشغيل في وضع مطور البرامج. سيرفض النظام بدء التشغيل وسيظهر رسالة خطأ عند محاولة تشغيل وضع مطوّر البرامج. إذا لم يتم ضبط هذه السياسة أو تم ضبطها على False، فسيبقى وضع مطوّر البرامج متوفرًا على الجهاز.</translation>
+<translation id="520403427390290017">‏ميزة دورات حياة علامات التبويب تُعيد المطالبة بوحدة المعالجة المركزية وفي النهاية الذاكرة المرتبطة بتشغيل علامات التبويب التي لم يتم استخدامها منذ فترة زمنية طويلة، من خلال تقييدها أولاً، ثم تجميدها وأخيرًا تجاهلها.
+
+      في حال ضبط السياسة على "false"، حينئذٍ يتم إيقاف دورات حياة علامات التبويب، كما سيتم ترك جميع علامات التبويب تعمل بشكلٍ طبيعي.
+
+      وفي حال ضبط السياسة على "true" أو تركها بدون تحديد، حينئذٍ يتم تفعيل دورات حياة علامات التبويب.</translation>
 <translation id="5208240613060747912">‏للسماح لك بتعيين قائمة أنماط عناوين URL التي تحدد المواقع التي لا يُسمح لها بعرض الإشعارات. إذا تم ترك هذه السياسة بدون تعيين، فسيتم استخدام القيمة التلقائية العامة لجميع المواقع إما من السياسة 'DefaultNotificationsSetting' إذا كان قد تم تعيينها أو من التهيئة الشخصية للمستخدم.</translation>
 <translation id="5219844027738217407">‏بالنسبة لتطبيقات Android، تؤثر هذه السياسة على الميكروفون فقط. عند تعيين هذه السياسة على "true"، يتم كتم صوت الميكروفون لجميع تطبيقات Android، دون أي استثناءات.</translation>
 <translation id="523505283826916779">إعدادات إمكانية الدخول</translation>
@@ -1444,6 +1464,11 @@
 
           عند تعيين هذه السياسة على False، لن يتمكن المستخدمون من إرسال المحتوى إلى جهازهم. وعند تعيين هذه السياسة على True، سيتم السماح للمستخدمين بإرسال المحتوى. وفي حال لم يتم تعيين هذه السياسة، لن يتم السماح للمستخدمين بإرسال المحتوى إلى أجهزة نظام تشغيل Chrome المُسجَّلة لكن يمكنهم الإرسال إلى أجهزة غير مُسجَّلة.</translation>
 <translation id="5330684698007383292">السماح لـ <ph name="PRODUCT_FRAME_NAME" /> بالتعامل مع أنواع المحتوى التالية</translation>
+<translation id="5360146044009867539">تفعّل هذه السياسة ميزة "الملء التلقائي" في <ph name="PRODUCT_NAME" /> وتسمح للمستخدمين بإكمال معلومات العنوان والملف الشخصي في نماذج الويب تلقائيًا باستخدام المعلومات المخزنة مسبقًا.
+
+      في حال إيقاف هذا الإعداد، لن تقترح ميزة "الملء التلقائي" معلومات العنوان أو تملأها مطلقًا ولن تحفظ معلومات العنوان الإضافية التي قد يرسلها المستخدم أثناء تصفُّح الويب.
+
+      وفي حال تفعيل هذا الإعداد أو عدم تحديد قيمة، سيتمكن المستخدم من التحكُّم في ميزة "الملء التلقائي" للعناوين في واجهة المستخدم.</translation>
 <translation id="5365946944967967336">عرض زر الصفحة الرئيسية في شريط الأدوات</translation>
 <translation id="5366745336748853475">‏تسمح لك بتعيين قائمة بأنماط عناوين URL التي تحدد المواقع التي يتم تحديد شهادات العميل لها تلقائيًا على شاشة تسجيل الدخول في الإطار الذي يستضيف تدفق SAML، وذلك في حال طلب الموقع لشهادة. والغرض من استخدام مثال هو تهيئة شهادة على مستوى الجهاز ليتم تقديمها إلى SAML IdP.
 
@@ -2112,6 +2137,15 @@
 
           عند إيقاف هذا الإعداد، لن تصبح هذه الميزة متاحة.</translation>
 <translation id="7275334191706090484">الإشارات المرجعية المُدارة</translation>
+<translation id="729492886167634859">‏تُحدِّد هذه السياسة قائمة بالنسب المئوية التي ستحدد الجزء من أجهزة <ph name="PRODUCT_OS_NAME" /> في الوحدة التنظيمية لتحديثها كل أسبوع بدءًا من اليوم الذي يتم فيه اكتشاف التحديث لأول مرة. وسيكون وقت الاكتشاف أحدث من وقت التحديث المنشور، حيث من الممكن أن يستغرق الأمر بعض الوقت بعد نشر التحديث حتى يبحث الجهاز عن التحديثات.
+
+      سيتم استخدام القيمة رقم N في القائمة كنسبة مئوية من الأجهزة التي يجب أن تستكمل التحديث إلى الإصدار التالي في الأسبوع رقم N بعد اكتشاف التحديث. على سبيل المثال، إذا تم اكتشاف أحد التحديثات اليوم، حينئذٍ تحدد القيمة الأولى في القائمة النسبة المئوية للأجهزة في الوحدة التنظيمية التي يجب تحديثها إلى هذا الإصدار بعد أسبوع ابتداءً من اليوم. أما القيمة الثانية تُحدِّد النسبة المئوية للأجهزة في الوحدة التنظيمية التي يجب تحديثها إلى هذا الإصدار بعد أسبوعين ابتداءً من اليوم، وما إلى ذلك.
+
+      إذا كانت هناك قيمة مُحدَّدة لهذه السياسة، ستتجاهل التحديثات سياسة <ph name="DEVICE_UPDATE_SCATTER_FACTOR_POLICY_NAME" /> وتتَّبع هذه السياسة بدلاً من ذلك.
+
+      إذا كانت هذه القائمة فارغة، لن تتوفَّر أي مراحل وسيتم تطبيق التحديثات وفقًا لسياسات الجهاز الأخرى.
+
+      لا تنطبق تلك السياسة على تطبيقات مفاتيح القنوات.</translation>
 <translation id="7295019613773647480">تفعيل المستخدمين الخاضعين للإشراف</translation>
 <translation id="7301543427086558500">‏تحديد قائمة بعناوين URL البديلة التي يمكن استخدامها لاستخراج عبارات البحث من محرك البحث. يجب أن تشتمل عناوين URL على سلسلة <ph name="SEARCH_TERM_MARKER" />، التي سيتم استخدامها في استخراج عبارات البحث.
 
@@ -2561,6 +2595,12 @@
 
           للحصول على نماذج للأنماط، راجع https://www.chromium.org/developers/how-tos/chrome-frame-getting-started.</translation>
 <translation id="8493645415242333585">إيقاف حفظ سجل المتصفح</translation>
+<translation id="8498293625012059298">‏يمكنك تهيئة عنوان URL لتغيير كلمة المرور (مخططات HTTP وHTTPS فقط). وستوجه خدمة "حماية كلمات المرور" المستخدمين إلى عنوان URL هذا لتغيير كلمات المرور بعد ظهور تحذير في المتصفّح.
+      وليتمكّن <ph name="PRODUCT_NAME" /> من الحصول على الملف المرجعي لكلمة المرور الجديدة بشكلٍ صحيح في صفحة تغيير كلمة المرور هذه، يُرجى التأكد من اتباع صفحة تغيير كلمة المرور للإرشادات الواردة في https://www.chromium.org/developers/design-documents/create-amazing-password-forms.
+
+      في حال تفعيل هذا الإعداد، حينئذٍ ستوجه خدمة "حماية كلمات المرور" المستخدمين إلى عنوان URL هذا لتغيير كلمات مرورهم بعد ظهور تحذير في المتصفّح.
+      وفي حال إيقاف هذا الإعداد أو عدم تحديده، حينئذٍ ستوجه خدمة "حماية كلمات المرور" المستخدمين إلى https://myaccounts.google.com لتغيير كلمات مرورهم.
+      لا تتوفر هذه السياسة على النُسخ الافتراضية لنظام التشغيل Windows غير المُلحقة بنطاق <ph name="MS_AD_NAME" />.</translation>
 <translation id="8499172469244085141">الإعدادات التلقائية (يمكن للمستخدمين استبدالها)</translation>
 <translation id="8507835864888987300">تعيّن هذه السياسة إصدارًا مستهدفًا للتحديثات التلقائية. 
 
@@ -2613,6 +2653,14 @@
       في حال تعيين السياسة على الوضع "False"، لن يتم السماح للجهاز بتشغيل الآلات الافتراضية.
       عند تغيير هذه السياسة إلى الوضع "False"، يسري تطبيقها على تشغيل الآلات الافتراضية الجديدة، ولكنها لا توقف الآلات الافتراضية المُشغّلة من قبل.
       في حال عدم تعيين هذه السياسة على جهاز مُدار، لا يُسمح للجهاز بتشغيل الآلات الافتراضية، إلا أنه يُسمح للأجهزة غير المُدارة بتشغيل الآلات الافتراضية.</translation>
+<translation id="8669669491594628013">‏تتيح لك هذه السياسة التحكُّم في تشغيل تحذير حماية كلمة المرور. وتنبّه "حماية كلمة المرور" المستخدمين عند إعادة استخدام كلمات المرور المحمية في المواقع الإلكترونية التي يُحتمل أن تكون مريبة.
+
+      يمكنك استخدام السياستين "PasswordProtectionLoginURLs" و"PasswordProtectionChangePasswordURL" لضبط كلمات المرور التي تريد حمايتها.
+
+      في حال ضبط هذه السياسة على "PasswordProtectionWarningOff"، لن يتم عرض أي تحذير بخصوص حماية كلمة المرور.
+      وفي حال ضبطها على "PasswordProtectionWarningOnPasswordReuse"، سيتم عرض تحذير حماية كلمة المرور عندما يعيد المستخدم استعمال كلمة المرور المحمية على موقع إلكتروني لم تتم إضافته إلى القائمة البيضاء.
+      في حال ضبط السياسة على "PasswordProtectionWarningOnPhishingReuse"، سيتم عرض تحذير حماية كلمة المرور عندما يعيد المستخدم استعمال كلمة المرور المحمية في موقع تصيُّد احتيالي.
+      وفي حال عدم ضبط هذه السياسة، لن تحمي خدمة "حماية كلمة المرور" إلا كلمات مرور Google ولكن سيتمكّن المستخدم من تغيير هذا الإعداد.</translation>
 <translation id="8672321184841719703">إصدار التحديث التلقائي المستهدف</translation>
 <translation id="867410340948518937">‏U2F (العامل الثاني العالمي)</translation>
 <translation id="8685024486845674965">تم تشغيل تحذير حماية كلمة المرور من خلال إعادة استخدام كلمة المرور.</translation>
diff --git a/components/policy/resources/policy_templates_bn.xtb b/components/policy/resources/policy_templates_bn.xtb
index a2d63d3..688220b 100644
--- a/components/policy/resources/policy_templates_bn.xtb
+++ b/components/policy/resources/policy_templates_bn.xtb
@@ -283,6 +283,13 @@
       অন্যথায়, যদি একটি ক্রুটিযুক্ত সার্ভারের সাথে সঙ্গতি বজায় রাখা আবশ্যক হয়, তাহলে একে "tls1.1" এ সেট করা যেতে পারে। এটি একটি অস্থায়ী সমাধান এবং সার্ভারটি দ্রুত সংশোধন করা উচিত।</translation>
 <translation id="1864269674877167562">এই নীতিটি যদি একটি ফাঁকা স্ট্রিং হিসাবে সেট করা থাকে বা কনফিগার করা না থাকে, তাহলে <ph name="PRODUCT_OS_NAME" /> ব্যবহারকারীকে সাইন ইন প্রবাহের সময়  কোনো স্বয়ংপূর্ণ বিকল্প দেখাবে না।
       এই নীতিটি যদি একটি ডোমেন নাম প্রতিনিধিত্ব করে এমন একটি স্ট্রিং হিসাবে সেট করা থাকে, তাহলে <ph name="PRODUCT_OS_NAME" /> ব্যবহারকারীকে সাইন ইনের সময়ে স্বয়ংপূর্ণ বিকল্প দেখাবে যেখানে ব্যবহারকারী ডোমেন নাম এক্সটেনশান ছাড়া শুধুমাত্র তার ইউজারনেম লেখার অনুমতি পাবেন। ব্যবহারকারী এই ডোমেন নাম এক্সটেনশান ওভাররাইট করতে পারবেন।</translation>
+<translation id="1864382791685519617"><ph name="PRODUCT_NAME" /> -এ নেটওয়ার্ক পূর্বাভাস চালু করে এবং ব্যবহারকারীদের এই সেটিংটি পরিবর্তন করতে বাধা দেয়।
+
+      এটি ডিএনএস প্রি-ফেচিং, ওয়েব পেজের TCP এবং SSL প্রি-কানেকশন এবং প্রি-রেন্ডারিং নিয়ন্ত্রণ করে।
+
+      আপনি এই নীতি সেট করলে, ব্যবহারকারীরা <ph name="PRODUCT_NAME" />-এ এই সেটিংটি পরিবর্তন বা ওভাররাইড করতে পারবে না।
+
+      এই নীতিটি যদি সেট না করে রাখা হয়, তাহলে নেটওয়ার্ক পূর্বাভাষ চালু করা হবে কিন্তু ব্যবহারকারী এটি পরিবর্তন করতে পারবেন।</translation>
 <translation id="1865417998205858223">মূল অনুমতিগুলি</translation>
 <translation id="186719019195685253">AC পাওয়ার ব্যবহার করে চালনা করার সময় নিষ্ক্রিয়তা বিলম্বের সময়সীমা পেরিয়ে গেলে যে পদক্ষেপ নেওয়া হবে</translation>
 <translation id="187819629719252111">ফাইল নির্বাচন কথোপকথনগুলি প্রদর্শন করতে <ph name="PRODUCT_NAME" />এর অনুমতি দিয়ে মেশিনে স্থানীয় ফাইলগুলিতে অ্যাক্সেসের অনুমতি দেয়৷ আপনি এই সেটিং সক্ষম করলে, ব্যবহারকারীরা সাধারণ হিসাবে ফাইল নির্বাচন কথোপকথনগুলি খুলতে পারে৷ আপনি এই সেটিং অক্ষম করলে, যখনই ব্যবহারকারী এমন কোনো কার্য করে যা কোনো ফাইল নির্বাচন কথোপকথন (যেমন বুকমার্কগুলির আমদানি, ফাইলগুলি আপলোড করা, লিঙ্কগুলি সংরক্ষণ করা ইত্যাদি)কে প্রণোদনা দেয় একটি বার্তা পরিবর্তে প্রদর্শিত হয় এবং ব্যবহারকারী ফাইল নির্বাচন কথোপকথনে বাতিল ক্লিক করেছে বলে ধরা হয়৷ এই সেটিংটি সেট করা না থাকলে, ব্যবহারকারীগণ সাধারণভাবে ফাইল নির্বাচন কথোপকথনগুলি খুলতে পারে৷</translation>
@@ -796,6 +803,7 @@
      যদি এই নীতিটি সেট করা না থাকে তাহলে <ph name="PRINTERS_ALLOW_ALL" /> নীতি মেনে চলা হয়।
       </translation>
 <translation id="2908277604670530363">প্রক্সি সার্ভারের জন্য সংঘটনশীল সংযোগের সর্বধিক সংখ্যা</translation>
+<translation id="2951386431828317490">প্রোফাইলগুলির জন্য AutoFill বিকল্প চালু করা</translation>
 <translation id="2956777931324644324">এই নীতিটি <ph name="PRODUCT_NAME" /> সংস্করণ ৩৬ এর হিসাবে অপসারণ করা হয়েছে।
 
       TLS ডোমেন-বাউন্ড সার্টিফিকেট এক্সটেনশান সক্ষম করা হবে কিনা তা নির্দিষ্ট করে।
@@ -805,6 +813,7 @@
 <translation id="2957513448235202597"><ph name="HTTP_NEGOTIATE" /> প্রমাণীকরণের জন্য অ্যাকাউন্টের ধরন</translation>
 <translation id="2959469725686993410">সময় অঞ্চল নির্ধারণ করার সময়ে সবসময় সার্ভারে ওয়াই ফাই অ্যাক্সেস-পয়েন্ট পাঠান</translation>
 <translation id="2959898425599642200">প্রক্সি বাইপাস বিধিসমূহ</translation>
+<translation id="2960128438010718932">একটি নতুন আপডেট প্রয়োগ করার জন্য স্ট্যাগিং সময়সূচি</translation>
 <translation id="2960691910306063964">দূরবর্তী অ্যাক্সেস হোস্টের জন্য পিন বিহীন প্রমাণীকরণ অক্ষম বা সক্ষম করে</translation>
 <translation id="2976002782221275500">ব্যবহারকারীর ইনপুট ছাড়াই সময়কাল নির্দিষ্ট করে, তারপর ব্যাটারি শক্তি চলতে থাকলেও স্ক্রিনটির উজ্জ্বলতা হ্রাস হয়ে যায়৷
 
@@ -853,6 +862,7 @@
       এই নীতি সেট করা আছে কিনা বা কিভাবে সেট করা আছে, তা যাই হোক না কেন, WPAD অপটিমাইজেশান সেটিং ব্যবহারকারীদের দ্বারা পরিবর্তন করা যাবে না।</translation>
 <translation id="3072045631333522102">সাইন-ইন স্ক্রিনে খুচরো মোডে স্ক্রিন সেভার ব্যবহৃত হতে পারে</translation>
 <translation id="3072847235228302527">একটি ডিভাইস-স্থানীয় অ্যাকাউন্টের জন্য পরিষেবার শর্তাদি সেট করুন</translation>
+<translation id="3077183141551274418">ট্যাব লাইফসাইকেল চালু অথবা বন্ধ করা</translation>
 <translation id="3086995894968271156"><ph name="PRODUCT_NAME" /> এ কাস্ট রিসিভার কনফিগার করুন।</translation>
 <translation id="3088796212846734853">যে সমস্ত সাইটকে ছবি দেখানোর অনুমতি দিতে চান সেগুলির ইউআরএলের একটি তালিকা সেট করতে দেয়।
 
@@ -1516,6 +1526,11 @@
       এই সাজেশনগুলি Google সার্ভার থেকে আনা হয়।
 
      যদি এই সেটিং ফলসে সেট করা হয়, সাজেশনগুলি আনা হবে না বা প্রদর্শিত হবে না।</translation>
+<translation id="4788252609789586009"><ph name="PRODUCT_NAME" />-এর AutoFill বৈশিষ্ট্যটি চালু করে এবং ব্যবহারকারীদের ঠিকানার মতো আগে থেকে থাকা তথ্য ব্যবহার করে ওয়েব ফর্ম পূরণ করার অনুমতি দেয়।
+
+      যদি আপনি এই সেটিসংটি বন্ধ করেন তবে Autofill ক্রেডিট কার্ডের তথ্যগুলি সুপারিশ করবে না বা এটি অতিরিক্ত ক্রেডিট কার্ডের তথ্য সেভ করবে না যা ওয়েব ব্রাউজ করার সময় ব্যবহারকারী জমা দিতে পারে।
+
+      আপনি যদি এই সেটিসংটি চালু করেন বা একটি মান সেট না করেন তবে ব্যবহারকারী UI-তে ক্রেডিট কার্ডের জন্য Autofill নিয়ন্ত্রণ করতে পারবেন।</translation>
 <translation id="4791031774429044540">বড় কার্সার অ্যাক্সেসযোগ্যতার বৈশিষ্ট্য সক্ষম করে৷
 
           যদি এই নীতি সত্যতে সেট করা থাকে, তাহলে বড় কার্সার সর্বদা সক্ষম থাকবে৷
@@ -1670,6 +1685,11 @@
 যদি এই নীতিটিকে সত্যতে সেট করা হয়, তাহলে <ph name="PRODUCT_OS_NAME" /> ডিভাইসটিকে ডেভেলপার মোডে চালু হতে আটকে দেবে৷ সিস্টেমটি চালু হবে না এবং ডেভেলপার স্যুইচটি চালু থাকবে তখন একটি ত্রুটি স্ক্রিন প্রদর্শন করবে৷
 
 যদি নীতিটিকে সেট না করে ফেলে রাখা হয় বা মিথ্যাতে সেট করা থাকে, তাহলে ডেভেলপার মোড ডিভাইসটিতে উপলব্ধ থাকবে৷</translation>
+<translation id="520403427390290017">খুলে রাখা কোনও ট্যাব দীর্ঘক্ষণ ব্যবহার করা না হলে সেটির জন্য খরচ হওয়া মেমরি খালি করা এবং সিপিইউ-এ চলা প্রসেস বন্ধ করার কাজটি ট্যাব লাইফসাইকেল ফিচারের মাধ্যমে করা যায়। প্রথমে সেগুলি নিয়ন্ত্রণ করে, তারপর আলাদা করে এবং অবশেষে বাতিল করে।
+
+      নীতিটি ফলসে সেট করা থাকলে ট্যাব লাইফসাইকেলগুলি বন্ধ থাকে এবং সমস্ত ট্যাবগুলি স্বাভাবিকভাবে চলতে থাকবে।
+
+      যদি নীতি ট্রু তে সেট করা থাকে বা তথ্য না দিয়েই ছেড়ে দেওয়া হয় তাহলে ট্যাব লাইফসাইকেলগুলি চালু থাকে।</translation>
 <translation id="5208240613060747912">বিজ্ঞপ্তিগুলি প্রদর্শনের জন্য অনুমোদিত এমন সাইটগুলি নির্দিষ্ট করে এমন url ধরণগুলির একটি তালিকা আপনাকে সেট করার অনুমতি দেয়৷
 
 যদি এই নীতিটি বামে সেট না করে ছেড়ে যাওয়া হয়, তাহলে গ্লোবাল ডিফল্ট মান সব সাইটগুলির জন্য ব্যবহার করা হবে যদি 'ডিফল্ট বিজ্ঞপ্তি সেটিং' নীতি সেট করা হয় তা থেকে, নয়তো ব্যবহারকারীদের ব্যক্তিগত কনফিগারেশান থেকে৷</translation>
@@ -1731,6 +1751,11 @@
 
           এই নীতিটি যদি মিথ্যাতে সেট করা থাকে তাহলে ব্যবহারকারীরা তাদের ডিভাইসে কন্টেন্ট কাস্ট করতে পারবেন না। যদি এই নীতিটি সত্যতে সেট করা থাকে তাহলে ব্যবহারকারীদের কন্টেন্ট কাস্ট করার অনুমতি দেওয়া হয়। যদি নীতিটি সেট করা না থাকে তাহলে ব্যবহারকারীদেরকে তালিকাভুক্ত Chrome OS ডিভাইসে কাস্ট করার অনুমতি দেওয়া হয় না, কিন্তু তারা তালিকাভুক্ত নয় এমন ডিভাইসে কাস্ট করতে পারেন।</translation>
 <translation id="5330684698007383292">নিম্নোক্ত সামগ্রী প্রকার পরিচালনা করতে <ph name="PRODUCT_FRAME_NAME" /> কে মঞ্জুরি দিন৷</translation>
+<translation id="5360146044009867539"><ph name="PRODUCT_NAME" />-এর AutoFill বৈশিষ্ট্যটি চালু করে এবং ব্যবহারকারীদের ঠিকানা বা ক্রেডিট কার্ডের তথ্যের মতো আগে থেকে থাকা তথ্য ব্যবহার করে ওয়েব ফর্ম পূরণ করার অনুমতি দেয়।
+
+      যদি আপনি এই সেটিসংটি বন্ধ করেন তবে AutoFill ঠিকানার তথ্য পূরণের সুপারিশ করবে না বা এটি ঠিকানার অতিরিক্ত তথ্য সেভ হয়ত করবে না যা ওয়েব ব্রাউজ করার সময় ব্যবহারকারী জমা দিতে পারে।
+
+      আপনি যদি এই সেটিংটি চালু করেন বা একটি মান সেট না করেন তবে ব্যবহারকারী UI-তে সমগ্র AutoFill বৈশিষ্ট্য নিয়ন্ত্রণ করতে পারবেন।</translation>
 <translation id="5365946944967967336">টুলবারে হোম বোতাম দেখান</translation>
 <translation id="5366745336748853475">কোনও সাইটে যদি সার্টিফিকেট প্রয়োজন হয় তাহলে এই নীতির মাধ্যমে আপনি URL প্যাটার্নের একটি তালিকা নির্দিষ্ট করতে পারেন যেখানে এমন সাইট উল্লেখ করা থাকবে যেগুলির ক্ষেত্রে SAML ফ্লো হোস্ট করা ফ্রেমের সাইন-ইন স্ক্রিনে ক্লায়েন্ট সার্টিফিকেট নিজে থেকেই বেছে নেওয়া হয়। ডিভাইসের সমস্ত কাজে প্রযোজ্য যে সার্টিফিকেট SAML IdP তে জমা দিতে হয়, সেটি কনফিগার করার ক্ষেত্রে এটি ব্যবহার করা হয়।
 
@@ -2524,6 +2549,15 @@
       আপনি এই সেটিংটি অক্ষম করলে, ব্যবহারকারীদেরকে Smart Lock ব্যবহার করতে দেওয়া হবে না।
      
 এই নীতি সেট না করে রাখা হলে, এন্টারপ্রাইজ-পরিচালিত ব্যবহারকারীদের জন্য ডিফল্টের অনুমতি দেওয়া হয় না এবং অ-পরিচালিত ব্যবহারকারীদের জন্য অনুমতি দেওয়া হয়।</translation>
+<translation id="729492886167634859">আপডেটটি প্রথম যখন খুঁজে পাওয়া যাবে, সেদিন থেকে শুরু করে প্রতি সপ্তাহে OU-এর যতগুলি <ph name="PRODUCT_OS_NAME" /> ডিভাইস আপডেট করতে হবে, তার শতকরা হারের একটি তালিকা এই নীতিতে নির্দিষ্ট করা থাকে। আপডেট দেখার সময়টি আপডেট প্রকাশিত হওয়ার সময়ের পরে আসে, কারণ প্রকাশ করার বেশ কিছুক্ষণ বা কিছু দিন পরে ডিভাইসটি আপডেট খুঁজতে পারে।
+
+      কত শতাংশ ডিভাইসে পরবর্তী ভার্সনে আপডেট করার কাজটি আপডেট খুঁজে পাওয়ার পরে n সংখ্যক সপ্তাহের মধ্যে করতে হবে, সেটি তালিকার h মান হিসেবে উল্লেখ করা থাকে। যেমন, আজ যদি একটি আপডেট খুঁজে পাওয়া যায় তাহলে আজ থেকে এক সপ্তাহের মধ্যে OU-এর যত শতাংশ ডিভাইস সেই ভার্সনে আপডেট করতে হবে, সেটি তালিকার প্রথম মান হিসেবে উল্লেখ করা থাকবে। OU-এর যত শতাংশ ডিভাইস আজ থেকে দুই সপ্তাহের মধ্যে সেই ভার্সনে আপডেট করতে হবে, সেটি দ্বিতীয় মান হিসেবে উল্লেখ করা থাকবে।
+
+      এই নীতির জন্য যদি কোনও মান উল্লেখ করা থাকে তাহলে আপডেটগুলি <ph name="DEVICE_UPDATE_SCATTER_FACTOR_POLICY_NAME" /> নীতির বদলে এটি অনুসরণ করবে।
+
+      এই তালিকাটি যদি খালি থাকে তাহলে স্টেজিং করা হবে না এবং আপডেটগুলি ডিভাইসের অন্যান্য নীতি অনুযায়ী প্রয়োগ করা হবে।
+
+      চ্যানেল পরিবর্তনের ক্ষেত্রে এই নীতিটি প্রযোজ্য নয়।</translation>
 <translation id="7295019613773647480">তত্ত্বাবধানে থাকা ব্যবহারকারীদের সক্ষম করুন</translation>
 <translation id="7301543427086558500">পরিবর্ত URLগুলির একটি তালিকা নির্দিষ্ট করে যা সার্চ ইঞ্জিন থেকে সার্চ শব্দগুলি বের করে আনতে ব্যবহার করা হয়৷ URLগুলিতে <ph name="SEARCH_TERM_MARKER" /> স্ট্রিং থাকা উচিত, যা সার্চ শব্দগুলি বের করে আনতে ব্যবহার করা হবে৷
 
@@ -3040,6 +3074,12 @@
 
           প্যাটার্নের উদাহরণগুলির জন্য http://www.chromium.org/developers/how-tos/chrome-frame-getting-started দেখুন।</translation>
 <translation id="8493645415242333585">ব্রাউজার ইতিহাস সংরক্ষণ করা অক্ষম করুন</translation>
+<translation id="8498293625012059298">পাসওয়ার্ড পরিবর্তনের ইউআরএল কনফিগার করুন (HTTP এবং HTTPS স্কিম শুধুমাত্র)। ব্রাউজারে সতর্কতা দেখার পর পাসওয়ার্ড পরিবর্তনের জন্য আপনাকে পাসওয়ার্ড সুরক্ষা পরিষেবা এই ইউআরএলে পাঠিয়ে দেবে।
+      পাসওয়ার্ড পরিবর্তন করার পৃষ্ঠাতে <ph name="PRODUCT_NAME" /> যাতে নতুন পাসওয়ার্ড ফিঙ্গারপ্রিন্টটি সঠিকভাবে চিনে নিতে পারে, তার জন্য দেখে নিন এই পৃষ্ঠাটি https://www.chromium.org/developers/design-documents/create-amazing-password-forms-এ উল্লেখ করা নির্দেশাবলী মেনে চলছে কিনা।
+
+      যদি এই সেটিংসটি চালু থাকে, ব্রাউজারে সতর্কতা দেখার পর পাসওয়ার্ড পরিবর্তনের জন্য আপনাকে পাসওয়ার্ড সুরক্ষা পরিষেবা এই ইউআরএলে পাঠিয়ে দেবে।
+      যদি এই সেটিংসটি বন্ধ থাকে অথবা সেট না করা হয়, তাহলে পাসওয়ার্ড পরিবর্তনের জন্য আপনাকে পাসওয়ার্ড সুরক্ষা পরিষেবা https://myaccounts.google.com এ পাঠিয়ে দেবে।
+      এই নীতিটি সেই উইন্ডোর ইনস্ট্যান্সগুলিতে কাজ করবে না যেগুলি <ph name="MS_AD_NAME" />-এ ডোমেনের সাথে যুক্ত নয়।</translation>
 <translation id="8499172469244085141">ডিফল্ট সেটিংস (ব্যবহারকারীরা পাল্টাতে পারেন)</translation>
 <translation id="8507835864888987300">অটোমেটিক আপডেটের জন্য টার্গেট ভার্সন সেট করুন।
 
@@ -3094,6 +3134,14 @@
       এই নীতিটি ফল্সে পরিবর্তিত হলে, সেটি নতুন ভার্চুয়াল মেশিন চালানো শুরু করবে কিন্তু আগে থেকে চলতে থাকা ভার্চুয়াল মেশিনটি বন্ধ করবে না।
       নীতিটি যদি একটি পরিচালিত ডিভাইসে সেট না করা হয় তাহলে ডিভাইসটি ভার্চুয়াল মেশিন চালানোর অনুমতি দেবে না।
       অপরিচালিত ডিভাইসগুলি ভার্চুয়াল মেশিন চালানোর অনুমতি দেয় না।</translation>
+<translation id="8669669491594628013">আপনাকে পাসওয়ার্ড সুরক্ষার সতর্কতা ট্রিগার হওয়া নিয়ন্ত্রণ করতে দেয়। পাসওয়ার্ড সুরক্ষা ব্যবহারকারীদের সতর্ক করে দেয় যখন তারা সম্ভাব্য সন্দেহজনক সাইটগুলিতে তাদের সুরক্ষিত পাসওয়ার্ড আবার ব্যবহার করে।
+
+      কোন পাসওয়ার্ড সুরক্ষিত রাখা হবে তা আপনি 'PasswordProtectionLoginURLs' এবং 'PasswordProtectionChangePasswordURL' নীতি ব্যবহার করে কনফিগার করতে পারেন।
+
+      যদি এই নীতিটি 'PasswordProtectionWarningOff'-এ সেট করা হয় তাহলে পাসওয়ার্ডের নিরাপত্তা সম্পর্কিত কোনও সতর্কতা দেখানো হবে না।
+      যদি এই নীতিটি 'PasswordProtectionWarningOnPasswordReuse'-এ সেট করা হয় তাহলে ব্যবহারকারী সাদা-তালিকাভুক্ত নয় এমন সাইটে পাসওয়ার্ড আবার ব্যবহার করলে পাসওয়ার্ডের নিরাপত্তা সম্পর্কিত সতর্কতা দেখানো হবে।
+      যদি এই নীতিটি 'PasswordProtectionWarningOnPhishingReuse'-এ সেট করা হয় তাহলে ব্যবহারকারী ফিশিং সাইটে পাসওয়ার্ড আবার ব্যবহার করলে পাসওয়ার্ডের নিরাপত্তা সম্পর্কিত সতর্কতা দেখানো হবে।
+      যদি এই নীতিটি সেট না করেই ছেড়ে দেওয়া হয় তাহলে পাসওয়ার্ড সুরক্ষা পরিষেবা শুধুমাত্র Google-এর পাসওয়ার্ড সুরক্ষিত রাখবে কিন্তু ব্যবহারকারীরা এই সেটিংসটি পরিবর্তন করতে পারবেন।</translation>
 <translation id="8672321184841719703">লক্ষ্য স্বয়ংক্রিয়ভাবে আপডেট করা সংস্করণ</translation>
 <translation id="867410340948518937">U2F (সর্বজনীন দ্বিতীয় পদক্ষেপ)</translation>
 <translation id="8685024486845674965">আবার পাসওয়ার্ড ব্যবহার করা হয়েছে বলে পাসওয়ার্ড সুরক্ষার সতর্কতা জানানো হয়েছে</translation>
diff --git a/components/policy/resources/policy_templates_pt-PT.xtb b/components/policy/resources/policy_templates_pt-PT.xtb
index 8105d8e..eb1d5a9 100644
--- a/components/policy/resources/policy_templates_pt-PT.xtb
+++ b/components/policy/resources/policy_templates_pt-PT.xtb
@@ -317,7 +317,7 @@
       Tenha em atenção que, se a plataforma suportar notificações sobre políticas, o atraso de atualização é definido para 24 horas (ao ignorar todas as predefinições e o valor desta política) porque é esperado que as notificações sobre políticas forcem uma atualização automaticamente, sempre que a política sofrer alterações, o que torna desnecessárias as atualizações mais frequentes.</translation>
 <translation id="2024476116966025075">Configurar o nome do domínio obrigatório para clientes de acesso remoto</translation>
 <translation id="2030905906517501646">Palavra-chave do fornecedor de pesquisas predefinido</translation>
-<translation id="203096360153626918">Esta política não tem qualquer efeito nas aplicações Android. Estas podem ser colocadas no modo de ecrã inteiro mesmo que esta política esteja definida como <ph name="FALSE" />.</translation>
+<translation id="203096360153626918">Esta política não tem qualquer efeito nas aplicações para Android. Estas podem ser colocadas no modo de ecrã inteiro mesmo que esta política esteja definida como <ph name="FALSE" />.</translation>
 <translation id="2043770014371753404">Impressoras empresariais desativadas</translation>
 <translation id="2057317273526988987">Permitir o acesso a uma lista de URLs</translation>
 <translation id="206623763829450685">Especifica quais os esquemas de autenticação HTTP que o <ph name="PRODUCT_NAME" /> suporta.
@@ -407,7 +407,7 @@
 
       Especifica o comportamento de um dispositivo enviado com ecryptfs e que tem de transitar para a encriptação ext4.
 
-      Se definir esta política como "DisallowArc", as aplicações Android são desativadas para todos os utilizadores no dispositivo (incluindo os que já têm a encriptação ext4) e não é oferecida qualquer migração de ecryptfs para a encriptação ext4 a qualquer utilizador.
+      Se definir esta política como "DisallowArc", as aplicações para Android são desativadas para todos os utilizadores no dispositivo (incluindo os que já têm a encriptação ext4) e não é oferecida qualquer migração de ecryptfs para a encriptação ext4 a qualquer utilizador.
 
       Se definir esta política como "AllowMigration", é oferecida aos utilizadores com diretórios principais ecryptfs a migração para a encriptação ext4 conforme seja necessário (atualmente, quando o Android N ficar disponível no dispositivo).
 
@@ -478,7 +478,7 @@
 
       Para dispositivos geridos pelo Active Directory, esta política suporta a expansão de <ph name="MACHINE_NAME_VARIABLE" /> para o nome do computador do Active Directory ou uma substring do mesmo. Por exemplo, se o nome do computador for <ph name="MACHINE_NAME_EXAMPLE" />, <ph name="MACHINE_NAME_VARIABLE_EXAMPLE" /> será substituído pelos 4 carateres a partir da 6.ª posição, ou seja, <ph name="MACHINE_NAME_PART_EXAMPLE" />. Tenha em atenção que a posição baseia-se em zero.
       </translation>
-<translation id="2294382669900758280">A reprodução de vídeos em aplicações Android não é tida em consideração mesmo que esta política esteja definida como <ph name="TRUE" />.</translation>
+<translation id="2294382669900758280">A reprodução de vídeos em aplicações para Android não é tida em consideração mesmo que esta política esteja definida como <ph name="TRUE" />.</translation>
 <translation id="2298647742290373702">Configurar a página Novo separador predefinida no <ph name="PRODUCT_NAME" />.</translation>
 <translation id="2299220924812062390">Especificar uma lista de plug-ins ativados</translation>
 <translation id="2303795211377219696">Ativar Preenchimento automático para cartões de crédito</translation>
@@ -514,7 +514,7 @@
       Se esta definição não for definida, o utilizador poderá decidir utilizar esta função ou não.
 
       Esta definição foi removida do <ph name="PRODUCT_NAME" /> 29 e versões superiores.</translation>
-<translation id="2438609638493026652">Ativa a comunicação dos eventos principais durante a instalação de aplicações Android no Google. Os eventos são capturados apenas para as aplicações cuja instalação foi acionada através da política.
+<translation id="2438609638493026652">Ativa a comunicação dos eventos principais durante a instalação de aplicações para Android no Google. Os eventos são capturados apenas para as aplicações cuja instalação foi acionada através da política.
 
       Se a política estiver definida como verdadeira, os eventos são registados.
       Se a política estiver definida como falsa ou não estiver definida, os eventos não são registados.</translation>
@@ -638,7 +638,7 @@
 
       Quando esta política não está configurada ou definida como <ph name="BR_DISABLED" />, a cópia de segurança e o restauro do Android estão desativados e não podem ser ativados pelo utilizador.
 
-      Quando esta política está definida como <ph name="BR_UNDER_USER_CONTROL" />, é perguntado ao utilizador se pretende utilizar a cópia de segurança e o restauro do Android. Se o utilizador ativar a cópia de segurança e o restauro, os dados de aplicações Android são carregados para os servidores de cópia de segurança do Android e restaurados a partir dos mesmos após a reinstalação de aplicações compatíveis.</translation>
+      Quando esta política está definida como <ph name="BR_UNDER_USER_CONTROL" />, é perguntado ao utilizador se pretende utilizar a cópia de segurança e o restauro do Android. Se o utilizador ativar a cópia de segurança e o restauro, os dados de aplicações para Android são carregados para os servidores de cópia de segurança do Android e restaurados a partir dos mesmos após a reinstalação de aplicações compatíveis.</translation>
 <translation id="2757054304033424106">Tipos de extensões/aplicações com permissão para serem instaladas</translation>
 <translation id="2759224876420453487">Controlar o comportamento dos utilizadores numa sessão multiperfil</translation>
 <translation id="2761483219396643566">Atraso do aviso de inatividade quando o dispositivo está a utilizar a energia da bateria</translation>
@@ -683,10 +683,10 @@
       Se ativar esta definição, a Pré-visualização de impressão utiliza a impressora predefinida do SO como a escolha de destino predefinida.</translation>
 <translation id="2867699958489427143">Reverta e continue a utilizar a versão de destino se a versão do SO for mais recente do que a de destino. Efetue um Powerwash completo durante o processo.</translation>
 <translation id="2872961005593481000">Encerrar</translation>
-<translation id="2874209944580848064">Nota para os dispositivos <ph name="PRODUCT_OS_NAME" /> compatíveis com aplicações Android:</translation>
+<translation id="2874209944580848064">Nota para os dispositivos <ph name="PRODUCT_OS_NAME" /> compatíveis com aplicações para Android:</translation>
 <translation id="2877225735001246144">Desativar a procura de CNAME ao negociar a autenticação Kerberos</translation>
 <translation id="2893546967669465276">Enviar registos do sistema para o servidor de gestão</translation>
-<translation id="2899002520262095963">As aplicações Android podem utilizar as configurações de rede e os certificados da AC (Autoridade de certificação) definidos através desta política, mas não têm acesso a algumas opções de configuração.</translation>
+<translation id="2899002520262095963">As aplicações para Android podem utilizar as configurações de rede e os certificados da AC (Autoridade de certificação) definidos através desta política, mas não têm acesso a algumas opções de configuração.</translation>
 <translation id="290002216614278247">Permite bloquear a sessão do utilizador com base no tempo do cliente ou na quota de utilização do dia.
 
           |time_window_limit| especifica um intervalo diário durante o qual a sessão do utilizador deve ser bloqueada. Suportamos apenas uma regra para cada dia da semana, pelo que o tamanho da matriz de |entries| pode variar entre 0 e 7. |starts_at| e |ends_at| são o início e o fim do limite do intervalo; se |ends_at| for menor do que |starts_at|, significa que |time_limit_window| termina no dia seguinte. |last_updated_millis| é a data/hora UTC em que a entrada foi atualizada pela última vez. É enviado como uma string porque a data/hora não seria suportada como um número inteiro.
@@ -774,7 +774,7 @@
       É recomendado migrar os servidores para os conjuntos de cifras ECDHE. Se não estiverem disponíveis, certifique-se de que está ativado um conjunto de cifras que utilize a troca de chaves RSA.</translation>
 <translation id="316778957754360075">Esta definição foi removida a partir da versão 29 do <ph name="PRODUCT_NAME" />. A forma recomendada de configurar coleções de extensões/aplicações alojadas na entidade é incluir no alojamento do site os pacotes CRX em ExtensionInstallSources e colocar links de transferência diretos para os pacotes numa página Web. Pode ser criado um iniciador para essa página Web utilizando a política ExtensionInstallForcelist.</translation>
 <translation id="3185009703220253572">desde a versão <ph name="SINCE_VERSION" /></translation>
-<translation id="3187220842205194486">As aplicações Android não podem obter acesso a chaves empresariais. Esta política não tem qualquer efeito nas mesmas.</translation>
+<translation id="3187220842205194486">As aplicações para Android não podem obter acesso a chaves empresariais. Esta política não tem qualquer efeito nas mesmas.</translation>
 <translation id="3201273385265130876">Permite-lhe especificar o servidor proxy utilizado pelo <ph name="PRODUCT_NAME" /> e impede os utilizadores de alterarem as definições de proxy.
 
           Se optar por nunca utilizar um servidor proxy e por estabelecer sempre ligação diretamente, todas as outras opções são ignoradas.
@@ -1078,7 +1078,7 @@
       Os dispositivos com o <ph name="PRODUCT_OS_NAME" /> procuram automaticamente atualizações se esta definição não estiver configurada ou se estiver definida como Falsa.
 
       Aviso: recomenda-se manter as atualizações automáticas ativadas, para que os utilizadores recebam atualizações de software e correções de segurança críticas. Desativar as atualizações automáticas pode colocar os utilizadores em risco.</translation>
-<translation id="4020682745012723568">Não é possível aceder aos cookies transferidos para o perfil do utilizador nas aplicações Android.</translation>
+<translation id="4020682745012723568">Não é possível aceder aos cookies transferidos para o perfil do utilizador nas aplicações para Android.</translation>
 <translation id="402759845255257575">Não permitir que os sites executem JavaScript</translation>
 <translation id="4027608872760987929">Ativar o fornecedor de pesquisas personalizado</translation>
 <translation id="4039085364173654945">Controla se o subconteúdo de terceiros numa página tem permissão para apresentar uma caixa de diálogo de Autenticação Básica de HTTP. Normalmente, esta definição está desativada como uma defesa contra phishing. Se esta política não for definida, a definição será desativada e o subconteúdo de terceiros não terá permissão para apresentar uma caixa de diálogo de Autenticação Básica de HTTP.</translation>
@@ -1087,7 +1087,7 @@
 
       Quando esta política não está configurada ou definida como <ph name="GLS_DISABLED" />, os serviços de localização da Google estão desativados e não podem ser ativados pelo utilizador.
 
-      Quando esta política está definida como <ph name="GLS_UNDER_USER_CONTROL" />, é perguntado ao utilizador se pretende utilizar os serviços de localização da Google. Isto permite às aplicações Android utilizarem os serviços para consultar a localização do dispositivo e ativa o envio de dados de localização anónimos para a Google.
+      Quando esta política está definida como <ph name="GLS_UNDER_USER_CONTROL" />, é perguntado ao utilizador se pretende utilizar os serviços de localização da Google. Isto permite às aplicações para Android utilizarem os serviços para consultar a localização do dispositivo e ativa o envio de dados de localização anónimos para a Google.
 
       Tenha em atenção que esta política é ignorada e os serviços de localização da Google estão sempre desativados quando a política <ph name="DEFAULT_GEOLOCATION_SETTING_POLICY_NAME" /> estiver definida como <ph name="BLOCK_GEOLOCATION_SETTING" />.</translation>
 <translation id="408029843066770167">Permitir consultas a um serviço de hora da Google</translation>
@@ -1139,7 +1139,7 @@
 <translation id="423797045246308574">Permite definir uma lista de padrões de URL que especificam os sites não autorizados a utilizar a geração de chaves. Se um padrão do URL estiver incluído em "KeygenAllowedForUrls", essa política substitui estas exceções.
 
           Se esta política não for definida, é utilizado o valor global predefinido para todos os sites, seja a partir da política "DefaultKeygenSetting", se estiver definida, ou a partir da configuração pessoal do utilizador.</translation>
-<translation id="4239720644496144453">A cache não é utilizada para aplicações Android. Se vários utilizadores instalarem a mesma aplicação Android, é transferida uma nova para cada utilizador.</translation>
+<translation id="4239720644496144453">A cache não é utilizada para aplicações para Android. Se vários utilizadores instalarem a mesma aplicação Android, é transferida uma nova para cada utilizador.</translation>
 <translation id="4250680216510889253">Não</translation>
 <translation id="4261820385751181068">Local do ecrã de início de sessão do dispositivo</translation>
 <translation id="427220754384423013">Especifica as impressoras disponíveis para um utilizador.
@@ -1167,14 +1167,14 @@
 <translation id="4309640770189628899">Determinar se os conjuntos de cifras DHE no TLS estão ativados</translation>
 <translation id="4322842393287974810">Permitir que a aplicação de quiosque de início automático com atraso zero controle a versão do <ph name="PRODUCT_OS_NAME" /></translation>
 <translation id="4325690621216251241">Adicionar um botão para terminar sessão ao tabuleiro do sistema</translation>
-<translation id="4332177773549877617">Registar eventos para instalações de aplicações Android</translation>
+<translation id="4332177773549877617">Registar eventos para instalações de aplicações para Android</translation>
 <translation id="4346674324214534449">Permite-lhe definir se os anúncios devem ser bloqueados em sites com anúncios intrusivos.
 
       Se esta política estiver definida como 2, os anúncios são bloqueados em sites com anúncios intrusivos.
       No entanto, este comportamento não é acionado se a política SafeBrowsingEnabled estiver definida como falsa.
       Se esta política estiver definida como 1, os anúncios não são bloqueados em sites com anúncios intrusivos.
       Se esta política não for definida, é utilizado o valor 2.</translation>
-<translation id="4347908978527632940">Se estiver definida como verdadeira e o utilizador for um utilizador supervisionado, outras aplicações Android podem consultar as restrições Web do utilizador através de um fornecedor de conteúdos.
+<translation id="4347908978527632940">Se estiver definida como verdadeira e o utilizador for um utilizador supervisionado, outras aplicações para Android podem consultar as restrições Web do utilizador através de um fornecedor de conteúdos.
 
           Se estiver definida como falsa ou não estiver definida, o fornecedor de conteúdos não devolve informações.</translation>
 <translation id="435461861920493948">Contém uma lista de padrões utilizados para controlar a visibilidade das contas no <ph name="PRODUCT_NAME" />.
@@ -1214,7 +1214,7 @@
 <translation id="4454820008017317557">Apresentar o ícone da barra de ferramentas do <ph name="PRODUCT_NAME" /></translation>
 <translation id="4467952432486360968">Bloquear cookies de terceiros</translation>
 <translation id="4474167089968829729">Permitir guardar palavras-passe no gestor de palavras-passe</translation>
-<translation id="4476769083125004742">Se esta política estiver definida como <ph name="BLOCK_GEOLOCATION_SETTING" />, as aplicações Android não podem aceder às informações de localização. Se definir esta política com qualquer outro valor ou se a deixar por definir, é pedido a autorização ao utilizador quando uma aplicação Android pretender aceder a informações de localização.</translation>
+<translation id="4476769083125004742">Se esta política estiver definida como <ph name="BLOCK_GEOLOCATION_SETTING" />, as aplicações para Android não podem aceder às informações de localização. Se definir esta política com qualquer outro valor ou se a deixar por definir, é pedido a autorização ao utilizador quando uma aplicação Android pretender aceder a informações de localização.</translation>
 <translation id="4480694116501920047">Forçar Pesquisa Segura</translation>
 <translation id="4482640907922304445">Apresenta o botão Página Inicial na barra de ferramentas do <ph name="PRODUCT_NAME" />. Se ativar esta definição, o botão Página Inicial é sempre apresentado. Se desativar esta definição, o botão Página Inicial nunca é apresentado. Se ativar ou desativar esta definição, os utilizadores não a poderão alterar ou substituir no <ph name="PRODUCT_NAME" />. Se deixar esta política por definir, permitirá que o utilizador decida se pretende ou não apresentar o botão Página Inicial.</translation>
 <translation id="4483649828988077221">Desativar a atualização automática</translation>
@@ -1241,7 +1241,7 @@
       Se ativar ou desativar esta definição, os utilizadores não a poderão alterar ou substituir no <ph name="PRODUCT_NAME" />.
 
       Se deixar esta política por definir, a definição será ativada mas o utilizador poderá alterá-la.</translation>
-<translation id="4531706050939927436">As aplicações Android podem ser instaladas à força a partir da Consola do gestor do Google através do Google Play. Essas aplicações não utilizam esta política.</translation>
+<translation id="4531706050939927436">As aplicações para Android podem ser instaladas à força a partir da Consola do gestor do Google através do Google Play. Essas aplicações não utilizam esta política.</translation>
 <translation id="4534500438517478692">Nome de restrição Android:</translation>
 <translation id="4541530620466526913">Contas locais do dispositivo</translation>
 <translation id="4544079461524242527">Configura as definições de gestão de extensões do produto <ph name="PRODUCT_NAME" />.
@@ -1447,7 +1447,7 @@
 
       Se a política estiver definida como verdadeira ou não estiver especificada, os ciclos de vida dos separadores são ativados.</translation>
 <translation id="5208240613060747912">Permite definir uma lista de padrões de URL que especificam os Web sites não autorizados a apresentar notificações. Se esta política não for definida, será utilizado o valor global predefinido para todos os Web sites, seja a partir da política "DefaultNotificationsSetting", caso esteja definida, ou a partir da configuração pessoal do utilizador.</translation>
-<translation id="5219844027738217407">Para aplicações Android, esta política afeta apenas o microfone. Se esta política estiver definida como verdadeira, o som do microfone é desativado para todas as aplicações Android, sem exceções.</translation>
+<translation id="5219844027738217407">Para aplicações para Android, esta política afeta apenas o microfone. Se esta política estiver definida como verdadeira, o som do microfone é desativado para todas as aplicações para Android, sem exceções.</translation>
 <translation id="523505283826916779">Definições de acessibilidade</translation>
 <translation id="5247006254130721952">Bloquear transferências perigosas</translation>
 <translation id="5248863213023520115">Define os tipos de encriptação permitidos ao solicitar permissões Kerberos a um servidor do <ph name="MS_AD_NAME" />.
@@ -1521,7 +1521,7 @@
       Se a política estiver definida como falsa ou não definida, não são comunicadas quaisquer informações de estado.
       Se estiver definida como verdadeira, são comunicadas informações de estado.
 
-      Esta política aplica-se apenas se as aplicações Android estiverem ativadas.</translation>
+      Esta política aplica-se apenas se as aplicações para Android estiverem ativadas.</translation>
 <translation id="5395271912574071439">Ativa a proteção de anfitriões de acesso remoto enquanto existir uma ligação em progresso.
 
           Se esta definição estiver ativada, então, os dispositivos de entrada e saída físicos do anfitrião são desativados enquanto existir uma ligação remota em progresso.
@@ -1564,7 +1564,7 @@
 <translation id="5530347722229944744">Bloquear transferências potencialmente perigosas</translation>
 <translation id="5535973522252703021">Lista de permissões do servidor de delegação do Kerberos</translation>
 <translation id="555077880566103058">Permitir que todos os sites executem o plug-in <ph name="FLASH_PLUGIN_NAME" /> automaticamente</translation>
-<translation id="5559079916187891399">Esta política não tem qualquer efeito em aplicações Android.</translation>
+<translation id="5559079916187891399">Esta política não tem qualquer efeito em aplicações para Android.</translation>
 <translation id="5560039246134246593">Adiciona um parâmetro à obtenção da semente Variações em <ph name="PRODUCT_NAME" />.
 
       Se estiver especificada, irá adicionar um parâmetro de consulta denominado "restrito" ao URL utilizado para obter a semente Variações. O valor do parâmetro será o valor especificado nesta política.
@@ -1585,7 +1585,7 @@
       Tenha em atenção que esta ação não é recomendada, dado que pode permitir ignorar a extensão nameConstraints que restringe os nomes de anfitriões para os quais um determinado certificado pode ser autorizado.
 
       Se esta política não estiver definida ou for definida como falsa, os certificados de servidor que não possuam uma extensão subjectAlternativeName com um nome DNS ou um endereço IP não serão fidedignos.</translation>
-<translation id="5584132346604748282">Controlar os serviços de localização da Google para aplicações Android.</translation>
+<translation id="5584132346604748282">Controlar os serviços de localização da Google para aplicações para Android.</translation>
 <translation id="5586942249556966598">Não fazer nada</translation>
 <translation id="5630352020869108293">Restaurar a última sessão</translation>
 <translation id="5645779841392247734">Permitir cookies nestes sites</translation>
@@ -1662,7 +1662,7 @@
 <translation id="5893553533827140852">Se esta definição estiver ativada, os pedidos de autenticação gnubby serão utilizados com proxy numa ligação de anfitrião remoto.
 
           Se esta definição estiver desativada ou não estiver configurada, os pedidos de autenticação não serão utilizados com proxy.</translation>
-<translation id="5898486742390981550">Quando vários utilizadores têm sessão iniciada, apenas o utilizador principal pode utilizar aplicações Android.</translation>
+<translation id="5898486742390981550">Quando vários utilizadores têm sessão iniciada, apenas o utilizador principal pode utilizar aplicações para Android.</translation>
 <translation id="5906199912611534122">Permite a ativação ou a desativação do controlo de rede.
       Aplica-se a todos os utilizadores e a todas as interfaces no dispositivo. Depois de definido,
       o controlo mantém-se até a política ser alterada de modo a desativá-lo.
@@ -1680,7 +1680,7 @@
 
           Se esta política não for definida, o cursor grande é desativado quando o ecrã de início de sessão é mostrado pela primeira vez. Os utilizadores podem ativar ou desativar o cursor grande a qualquer momento e o seu estado no ecrã de início de sessão persiste entre utilizadores.</translation>
 <translation id="5929855945144989709">Permitir aos dispositivos a execução de máquinas virtuais no Chrome OS</translation>
-<translation id="5932767795525445337">Também é possível utilizar esta política para fixar aplicações Android.</translation>
+<translation id="5932767795525445337">Também é possível utilizar esta política para fixar aplicações para Android.</translation>
 <translation id="5936622343001856595">Força a execução de consultas na Pesquisa Web do Google através da Pesquisa Segura definida como ativada e impede os utilizadores de alterar esta definição.
 
       Se ativar esta definição, a Pesquisa Segura na Pesquisa do Google estará sempre ativa.
@@ -1702,7 +1702,7 @@
 <translation id="6022948604095165524">Ação no arranque</translation>
 <translation id="6023030044732320798">Especifica um conjunto de políticas que são transmitidas ao tempo de execução ARC. O valor tem de ser um formato JSON válido.
 
-      É possível utilizar esta política para configurar quais as aplicações Android automaticamente instaladas no dispositivo:
+      É possível utilizar esta política para configurar quais as aplicações para Android automaticamente instaladas no dispositivo:
 
       {
         "type": "object",
@@ -1831,15 +1831,15 @@
 <translation id="6392973646875039351">Ativa a funcionalidade de Preenchimento Automático do <ph name="PRODUCT_NAME" /> e permite que os utilizadores preencham automaticamente formulários Web utilizando informações anteriormente armazenadas, como endereços ou dados de cartões de crédito. Se desativar esta definição, os utilizadores não poderão aceder à funcionalidade de Preenchimento Automático. Se ativar esta definição ou não definir qualquer valor, os utilizadores poderão controlar o Preenchimento Automático, o que lhes permitirá configurar perfis de Preenchimento Automático e ligar ou desligar esta funcionalidade conforme pretendam.</translation>
 <translation id="6394350458541421998">Esta política foi removida a partir da versão 29 do <ph name="PRODUCT_OS_NAME" />. Em vez disso, utilize a política PresentationScreenDimDelayScale.</translation>
 <translation id="6401669939808766804">Terminar a sessão do utilizador</translation>
-<translation id="6426205278746959912">Não pode forçar as aplicações Android a utilizar um proxy. É disponibilizado um subconjunto de definições de proxy para aplicações Android, que estas podem optar voluntariamente por aceitar:
+<translation id="6426205278746959912">Não pode forçar as aplicações para Android a utilizar um proxy. É disponibilizado um subconjunto de definições de proxy para aplicações para Android, que estas podem optar voluntariamente por aceitar:
 
-          Se escolher nunca utilizar um servidor proxy, as aplicações Android são informadas de que não existe nenhum proxy configurado.
+          Se escolher nunca utilizar um servidor proxy, as aplicações para Android são informadas de que não existe nenhum proxy configurado.
 
-          Se escolher utilizar as definições de proxy do sistema ou um servidor proxy fixo, as aplicações Android recebem o endereço e a porta do servidor proxy HTTP.
+          Se escolher utilizar as definições de proxy do sistema ou um servidor proxy fixo, as aplicações para Android recebem o endereço e a porta do servidor proxy HTTP.
 
-          Se escolher detetar automaticamente o servidor proxy, é fornecido o URL "http://wpad/wpad.dat" do script às aplicações Android. Não é utilizada mais nenhuma parte do protocolo de deteção automática do proxy.
+          Se escolher detetar automaticamente o servidor proxy, é fornecido o URL "http://wpad/wpad.dat" do script às aplicações para Android. Não é utilizada mais nenhuma parte do protocolo de deteção automática do proxy.
 
-          Se escolher utilizar um script de proxy .pac, o URL do script é fornecido às aplicações Android.</translation>
+          Se escolher utilizar um script de proxy .pac, o URL do script é fornecido às aplicações para Android.</translation>
 <translation id="6440051664870270040">Permitir que os sites naveguem e abram pop-ups em simultâneo</translation>
 <translation id="6447948611083700881">A cópia de segurança e o restauro estão desativados.</translation>
 <translation id="645425387487868471">Ativar o início de sessão forçado no <ph name="PRODUCT_NAME" /></translation>
@@ -1863,7 +1863,7 @@
 
           O valor da política deve ser especificado em milissegundos. Os valores devem ser inferiores ao atraso de inatividade.</translation>
 <translation id="6536600139108165863">Reinicialização automática no encerramento do dispositivo</translation>
-<translation id="6539246272469751178">Esta política não tem qualquer efeito em aplicações Android. As aplicações Android utilizam sempre o diretório de transferências predefinido e não podem aceder a quaisquer ficheiros transferidos pelo <ph name="PRODUCT_OS_NAME" /> para um diretório de transferências não predefinido.</translation>
+<translation id="6539246272469751178">Esta política não tem qualquer efeito em aplicações para Android. As aplicações para Android utilizam sempre o diretório de transferências predefinido e não podem aceder a quaisquer ficheiros transferidos pelo <ph name="PRODUCT_OS_NAME" /> para um diretório de transferências não predefinido.</translation>
 <translation id="654303922206238013">Estratégia de migração de ecryptfs</translation>
 <translation id="6544897973797372144">Se esta política for definida como Verdadeira e a política ChromeOsReleaseChannel não estiver especificada, os utilizadores do domínio inscrito serão autorizados a alterar o canal de lançamento do dispositivo. Se esta política for definida como Falsa, o dispositivo será bloqueado no último canal em que foi definido.
 
@@ -2297,7 +2297,7 @@
 
       Se esta política não for definida, será utilizado o tamanho predefinido e o utilizador poderá substituí-lo com a sinalização "--disk-cache-size".</translation>
 <translation id="759957074386651883">Definições da Navegação segura</translation>
-<translation id="7604169113182304895">As aplicações Android podem escolher voluntariamente aceitar esta lista. Não as pode forçar a aceitá-la.</translation>
+<translation id="7604169113182304895">As aplicações para Android podem escolher voluntariamente aceitar esta lista. Não as pode forçar a aceitá-la.</translation>
 <translation id="7612157962821894603">Sinalizadores ao nível do sistema a aplicar ao arranque do <ph name="PRODUCT_NAME" /></translation>
 <translation id="7614663184588396421">Lista dos esquemas de protocolos desativados</translation>
 <translation id="7617319494457709698">Esta política especifica as extensões com permissão para utilizar a função <ph name="CHALLENGE_USER_KEY_FUNCTION" /> da <ph name="ENTERPRISE_PLATFORM_KEYS_API" /> para a comprovação remota. As extensões têm de ser adicionadas a esta lista para poderem utilizar a API.
@@ -2595,7 +2595,7 @@
 
       O objetivo é remover esta substituição no futuro.</translation>
 <translation id="8285435910062771358">Lupa em ecrã inteiro ativada</translation>
-<translation id="8288199156259560552">Ativar os serviços de localização da Google para aplicações Android</translation>
+<translation id="8288199156259560552">Ativar os serviços de localização da Google para aplicações para Android</translation>
 <translation id="8294750666104911727">Normalmente, as páginas com X-UA-Compatible definido como chrome=1 serão processadas em <ph name="PRODUCT_FRAME_NAME" />, independentemente da política "ChromeFrameRendererSettings".
 
           Se ativar esta definição, não serão procuradas metatags nas páginas.
@@ -2688,7 +2688,7 @@
 
       As alterações à política apenas são aplicadas enquanto o ARC não estiver em execução, por exemplo, durante o arranque do Chrome OS.</translation>
 <translation id="8631434304112909927">até à versão <ph name="UNTIL_VERSION" /></translation>
-<translation id="863319402127182273">Para aplicações Android, esta política afeta apenas a câmara integrada. Se esta política for definida como verdadeira, a câmara é desativada para todas as aplicações Android, sem exceções.</translation>
+<translation id="863319402127182273">Para aplicações para Android, esta política afeta apenas a câmara integrada. Se esta política for definida como verdadeira, a câmara é desativada para todas as aplicações para Android, sem exceções.</translation>
 <translation id="8649763579836720255">Os dispositivos Chrome OS podem utilizar a comprovação remota (Acesso confirmado) para obter um certificado emitido pela AC do Chrome OS que declara que o dispositivo é elegível para reproduzir conteúdo protegido. Este processo envolve o envio de informações de garantia de hardware para a AC do Chrome OS, que identifica de forma única o dispositivo.
 
           Se esta definição for falsa, o dispositivo não utilizará a comprovação remota para proteção de conteúdo e o dispositivo poderá não conseguir reproduzir conteúdo protegido.
@@ -2852,7 +2852,7 @@
 <translation id="9088444059179765143">Configurar o método de deteção automática do fuso horário</translation>
 <translation id="9096086085182305205">Lista de permissões do servidor de autenticação</translation>
 <translation id="9098553063150791878">Políticas para a autenticação HTTP</translation>
-<translation id="9105265795073104888">Apenas é disponibilizado um subconjunto de opções de configuração de proxy para aplicações Android. As aplicações Android podem optar voluntariamente por utilizar o proxy. Não as pode forçar a utilizar um proxy.</translation>
+<translation id="9105265795073104888">Apenas é disponibilizado um subconjunto de opções de configuração de proxy para aplicações para Android. As aplicações para Android podem optar voluntariamente por utilizar o proxy. Não as pode forçar a utilizar um proxy.</translation>
 <translation id="9106865192244721694">Permitir WebUSB nestes sites</translation>
 <translation id="9112727953998243860">Ficheiro de configuração de impressoras empresariais</translation>
 <translation id="9112897538922695510">Permite-lhe registar uma lista de controladores de protocolos. Esta apenas pode ser uma política recomendada. A propriedade |protocol| deve ser definida para um esquema como "mailto" e a propriedade |url| deve ser definida para o padrão do URL da aplicação que controla o esquema. O padrão pode incluir um "%s" que, caso esteja presente, é substituído pelo URL controlado.
diff --git a/components/policy/resources/policy_templates_ru.xtb b/components/policy/resources/policy_templates_ru.xtb
index 2ce78cc..d3f54f6a 100644
--- a/components/policy/resources/policy_templates_ru.xtb
+++ b/components/policy/resources/policy_templates_ru.xtb
@@ -225,6 +225,13 @@
       Если поддерживать совместимость с неисправным сервером необходимо, установите значение tls1.1. Однако помните, что это временная мера и ошибки на сервере следует устранить как можно скорее.</translation>
 <translation id="1864269674877167562">Если правило не настроено или его значение не задано, <ph name="PRODUCT_OS_NAME" /> не будет включать автозаполнение в процессе входа в аккаунт.
       Если вы укажете в качестве значения доменное имя, <ph name="PRODUCT_OS_NAME" /> включит автозаполнение. После этого при входе в аккаунт можно будет вводить только имя пользователя (без домена). При необходимости пользователь сможет указать другой домен вместо предложенного.</translation>
+<translation id="1864382791685519617">Правило включает предварительное определение сети в <ph name="PRODUCT_NAME" /> и запрещает пользователям менять эту настройку
+
+      Это позволяет контролировать не только упреждающее чтение DNS, но и упреждающее подключение по протоколам TCP и SSL, а также предварительную визуализацию веб-страниц.
+
+      Если это правило включено, никто, кроме вас, не сможет изменить его в <ph name="PRODUCT_NAME" />.
+
+      Если не настраивать это правило, предварительное определение сети будет включено, но у пользователей будет возможность выключить его.</translation>
 <translation id="1865417998205858223">Позволяет разрешать или запрещать использование ключей</translation>
 <translation id="186719019195685253">Действие в случае превышения времени бездействия при работе от сети.</translation>
 <translation id="187819629719252111">Открывает доступ к локальным файлам на компьютере, разрешая <ph name="PRODUCT_NAME" /> показывать окна выбора файлов. Если этот параметр включен, пользователи могут открывать окна выбора файлов в обычном режиме. Если параметр отключен и пользователь выполняет действия, для которых нужно открыть окно выбора файла (например, импорт закладок, загрузка файлов, сохранение ссылок и т. д.), вместо окна отображается сообщение и предполагается, что пользователь нажал кнопку "Отмена" в окне выбора файлов. Если этот параметр не задан, пользователи могут открывать окна выбора файлов в обычном режиме.</translation>
@@ -676,6 +683,7 @@
       Если правило не настроено, используется параметр <ph name="PRINTERS_ALLOW_ALL" />.
       </translation>
 <translation id="2908277604670530363">Максимальное количество одновременных подключений к прокси-серверу</translation>
+<translation id="2951386431828317490">Правило включает автозаполнение профилей</translation>
 <translation id="2956777931324644324">Это правило не используется, начиная с версии <ph name="PRODUCT_NAME" /> 36.
 
       Оно определяет, использовать ли TLS-расширение для сертификатов, привязанных к домену.
@@ -684,6 +692,7 @@
 <translation id="2957506574938329824">Запретить всем сайтам запрашивать доступ к Bluetooth-устройствам через Web Bluetooth API</translation>
 <translation id="2957513448235202597">Тип аккаунта для аутентификации <ph name="HTTP_NEGOTIATE" /></translation>
 <translation id="2959898425599642200">Правила игнорирования прокси-серверов</translation>
+<translation id="2960128438010718932">Правило задает график поэтапного обновления</translation>
 <translation id="2960691910306063964">Включает/отключает аутентификацию без PIN-кода для хостов удаленного доступа</translation>
 <translation id="2976002782221275500">Указывает, через какое время бездействия экран затемняется при работе от батареи.
 
@@ -724,6 +733,7 @@
       Какой бы ни был задан параметр для правила, пользователи не могут менять настройки оптимизации WPAD.</translation>
 <translation id="3072045631333522102">Экранная заставка, используемая для экрана входа в коммерческой версии</translation>
 <translation id="3072847235228302527">Установить Условия использования локального аккаунта</translation>
+<translation id="3077183141551274418">Правило включает или отключает жизненный цикл вкладки</translation>
 <translation id="3086995894968271156">Настройка ресивера Cast в <ph name="PRODUCT_NAME" />.</translation>
 <translation id="3088796212846734853">Правило позволяет задать список шаблонов URL для сайтов, которым разрешено показывать изображения.
 
@@ -1274,6 +1284,11 @@
       Предложенные страницы загружаются с серверов Google.
 
       Если для правила задано значение False, подсказки появляться не будут.</translation>
+<translation id="4788252609789586009">Правило включает в <ph name="PRODUCT_NAME" /> функцию автозаполнения и разрешает пользователям автоматически заполнять веб-формы, используя ранее сохраненные данные кредитной карты.
+
+      Если правило отключено, пользователи не будут видеть предложение заполнить платежную информацию автоматически. Данные кредитных карт, которые пользователи указывают на веб-сайтах, также сохраняться не будут.
+
+      Если правило включено или его значение не указано, пользователи смогут сами управлять автозаполнением платежных данных через интерфейс.</translation>
 <translation id="4791031774429044540">Включение или отключение большого курсора.
 
           Если для правила задано значение "true", большой курсор будет всегда включен.
@@ -1398,6 +1413,11 @@
       Если эта политика включена, <ph name="PRODUCT_OS_NAME" /> не позволит устройству загружаться в режиме разработчика. При попытке выбрать такой режим будет показано сообщение об ошибке.
 
       Если эта политика выключена или не настроена, режим разработчика на данном устройстве останется доступным.</translation>
+<translation id="520403427390290017">Функция жизненного цикла вкладок оптимизирует использование ЦП и памяти, проверяя запущенные вкладки, которые долго не используются. Сначала вкладки приостанавливаются, потом отключаются.
+
+      Если для правила установлено значение false, функция отключается, и все вкладки работают в обычном режиме.
+
+      Если установлено значение true или правило не настроено, функция жизненного цикла вкладок включена.</translation>
 <translation id="5208240613060747912">Задает список шаблонов URL для сайтов, которым запрещено отображать уведомления. Если это правило не настроено, для всех сайтов используется глобальное значение по умолчанию на основе правила DefaultNotificationsSetting (если оно настроено, в противном случае – на основе пользовательской конфигурации).</translation>
 <translation id="5219844027738217407">Для приложений Android это правило влияет только на доступ к микрофону. Если для правила задано значение True, для всех без исключения приложений Android микрофон будет недоступен.</translation>
 <translation id="523505283826916779">Настройки специальных возможностей</translation>
@@ -1443,6 +1463,11 @@
 
           Если выбрать значение False, пользователи не смогут транслировать контент на свои устройства. Чтобы разрешить это делать, укажите значение True. Когда правило не настроено, транслировать контент на зарегистрированные устройства с Chrome OS нельзя, но можно использовать другие устройства.</translation>
 <translation id="5330684698007383292">Типы содержания, которые <ph name="PRODUCT_FRAME_NAME" /> может обрабатывать</translation>
+<translation id="5360146044009867539">Правило включает в <ph name="PRODUCT_NAME" /> функцию автозаполнения и разрешает пользователям автоматически заполнять профили и данные об адресе в веб-формах, используя ранее сохраненную информацию.
+
+      Если правило отключено, пользователи не будут видеть предложение внести информацию автоматически. Данные об адресе, которые пользователи указывают на веб-сайтах, также сохраняться не будут.
+
+      Если правило включено или его значение не указано, пользователи смогут сами управлять автозаполнением через пользовательский интерфейс.</translation>
 <translation id="5365946944967967336">Отображать кнопку "Главная страница" на панели инструментов</translation>
 <translation id="5366745336748853475">Позволяет указать список шаблонов URL тех сайтов, для которых сертификат клиента будет автоматически выбран на экране входа во фрейме с потоком SAML (если сайту требуется сертификат). Например, можно настроить, чтобы сертификат для устройств предоставлялся поставщику услуг SAML.
 
@@ -2122,6 +2147,15 @@
 
           Если данный параметр отключен, эта функция недоступна.</translation>
 <translation id="7275334191706090484">Управляемые закладки</translation>
+<translation id="729492886167634859">Правило позволяет задать список процентных величин, определяющий долю устройств <ph name="PRODUCT_OS_NAME" /> в организации, которые будут обновляться еженедельно после обнаружения обновления. Обнаружение обновлений происходит после их публикации, поэтому между появлением обновлений и проверкой их наличия может пройти время.
+
+      N-ное значение в списке используется для определения количества устройств, которые должны быть обновлены в течение N-ной недели после обнаружения обновления. Например, если обновление обнаружено сегодня, первое значение списка определяет долю устройств в организации, которые должны обновиться в течение недели с сегодняшнего дня. Второе значение – долю устройств, которые должны обновиться в течение 2 недель и т. д.
+
+      Если для этого правила задано значение, обновления будут выполняться в соответствии с этим правилом независимо от значения правила <ph name="DEVICE_UPDATE_SCATTER_FACTOR_POLICY_NAME" />.
+
+      Если в списке нет ни одного значения, обновления будут применяться в соответствии остальными правилами, действующими на устройстве.
+
+      Это правило не применяется к переключению каналов.</translation>
 <translation id="7295019613773647480">Включить контролируемые профили</translation>
 <translation id="7301543427086558500">Задает список альтернативных URL, которые могут использоваться для извлечения запросов из поисковой системы. Для выполнения этой функции URL должен содержать строку <ph name="SEARCH_TERM_MARKER" />.
 
@@ -2574,6 +2608,12 @@
 
           Примеры шаблонов приведены здесь: http://www.chromium.org/developers/how-tos/chrome-frame-getting-started.</translation>
 <translation id="8493645415242333585">Отключить сохранение истории браузера</translation>
+<translation id="8498293625012059298">Правило определяет адрес страницы, на которой пользователь меняет пароль (только для протоколов HTTP и HTTPS). Служба защиты паролей перенаправляет пользователей на указанную страницу, чтобы изменить пароль после появления предупреждения в браузере.
+      Чтобы сервис "<ph name="PRODUCT_NAME" />" корректно сохранил новый цифровой отпечаток, страница смены пароля должна соответствовать требованиям, перечисленным на странице https://www.chromium.org/developers/design-documents/create-amazing-password-forms.
+
+      Если правило включено, служба защиты паролей перенаправляет пользователей на указанный URL, чтобы изменить пароль после появления предупреждения в браузере.
+       Если правило отключено или не настроено, служба защиты паролей перенаправляет пользователей на страницу https://myaccounts.google.com.
+      Правило недоступно на устройствах Windows, не входящих в домен <ph name="MS_AD_NAME" />.</translation>
 <translation id="8499172469244085141">Настройки по умолчанию (пользователи могут менять)</translation>
 <translation id="8507835864888987300">Правило позволяет задать префикс целевой версии для обновления <ph name="PRODUCT_OS_NAME" />.
 
@@ -2627,6 +2667,14 @@
       При смене значения на False настройки начинают применяться к новым виртуальным машинам, не останавливая работу уже запущенных.
       Если правило не задано на управляемом устройстве, то ему запрещено запускать виртуальные машины.
       Устройствам, которые не управляются удаленно, разрешено запускать виртуальные машины.</translation>
+<translation id="8669669491594628013">Правило позволяет управлять триггером, при срабатывании которого пользователь получает предупреждение от службы защиты паролей о повторном вводе пароля на подозрительном сайте.
+
+      Для определения пароля, нуждающегося в защите, можно использовать правила PasswordProtectionLoginURLs и PasswordProtectionChangePasswordURL.
+
+       Если установлено значение PasswordProtectionWarningOff, предупреждения не появляются.
+       Если установлено значение PasswordProtectionWarningOnPasswordReuse, предупреждение от службы защиты паролей появляется, когда пользователь повторно вводит пароль Google на сайте, не внесенном в белый список.
+       Если установлено значение PasswordProtectionWarningOnPhishingReuse, предупреждение от службы защиты паролей появляется, когда пользователь повторно вводит пароль Google на фишинговом сайте.
+      Если значение не установлено, предупреждение от службы защиты паролей появляется при повторном вводе пароля Google на фишинговом сайте, но пользователь может изменить эту настройку самостоятельно.</translation>
 <translation id="8672321184841719703">Выбор версии автообновления</translation>
 <translation id="867410340948518937">U2F (Universal Second Factor)</translation>
 <translation id="8685024486845674965">Предупреждение от защиты паролем срабатывает при повторном использовании пароля</translation>
diff --git a/components/resources/nux_google_apps.grdp b/components/resources/nux_google_apps.grdp
index 0218fa6..58f9f8f 100644
--- a/components/resources/nux_google_apps.grdp
+++ b/components/resources/nux_google_apps.grdp
@@ -2,6 +2,8 @@
 <grit-part>
   <include name="IDR_NUX_GOOGLE_APPS_HTML" file="../nux_google_apps/resources/nux_google_apps.html" type="BINDATA" />
   <include name="IDR_NUX_GOOGLE_APPS_JS" file="../nux_google_apps/resources/nux_google_apps.js" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_PROXY_HTML" file="../nux_google_apps/resources/nux_google_apps_proxy.html" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_PROXY_JS" file="../nux_google_apps/resources/nux_google_apps_proxy.js" type="BINDATA" />
   <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="../nux_google_apps/resources/apps_chooser.html" type="BINDATA" />
   <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="../nux_google_apps/resources/apps_chooser.js" type="BINDATA" />
   <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="../nux_google_apps/resources/chrome_store_24dp_1x.png" type="BINDATA" />
diff --git a/components/strings/components_strings_am.xtb b/components/strings/components_strings_am.xtb
index 8743798..be5b6f8f 100644
--- a/components/strings/components_strings_am.xtb
+++ b/components/strings/components_strings_am.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">ተጨማሪ ዝርዝሮችን ያቅርቡ</translation>
 <translation id="1021110881106174305">ተቀባይነት ያላቸው ካርዶች</translation>
 <translation id="1032854598605920125">በሰዓት አቅጣጫ አሽከርክር</translation>
-<translation id="1035334672863811645">ወደ Chrome ይግቡ</translation>
 <translation id="1038842779957582377">ያልታወቀ ስም</translation>
 <translation id="1050038467049342496">ሌሎች መተግበሪያዎችን ይዝጉ</translation>
 <translation id="1055184225775184556">&amp;አክልን ቀልብስ</translation>
diff --git a/components/strings/components_strings_ar.xtb b/components/strings/components_strings_ar.xtb
index 496b20c..bb1b696b 100644
--- a/components/strings/components_strings_ar.xtb
+++ b/components/strings/components_strings_ar.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">تقديم تفاصيل إضافية</translation>
 <translation id="1021110881106174305">البطاقات المقبولة</translation>
 <translation id="1032854598605920125">تدوير في اتجاه عقارب الساعة</translation>
-<translation id="1035334672863811645">‏تسجيل الدخول إلى Chrome</translation>
 <translation id="1038842779957582377">اسم غير معروف</translation>
 <translation id="1050038467049342496">إغلاق التطبيقات الأخرى</translation>
 <translation id="1055184225775184556">تراجع عن الإ&amp;ضافة</translation>
@@ -584,6 +583,7 @@
 <translation id="5089810972385038852">بلد/دولة</translation>
 <translation id="5094747076828555589">‏هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان غير موثوقة من قبل Chromium. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض الاتصال.</translation>
 <translation id="5095208057601539847">الإقليم</translation>
+<translation id="5098332213681597508">‏هذا الاسم من حسابك على Google.</translation>
 <translation id="5115563688576182185">(64 بت)</translation>
 <translation id="5121084798328133320">‏بعد التأكيد، ستتم مشاركة تفاصيل البطاقة من حساب دفعات Google مع هذا الموقع.</translation>
 <translation id="5128122789703661928">الجلسة التي تحمل هذا الاسم غير صالحة للحذف.</translation>
@@ -669,6 +669,7 @@
 <translation id="5633066919399395251">يمكن حاليًا للمهاجمين على <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> محاولة تثبيت برامج خطيرة على الكمبيوتر تسرق أو تحذف معلوماتك (على سبيل المثال، الصور، وكلمات المرور، والرسائل، وبطاقات الائتمان). <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="563324245173044180">تم حظر المحتوى المُضلّل.</translation>
 <translation id="5659593005791499971">البريد الإلكتروني</translation>
+<translation id="5666899935841546222">هل ترغب في الاحتفاظ بجميع بطاقاتك في مكانٍ واحد؟</translation>
 <translation id="5675650730144413517">يتعذّر على هذه الصفحة العمل</translation>
 <translation id="5685654322157854305">إضافة عنوان الشحن</translation>
 <translation id="5689199277474810259">‏تصدير إلى JSON</translation>
diff --git a/components/strings/components_strings_bg.xtb b/components/strings/components_strings_bg.xtb
index b34f24ff..e6a686ac9 100644
--- a/components/strings/components_strings_bg.xtb
+++ b/components/strings/components_strings_bg.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Въвеждане на допълнителни подробности</translation>
 <translation id="1021110881106174305">Приемани карти</translation>
 <translation id="1032854598605920125">Завъртане по часовниковата стрелка</translation>
-<translation id="1035334672863811645">Влезте в Chrome</translation>
 <translation id="1038842779957582377">неизвестно име</translation>
 <translation id="1050038467049342496">Затворете другите приложения.</translation>
 <translation id="1055184225775184556">&amp;Отмяна на добавянето</translation>
diff --git a/components/strings/components_strings_bn.xtb b/components/strings/components_strings_bn.xtb
index 25b515a3..ce1d988 100644
--- a/components/strings/components_strings_bn.xtb
+++ b/components/strings/components_strings_bn.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">অতিরিক্ত বিবরণ দিন</translation>
 <translation id="1021110881106174305">এই কার্ডগুলি গ্রহণ করা হয়</translation>
 <translation id="1032854598605920125">ঘড়ির কাঁটার দিকে ঘোরান</translation>
-<translation id="1035334672863811645">Chrome এ প্রবেশ করুন</translation>
 <translation id="1038842779957582377">অজানা নাম</translation>
 <translation id="1050038467049342496">অন্যান্য অ্যাপ্লিকেশানগুলি বন্ধ করুন</translation>
 <translation id="1055184225775184556">&amp;যোগ করাকে পূর্বাবস্থায় ফেরান</translation>
@@ -585,6 +584,7 @@
 <translation id="5089810972385038852">রাজ্য</translation>
 <translation id="5094747076828555589">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা শংসাপত্রটি Chromium এর নিকট বিশ্বাসযোগ্য নয়। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
 <translation id="5095208057601539847">প্রদেশ</translation>
+<translation id="5098332213681597508">এই নামটি আপনার Google অ্যাকাউন্ট থেকে।</translation>
 <translation id="5115563688576182185">(৬৪-বিট)</translation>
 <translation id="5121084798328133320">আপনি নিশ্চিত করার পর আপনার Google অর্থ প্রদান অ্যাকাউন্ট থেকে কার্ডের বিবরণ এই সাইটে শেয়ার করা হবে।</translation>
 <translation id="5128122789703661928">এই নামের সেশনটি মুছে ফেলার জন্য সঠিক নয়।</translation>
@@ -670,6 +670,7 @@
 <translation id="5633066919399395251"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> এ যে আক্রমণকারীরা এই মুহূর্তে সক্রিয় আছে, তারা আপনার কম্পিউটারে এমন বিপজ্জনক প্রোগ্রাম ইনস্টল করে দিতে পারে যেগুলি আপনার তথ্যের (যেমন ফটো, পাসওয়ার্ড, মেসেজ এবং ক্রেডিট কার্ড) ক্ষতি করতে বা সেগুলি চুরি করতে পারে। <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="563324245173044180">প্রতারণামূলক কন্টেন্ট ব্লক করা হয়েছে।</translation>
 <translation id="5659593005791499971">ইমেল</translation>
+<translation id="5666899935841546222">আপনি এক জায়গায় আপনার সমস্ত কার্ড রাখতে চান?</translation>
 <translation id="5675650730144413517">এই পৃষ্ঠাটি কাজ করছে না</translation>
 <translation id="5685654322157854305">শিপিং ঠিকানা যোগ করুন</translation>
 <translation id="5689199277474810259">JSON এ রপ্তানি করুন</translation>
diff --git a/components/strings/components_strings_ca.xtb b/components/strings/components_strings_ca.xtb
index c3f4dc5..70c8e7cf 100644
--- a/components/strings/components_strings_ca.xtb
+++ b/components/strings/components_strings_ca.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Proporcioneu més informació</translation>
 <translation id="1021110881106174305">Targetes acceptades</translation>
 <translation id="1032854598605920125">Gira en el sentit de les agulles del rellotge</translation>
-<translation id="1035334672863811645">Inicia la sessió a Chrome</translation>
 <translation id="1038842779957582377">nom desconegut</translation>
 <translation id="1050038467049342496">Tanca altres aplicacions</translation>
 <translation id="1055184225775184556">&amp;Desfés l'addició</translation>
diff --git a/components/strings/components_strings_cs.xtb b/components/strings/components_strings_cs.xtb
index 385df808..0926d6f 100644
--- a/components/strings/components_strings_cs.xtb
+++ b/components/strings/components_strings_cs.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Zadejte další podrobnosti</translation>
 <translation id="1021110881106174305">Přijímané karty</translation>
 <translation id="1032854598605920125">Otočit ve směru hodinových ručiček</translation>
-<translation id="1035334672863811645">přihlaste se do Chromu</translation>
 <translation id="1038842779957582377">neznámé jméno</translation>
 <translation id="1050038467049342496">Zavřete ostatní aplikace</translation>
 <translation id="1055184225775184556">&amp;Vrátit přidání zpět</translation>
diff --git a/components/strings/components_strings_da.xtb b/components/strings/components_strings_da.xtb
index 067df31d..77619f6 100644
--- a/components/strings/components_strings_da.xtb
+++ b/components/strings/components_strings_da.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Angiv yderligere oplysninger</translation>
 <translation id="1021110881106174305">Accepterede kort</translation>
 <translation id="1032854598605920125">Rotér med uret</translation>
-<translation id="1035334672863811645">log ind på Chrome</translation>
 <translation id="1038842779957582377">ukendt navn</translation>
 <translation id="1050038467049342496">Luk andre apps</translation>
 <translation id="1055184225775184556">&amp;Fortryd tilføjelse</translation>
diff --git a/components/strings/components_strings_de.xtb b/components/strings/components_strings_de.xtb
index 6d65a29a..c37f84e 100644
--- a/components/strings/components_strings_de.xtb
+++ b/components/strings/components_strings_de.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Weitere Details angeben</translation>
 <translation id="1021110881106174305">Akzeptierte Karten</translation>
 <translation id="1032854598605920125">Im Uhrzeigersinn drehen</translation>
-<translation id="1035334672863811645">In Chrome anmelden</translation>
 <translation id="1038842779957582377">Unbekannter Name</translation>
 <translation id="1050038467049342496">Andere Apps schließen</translation>
 <translation id="1055184225775184556">&amp;Hinzufügen rückgängig machen</translation>
diff --git a/components/strings/components_strings_el.xtb b/components/strings/components_strings_el.xtb
index 96fd7e8..5c274415 100644
--- a/components/strings/components_strings_el.xtb
+++ b/components/strings/components_strings_el.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Καταχωρίστε επιπλέον λεπτομέρειες</translation>
 <translation id="1021110881106174305">Αποδεκτές κάρτες</translation>
 <translation id="1032854598605920125">Περιστροφή προς τα δεξιά</translation>
-<translation id="1035334672863811645">σύνδεση στο Chrome</translation>
 <translation id="1038842779957582377">άγνωστο όνομα</translation>
 <translation id="1050038467049342496">Κλείστε τις άλλες εφαρμογές</translation>
 <translation id="1055184225775184556">&amp;Αναίρεση προσθήκης</translation>
diff --git a/components/strings/components_strings_en-GB.xtb b/components/strings/components_strings_en-GB.xtb
index 9d65128..6335b87 100644
--- a/components/strings/components_strings_en-GB.xtb
+++ b/components/strings/components_strings_en-GB.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Provide additional details.</translation>
 <translation id="1021110881106174305">Accepted cards</translation>
 <translation id="1032854598605920125">Rotate clockwise</translation>
-<translation id="1035334672863811645">sign in to Chrome</translation>
 <translation id="1038842779957582377">unknown name</translation>
 <translation id="1050038467049342496">Close other apps</translation>
 <translation id="1055184225775184556">&amp;Undo Add</translation>
diff --git a/components/strings/components_strings_es-419.xtb b/components/strings/components_strings_es-419.xtb
index af00016..bced088 100644
--- a/components/strings/components_strings_es-419.xtb
+++ b/components/strings/components_strings_es-419.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Proporciona más detalles</translation>
 <translation id="1021110881106174305">Tarjetas aceptadas</translation>
 <translation id="1032854598605920125">Girar a la derecha</translation>
-<translation id="1035334672863811645">acceder a Chrome</translation>
 <translation id="1038842779957582377">nombre desconocido</translation>
 <translation id="1050038467049342496">Cierra las demás apps.</translation>
 <translation id="1055184225775184556">&amp;Deshacer Agregar</translation>
diff --git a/components/strings/components_strings_es.xtb b/components/strings/components_strings_es.xtb
index 66f4163..381cf043a9 100644
--- a/components/strings/components_strings_es.xtb
+++ b/components/strings/components_strings_es.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Proporciónanos más detalles</translation>
 <translation id="1021110881106174305">Tarjetas aceptadas</translation>
 <translation id="1032854598605920125">Girar hacia la derecha</translation>
-<translation id="1035334672863811645">iniciar sesión en Chrome</translation>
 <translation id="1038842779957582377">nombre desconocido</translation>
 <translation id="1050038467049342496">Cierra otras aplicaciones</translation>
 <translation id="1055184225775184556">&amp;Deshacer acción de añadir</translation>
diff --git a/components/strings/components_strings_et.xtb b/components/strings/components_strings_et.xtb
index 7dc3c84a..7e2e2c9 100644
--- a/components/strings/components_strings_et.xtb
+++ b/components/strings/components_strings_et.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Esitage lisateavet</translation>
 <translation id="1021110881106174305">Aktsepteeritud kaardid</translation>
 <translation id="1032854598605920125">Pööra päripäeva</translation>
-<translation id="1035334672863811645">logige Chromeʼi sisse</translation>
 <translation id="1038842779957582377">tundmatu nimi</translation>
 <translation id="1050038467049342496">Sulgege muud rakendused</translation>
 <translation id="1055184225775184556">&amp;Võta lisamine tagasi</translation>
diff --git a/components/strings/components_strings_fa.xtb b/components/strings/components_strings_fa.xtb
index 837510f..fc2965a 100644
--- a/components/strings/components_strings_fa.xtb
+++ b/components/strings/components_strings_fa.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">جزئیات بیشتری ارائه دهید</translation>
 <translation id="1021110881106174305">کارت‌های قابل‌ قبول</translation>
 <translation id="1032854598605920125">چرخش در جهت عقربه‌های ساعت</translation>
-<translation id="1035334672863811645">‏ورود به سیستم Chrome</translation>
 <translation id="1038842779957582377">نام ناشناس</translation>
 <translation id="1050038467049342496">برنامه‌های دیگر را ببندید</translation>
 <translation id="1055184225775184556">&amp;واگرد افزودن</translation>
diff --git a/components/strings/components_strings_fi.xtb b/components/strings/components_strings_fi.xtb
index bac45c9..8db0da85 100644
--- a/components/strings/components_strings_fi.xtb
+++ b/components/strings/components_strings_fi.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Lisätietoja</translation>
 <translation id="1021110881106174305">Hyväksytyt kortit</translation>
 <translation id="1032854598605920125">Käännä myötäpäivään</translation>
-<translation id="1035334672863811645">Kirjaudu Chromeen</translation>
 <translation id="1038842779957582377">tuntematon nimi</translation>
 <translation id="1050038467049342496">Sulje muita sovelluksia.</translation>
 <translation id="1055184225775184556">K&amp;umoa lisäys</translation>
diff --git a/components/strings/components_strings_fil.xtb b/components/strings/components_strings_fil.xtb
index dcb2eff..bf7a1f7 100644
--- a/components/strings/components_strings_fil.xtb
+++ b/components/strings/components_strings_fil.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Magbigay ng mga karagdagang detalye</translation>
 <translation id="1021110881106174305">Mga tinatanggap na card</translation>
 <translation id="1032854598605920125">I-rotate pakanan</translation>
-<translation id="1035334672863811645">mag-sign in sa Chrome</translation>
 <translation id="1038842779957582377">Hindi kilalang pangalan</translation>
 <translation id="1050038467049342496">Isara ang iba pang app</translation>
 <translation id="1055184225775184556">&amp;I-undo ang Pagdagdag</translation>
diff --git a/components/strings/components_strings_fr.xtb b/components/strings/components_strings_fr.xtb
index 6767748..71b7a786 100644
--- a/components/strings/components_strings_fr.xtb
+++ b/components/strings/components_strings_fr.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Fournir des informations supplémentaires</translation>
 <translation id="1021110881106174305">Cartes acceptées</translation>
 <translation id="1032854598605920125">Faire pivoter vers la droite</translation>
-<translation id="1035334672863811645">connectez-vous à Chrome</translation>
 <translation id="1038842779957582377">Nom inconnu</translation>
 <translation id="1050038467049342496">Fermez les autres applications</translation>
 <translation id="1055184225775184556">&amp;Annuler l'ajout</translation>
diff --git a/components/strings/components_strings_gu.xtb b/components/strings/components_strings_gu.xtb
index 07e23fe..656b8fa 100644
--- a/components/strings/components_strings_gu.xtb
+++ b/components/strings/components_strings_gu.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">અતિરિક્ત વિગતો પ્રદાન કરો</translation>
 <translation id="1021110881106174305">સ્વીકારેલ કાર્ડ</translation>
 <translation id="1032854598605920125">ઘડિયાળની દિશામાં ફેરવો</translation>
-<translation id="1035334672863811645">Chrome માં સાઇન ઇન કરો</translation>
 <translation id="1038842779957582377">અજ્ઞાત નામ</translation>
 <translation id="1050038467049342496">અન્ય ઍપ્લિકેશનો બંધ કરો</translation>
 <translation id="1055184225775184556">&amp;ઉમેરવું પૂર્વવત્ કરો</translation>
diff --git a/components/strings/components_strings_hi.xtb b/components/strings/components_strings_hi.xtb
index a0871499..a7d5ead 100644
--- a/components/strings/components_strings_hi.xtb
+++ b/components/strings/components_strings_hi.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">अतिरिक्त विवरण प्रदान करें</translation>
 <translation id="1021110881106174305">स्वीकार्य कार्ड</translation>
 <translation id="1032854598605920125">घड़ी की दिशा में घुमाएं</translation>
-<translation id="1035334672863811645">Chrome में प्रवेश करें</translation>
 <translation id="1038842779957582377">अज्ञात नाम</translation>
 <translation id="1050038467049342496">दूूूूसरे ऐप्लिकेशन बंद करें</translation>
 <translation id="1055184225775184556">&amp;जोड़ना वापस लाएं</translation>
diff --git a/components/strings/components_strings_hr.xtb b/components/strings/components_strings_hr.xtb
index 45a42a5..0d69b31 100644
--- a/components/strings/components_strings_hr.xtb
+++ b/components/strings/components_strings_hr.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Navedite dodatne pojedinosti</translation>
 <translation id="1021110881106174305">Prihvaćene kartice</translation>
 <translation id="1032854598605920125">Zakretanje u smjeru kazaljke na satu</translation>
-<translation id="1035334672863811645">prijavite se na Chrome</translation>
 <translation id="1038842779957582377">nepoznati naziv</translation>
 <translation id="1050038467049342496">Zatvorite ostale aplikacije</translation>
 <translation id="1055184225775184556">&amp;Poništi dodavanje</translation>
diff --git a/components/strings/components_strings_hu.xtb b/components/strings/components_strings_hu.xtb
index 0ce4c2b..04db823b 100644
--- a/components/strings/components_strings_hu.xtb
+++ b/components/strings/components_strings_hu.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">További részletek megadása</translation>
 <translation id="1021110881106174305">Elfogadott kártyák</translation>
 <translation id="1032854598605920125">Forgatás jobbra</translation>
-<translation id="1035334672863811645">bejelentkezés a Chrome-ba</translation>
 <translation id="1038842779957582377">Ismeretlen név</translation>
 <translation id="1050038467049342496">Zárja be a többi alkalmazást</translation>
 <translation id="1055184225775184556">&amp;Hozzáadás visszavonása</translation>
diff --git a/components/strings/components_strings_id.xtb b/components/strings/components_strings_id.xtb
index c9a60b4..15c8d239 100644
--- a/components/strings/components_strings_id.xtb
+++ b/components/strings/components_strings_id.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Berikan detail tambahan</translation>
 <translation id="1021110881106174305">Kartu yang diterima</translation>
 <translation id="1032854598605920125">Putar searah jarum jam</translation>
-<translation id="1035334672863811645">masuk ke Chrome</translation>
 <translation id="1038842779957582377">nama tidak diketahui</translation>
 <translation id="1050038467049342496">Tutup aplikasi lain</translation>
 <translation id="1055184225775184556">&amp;Urungkan Penambahan</translation>
diff --git a/components/strings/components_strings_it.xtb b/components/strings/components_strings_it.xtb
index f2a3b71..2dfc6e3 100644
--- a/components/strings/components_strings_it.xtb
+++ b/components/strings/components_strings_it.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Fornisci ulteriori dettagli</translation>
 <translation id="1021110881106174305">Carte di credito accettate</translation>
 <translation id="1032854598605920125">Ruota in senso orario</translation>
-<translation id="1035334672863811645">accedi a Chrome</translation>
 <translation id="1038842779957582377">nome sconosciuto</translation>
 <translation id="1050038467049342496">Chiudi altre app</translation>
 <translation id="1055184225775184556">&amp;Annulla aggiunta</translation>
diff --git a/components/strings/components_strings_iw.xtb b/components/strings/components_strings_iw.xtb
index 77b00c45..5d98eec 100644
--- a/components/strings/components_strings_iw.xtb
+++ b/components/strings/components_strings_iw.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">ספק פרטים נוספים</translation>
 <translation id="1021110881106174305">כרטיסים מאושרים</translation>
 <translation id="1032854598605920125">סובב בכיוון השעון</translation>
-<translation id="1035334672863811645">‏היכנס ל-Chrome</translation>
 <translation id="1038842779957582377">שם לא ידוע</translation>
 <translation id="1050038467049342496">סגירת יישומים אחרים</translation>
 <translation id="1055184225775184556">&amp;ביטול הוספה</translation>
diff --git a/components/strings/components_strings_ja.xtb b/components/strings/components_strings_ja.xtb
index 4560746d..1503a45 100644
--- a/components/strings/components_strings_ja.xtb
+++ b/components/strings/components_strings_ja.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">詳細を報告する</translation>
 <translation id="1021110881106174305">利用可能なカード</translation>
 <translation id="1032854598605920125">時計回りに回転</translation>
-<translation id="1035334672863811645">Chrome にログイン</translation>
 <translation id="1038842779957582377">不明な名前</translation>
 <translation id="1050038467049342496">他のアプリを終了する</translation>
 <translation id="1055184225775184556">追加の取り消し(&amp;U)</translation>
diff --git a/components/strings/components_strings_kn.xtb b/components/strings/components_strings_kn.xtb
index b6bcc7c3..c3fbae2d 100644
--- a/components/strings/components_strings_kn.xtb
+++ b/components/strings/components_strings_kn.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">ಹೆಚ್ಚುವರಿ ವಿವರಗಳನ್ನು ಒದಗಿಸಿ</translation>
 <translation id="1021110881106174305">ಸ್ವೀಕೃತ ಕಾರ್ಡ್‌ಗಳು</translation>
 <translation id="1032854598605920125">ಪ್ರದಕ್ಷಿಣಾಕಾರದಲ್ಲಿ ತಿರುಗಿಸು</translation>
-<translation id="1035334672863811645">Chrome ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ</translation>
 <translation id="1038842779957582377">ಆಜ್ಞಾತ ಹೆಸರು</translation>
 <translation id="1050038467049342496">ಇತರ ಅಪ್ಲಿಕೇಶನ್‍ಗಳನ್ನು ಮುಚ್ಚಿ</translation>
 <translation id="1055184225775184556">&amp;ಸೇರಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
diff --git a/components/strings/components_strings_ko.xtb b/components/strings/components_strings_ko.xtb
index 06b70b1f..d283451 100644
--- a/components/strings/components_strings_ko.xtb
+++ b/components/strings/components_strings_ko.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">추가 세부정보 제공</translation>
 <translation id="1021110881106174305">사용할 수 있는 카드</translation>
 <translation id="1032854598605920125">시계 방향으로 회전</translation>
-<translation id="1035334672863811645">Chrome에 로그인</translation>
 <translation id="1038842779957582377">알 수 없는 이름</translation>
 <translation id="1050038467049342496">다른 앱 닫기</translation>
 <translation id="1055184225775184556">추가 실행 취소(&amp;U)</translation>
diff --git a/components/strings/components_strings_lt.xtb b/components/strings/components_strings_lt.xtb
index 53ef677..a5bf9f79 100644
--- a/components/strings/components_strings_lt.xtb
+++ b/components/strings/components_strings_lt.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Pateikti papildomos išsamios informacijos</translation>
 <translation id="1021110881106174305">Tinkamos kortelės</translation>
 <translation id="1032854598605920125">Pasukti pagal laikrodžio rodyklę</translation>
-<translation id="1035334672863811645">prisijunkite prie „Chrome“</translation>
 <translation id="1038842779957582377">nežinomas pavadinimas</translation>
 <translation id="1050038467049342496">Uždarykite kitas programas</translation>
 <translation id="1055184225775184556">&amp;Anuliuoti pridėjimą</translation>
diff --git a/components/strings/components_strings_lv.xtb b/components/strings/components_strings_lv.xtb
index 9d3be7f..9ea0e09 100644
--- a/components/strings/components_strings_lv.xtb
+++ b/components/strings/components_strings_lv.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Sniegt papildu informāciju</translation>
 <translation id="1021110881106174305">Pieņemtās kartes</translation>
 <translation id="1032854598605920125">Pagriezt pulksteņrādītāju kustības virzienā</translation>
-<translation id="1035334672863811645">pierakstieties pārlūkā Chrome</translation>
 <translation id="1038842779957582377">nezināms nosaukums</translation>
 <translation id="1050038467049342496">Aizveriet citas lietotnes</translation>
 <translation id="1055184225775184556">&amp;Pievienošanas atsaukšana</translation>
diff --git a/components/strings/components_strings_ml.xtb b/components/strings/components_strings_ml.xtb
index a60241a..d8c9d8a9 100644
--- a/components/strings/components_strings_ml.xtb
+++ b/components/strings/components_strings_ml.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">കൂടുതൽ വിശദാംശങ്ങൾ നൽകുക</translation>
 <translation id="1021110881106174305">സ്വീകരിച്ച കാർഡുകൾ</translation>
 <translation id="1032854598605920125">ഘടികാരദിശയിൽ‌ തിരിക്കുക</translation>
-<translation id="1035334672863811645">Chrome-ലേക്ക് സൈൻ ഇൻ ചെയ്യുക</translation>
 <translation id="1038842779957582377">അജ്ഞാത നാമം</translation>
 <translation id="1050038467049342496">മറ്റ് ആപ്പുകൾ അടയ്‌ക്കുക</translation>
 <translation id="1055184225775184556">&amp;ചേർക്കുന്നത് പഴയപടിയാക്കുക</translation>
diff --git a/components/strings/components_strings_mr.xtb b/components/strings/components_strings_mr.xtb
index 0fb9f41..556f241 100644
--- a/components/strings/components_strings_mr.xtb
+++ b/components/strings/components_strings_mr.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">अतिरिक्त तपशील प्रदान करा</translation>
 <translation id="1021110881106174305">स्वीकारलेली कार्ड</translation>
 <translation id="1032854598605920125">घड्याळाच्या दिशेने फिरवा</translation>
-<translation id="1035334672863811645">Chrome मध्ये साइन इन करा</translation>
 <translation id="1038842779957582377">अज्ञात नाव</translation>
 <translation id="1050038467049342496">अन्य अॅप्स बंद करा</translation>
 <translation id="1055184225775184556">&amp;जोडा पूर्ववत करा</translation>
diff --git a/components/strings/components_strings_ms.xtb b/components/strings/components_strings_ms.xtb
index 4cd12a7..8df151c1 100644
--- a/components/strings/components_strings_ms.xtb
+++ b/components/strings/components_strings_ms.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Berikan butiran tambahan</translation>
 <translation id="1021110881106174305">Kad diterima</translation>
 <translation id="1032854598605920125">Putar ikut arah jam</translation>
-<translation id="1035334672863811645">log masuk ke Chrome</translation>
 <translation id="1038842779957582377">nama tidak diketahui</translation>
 <translation id="1050038467049342496">Tutup apl lain</translation>
 <translation id="1055184225775184556">&amp;Buat Asal Tambahkan</translation>
diff --git a/components/strings/components_strings_nl.xtb b/components/strings/components_strings_nl.xtb
index bf0f8ba..8233936 100644
--- a/components/strings/components_strings_nl.xtb
+++ b/components/strings/components_strings_nl.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Aanvullende gegevens verzenden</translation>
 <translation id="1021110881106174305">Geaccepteerde kaarten</translation>
 <translation id="1032854598605920125">Rechtsom draaien</translation>
-<translation id="1035334672863811645">inloggen bij Chrome</translation>
 <translation id="1038842779957582377">onbekende naam</translation>
 <translation id="1050038467049342496">Andere apps sluiten</translation>
 <translation id="1055184225775184556">&amp;Toevoegen ongedaan maken</translation>
diff --git a/components/strings/components_strings_no.xtb b/components/strings/components_strings_no.xtb
index 89d72d9..74838a2 100644
--- a/components/strings/components_strings_no.xtb
+++ b/components/strings/components_strings_no.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Oppgi flere detaljer</translation>
 <translation id="1021110881106174305">Godkjente kort</translation>
 <translation id="1032854598605920125">Rotér med klokken</translation>
-<translation id="1035334672863811645">logg på Chrome</translation>
 <translation id="1038842779957582377">ukjent navn</translation>
 <translation id="1050038467049342496">Lukk andre apper</translation>
 <translation id="1055184225775184556">&amp;Angre tilleggingen</translation>
diff --git a/components/strings/components_strings_pl.xtb b/components/strings/components_strings_pl.xtb
index 6899579..8c14187 100644
--- a/components/strings/components_strings_pl.xtb
+++ b/components/strings/components_strings_pl.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Podaj dodatkowe informacje</translation>
 <translation id="1021110881106174305">Akceptowane karty</translation>
 <translation id="1032854598605920125">Obróć w prawo</translation>
-<translation id="1035334672863811645">zaloguj się w Chrome</translation>
 <translation id="1038842779957582377">nieznana nazwa</translation>
 <translation id="1050038467049342496">Zamknij inne aplikacje</translation>
 <translation id="1055184225775184556">&amp;Cofnij dodanie</translation>
diff --git a/components/strings/components_strings_pt-BR.xtb b/components/strings/components_strings_pt-BR.xtb
index f9b2b52..19d992e 100644
--- a/components/strings/components_strings_pt-BR.xtb
+++ b/components/strings/components_strings_pt-BR.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Forneça detalhes adicionais</translation>
 <translation id="1021110881106174305">Cartões aceitos</translation>
 <translation id="1032854598605920125">Girar no sentido horário</translation>
-<translation id="1035334672863811645">fazer login no Chrome</translation>
 <translation id="1038842779957582377">nome desconhecido</translation>
 <translation id="1050038467049342496">Fechar outros apps</translation>
 <translation id="1055184225775184556">&amp;Desfazer adicionar</translation>
diff --git a/components/strings/components_strings_pt-PT.xtb b/components/strings/components_strings_pt-PT.xtb
index 9dd9adbbe..9d7ec76 100644
--- a/components/strings/components_strings_pt-PT.xtb
+++ b/components/strings/components_strings_pt-PT.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Forneça mais detalhes</translation>
 <translation id="1021110881106174305">Cartões admitidos</translation>
 <translation id="1032854598605920125">Rodar para a direita</translation>
-<translation id="1035334672863811645">inicie sessão no Chrome</translation>
 <translation id="1038842779957582377">nome desconhecido</translation>
 <translation id="1050038467049342496">Fechar outras aplicações</translation>
 <translation id="1055184225775184556">&amp;Anular adição</translation>
diff --git a/components/strings/components_strings_ro.xtb b/components/strings/components_strings_ro.xtb
index 9b3ac0a..860ee08 100644
--- a/components/strings/components_strings_ro.xtb
+++ b/components/strings/components_strings_ro.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Specifică detalii suplimentare</translation>
 <translation id="1021110881106174305">Carduri acceptate</translation>
 <translation id="1032854598605920125">Rotește în sensul acelor de ceasornic</translation>
-<translation id="1035334672863811645">conectează-te la Chrome</translation>
 <translation id="1038842779957582377">nume necunoscut</translation>
 <translation id="1050038467049342496">închide celelalte aplicații;</translation>
 <translation id="1055184225775184556">&amp;Anulați adăugarea</translation>
diff --git a/components/strings/components_strings_ru.xtb b/components/strings/components_strings_ru.xtb
index c2086a8..e3c63dd1 100644
--- a/components/strings/components_strings_ru.xtb
+++ b/components/strings/components_strings_ru.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Сообщить дополнительную информацию</translation>
 <translation id="1021110881106174305">Карты, которые принимаются к оплате</translation>
 <translation id="1032854598605920125">Повернуть по часовой стрелке</translation>
-<translation id="1035334672863811645">войдите в Chrome</translation>
 <translation id="1038842779957582377">неизвестное имя</translation>
 <translation id="1050038467049342496">Закройте другие приложения.</translation>
 <translation id="1055184225775184556">&amp;Отменить добавление</translation>
@@ -583,6 +582,7 @@
 <translation id="5089810972385038852">Штат</translation>
 <translation id="5094747076828555589">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Chromium не доверяет его сертификату безопасности. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
 <translation id="5095208057601539847">Провинция</translation>
+<translation id="5098332213681597508">Имя из вашего аккаунта Google.</translation>
 <translation id="5115563688576182185">(64 бит)</translation>
 <translation id="5121084798328133320">После подтверждения реквизиты карты из платежного аккаунта Google будут переданы этому сайту.</translation>
 <translation id="5128122789703661928">Невозможно удалить сеанс с таким названием.</translation>
@@ -668,6 +668,7 @@
 <translation id="5633066919399395251">Сайт <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> может установить на ваш компьютер вредоносное ПО, которое крадет или удаляет личную информацию (например, фотографии, пароли, сообщения и реквизиты банковских карт). <ph name="BEGIN_LEARN_MORE_LINK" />Подробнее…<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="563324245173044180">Мошеннический контент заблокирован</translation>
 <translation id="5659593005791499971">Электронная почта</translation>
+<translation id="5666899935841546222">Хотите добавить все свои карты в аккаунт?</translation>
 <translation id="5675650730144413517">Страница недоступна</translation>
 <translation id="5685654322157854305">Добавить адрес доставки посылок</translation>
 <translation id="5689199277474810259">Экспортировать как JSON</translation>
diff --git a/components/strings/components_strings_sk.xtb b/components/strings/components_strings_sk.xtb
index 6445bef..aba02cc 100644
--- a/components/strings/components_strings_sk.xtb
+++ b/components/strings/components_strings_sk.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Poskytnite ďalšie podrobnosti</translation>
 <translation id="1021110881106174305">Prijímané karty</translation>
 <translation id="1032854598605920125">Otočiť v smere hodinových ručičiek</translation>
-<translation id="1035334672863811645">prihláste sa do prehliadača Chrome</translation>
 <translation id="1038842779957582377">neznámy názov</translation>
 <translation id="1050038467049342496">Zavrite ostatné aplikácie</translation>
 <translation id="1055184225775184556">&amp;Vrátiť späť pridanie</translation>
diff --git a/components/strings/components_strings_sl.xtb b/components/strings/components_strings_sl.xtb
index b69a5096..eb70b654 100644
--- a/components/strings/components_strings_sl.xtb
+++ b/components/strings/components_strings_sl.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Navedite dodatne podrobnosti</translation>
 <translation id="1021110881106174305">Sprejete kartice</translation>
 <translation id="1032854598605920125">Sukanje v smeri urnega kazalca</translation>
-<translation id="1035334672863811645">se prijavite v Chrome</translation>
 <translation id="1038842779957582377">neznano ime</translation>
 <translation id="1050038467049342496">Zaprite druge aplikacije</translation>
 <translation id="1055184225775184556">&amp;Razveljavi dodajanje</translation>
diff --git a/components/strings/components_strings_sr.xtb b/components/strings/components_strings_sr.xtb
index 92cade3..4fa15c0 100644
--- a/components/strings/components_strings_sr.xtb
+++ b/components/strings/components_strings_sr.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Наведите додатне детаље</translation>
 <translation id="1021110881106174305">Прихваћене картице</translation>
 <translation id="1032854598605920125">Окрените у смеру казаљке на сату</translation>
-<translation id="1035334672863811645">пријавите се у Chrome</translation>
 <translation id="1038842779957582377">непознато име</translation>
 <translation id="1050038467049342496">Затворите друге апликације</translation>
 <translation id="1055184225775184556">&amp;Опозови додавање</translation>
diff --git a/components/strings/components_strings_sv.xtb b/components/strings/components_strings_sv.xtb
index 96c555b..7110bcc 100644
--- a/components/strings/components_strings_sv.xtb
+++ b/components/strings/components_strings_sv.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Ange ytterligare information</translation>
 <translation id="1021110881106174305">Godkända kort</translation>
 <translation id="1032854598605920125">Rotera medurs</translation>
-<translation id="1035334672863811645">Logga in i Chrome</translation>
 <translation id="1038842779957582377">okänt namn</translation>
 <translation id="1050038467049342496">Stäng andra appar</translation>
 <translation id="1055184225775184556">&amp;Ångra Lägg till</translation>
diff --git a/components/strings/components_strings_sw.xtb b/components/strings/components_strings_sw.xtb
index 03032b2..cc2e04c 100644
--- a/components/strings/components_strings_sw.xtb
+++ b/components/strings/components_strings_sw.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Toa maelezo ya ziada</translation>
 <translation id="1021110881106174305">Kadi zinazokubaliwa</translation>
 <translation id="1032854598605920125">Zungusha kwenye mwendo wa saa</translation>
-<translation id="1035334672863811645">ingia katika Chrome</translation>
 <translation id="1038842779957582377">jina lisilojulikana</translation>
 <translation id="1050038467049342496">Funga programu nyingine</translation>
 <translation id="1055184225775184556">Tendua Kuongeza</translation>
diff --git a/components/strings/components_strings_ta.xtb b/components/strings/components_strings_ta.xtb
index 0821871..6de83c16 100644
--- a/components/strings/components_strings_ta.xtb
+++ b/components/strings/components_strings_ta.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">கூடுதல் விவரங்களை வழங்கவும்</translation>
 <translation id="1021110881106174305">ஏற்கப்படும் கார்டுகள்</translation>
 <translation id="1032854598605920125">கடிகாரத்திசையில் சுழற்று</translation>
-<translation id="1035334672863811645">Chrome இல் உள்நுழைக</translation>
 <translation id="1038842779957582377">அறியப்படாத பெயர்</translation>
 <translation id="1050038467049342496">பிற பயன்பாடுகளை மூடவும்</translation>
 <translation id="1055184225775184556">&amp;சேர்த்தலைச் செயல்தவிர்</translation>
diff --git a/components/strings/components_strings_te.xtb b/components/strings/components_strings_te.xtb
index 140e3c9..333702b 100644
--- a/components/strings/components_strings_te.xtb
+++ b/components/strings/components_strings_te.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">అదనపు వివరాలను అందించండి</translation>
 <translation id="1021110881106174305">ఆమోదించబడే కార్డ్‌లు</translation>
 <translation id="1032854598605920125">సవ్యదిశలో తిప్పు</translation>
-<translation id="1035334672863811645">Chromeకు సైన్ ఇన్ చేయండి</translation>
 <translation id="1038842779957582377">తెలియని పేరు</translation>
 <translation id="1050038467049342496">ఇతర అనువర్తనాలను మూసివేయండి</translation>
 <translation id="1055184225775184556">&amp;జోడించడాన్ని రద్దు చేయి</translation>
diff --git a/components/strings/components_strings_th.xtb b/components/strings/components_strings_th.xtb
index 94a5664b..961f8b0 100644
--- a/components/strings/components_strings_th.xtb
+++ b/components/strings/components_strings_th.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">ให้รายละเอียดเพิ่มเติม</translation>
 <translation id="1021110881106174305">บัตรที่ยอมรับ</translation>
 <translation id="1032854598605920125">หมุนตามเข็มนาฬิกา</translation>
-<translation id="1035334672863811645">ลงชื่อเข้าใช้ Chrome</translation>
 <translation id="1038842779957582377">ไม่ทราบชื่อ</translation>
 <translation id="1050038467049342496">ปิดแอปอื่นๆ</translation>
 <translation id="1055184225775184556">&amp;เลิกทำการเพิ่ม</translation>
diff --git a/components/strings/components_strings_tr.xtb b/components/strings/components_strings_tr.xtb
index 28a06d4..f7c12c7f 100644
--- a/components/strings/components_strings_tr.xtb
+++ b/components/strings/components_strings_tr.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Diğer ayrıntıları sağlayın</translation>
 <translation id="1021110881106174305">Kabul edilen kartlar</translation>
 <translation id="1032854598605920125">Saat yönünde döndür</translation>
-<translation id="1035334672863811645">Chrome'da oturum açın</translation>
 <translation id="1038842779957582377">bilinmeyen ad</translation>
 <translation id="1050038467049342496">Diğer uygulamaları kapatın</translation>
 <translation id="1055184225775184556">Eklemeyi &amp;Geri Al</translation>
diff --git a/components/strings/components_strings_uk.xtb b/components/strings/components_strings_uk.xtb
index 1c3ae1c..c1cd2bb 100644
--- a/components/strings/components_strings_uk.xtb
+++ b/components/strings/components_strings_uk.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Надати додаткову інформацію</translation>
 <translation id="1021110881106174305">Прийняті картки</translation>
 <translation id="1032854598605920125">Обернути за годинниковою стрілкою</translation>
-<translation id="1035334672863811645">увійдіть в обліковий запис Chrome</translation>
 <translation id="1038842779957582377">Невідоме ім’я</translation>
 <translation id="1050038467049342496">Закрийте інші додатки</translation>
 <translation id="1055184225775184556">&amp;Відмінити додавання</translation>
diff --git a/components/strings/components_strings_vi.xtb b/components/strings/components_strings_vi.xtb
index 2b3f036188..4e1c4ac9 100644
--- a/components/strings/components_strings_vi.xtb
+++ b/components/strings/components_strings_vi.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">Cung cấp chi tiết bổ sung</translation>
 <translation id="1021110881106174305">Thẻ được chấp nhận</translation>
 <translation id="1032854598605920125">Xoay theo chiều kim đồng hồ</translation>
-<translation id="1035334672863811645">đăng nhập vào Chrome</translation>
 <translation id="1038842779957582377">tên không biết</translation>
 <translation id="1050038467049342496">Đóng các ứng dụng khác</translation>
 <translation id="1055184225775184556">&amp;Hoàn tác thêm</translation>
diff --git a/components/strings/components_strings_zh-CN.xtb b/components/strings/components_strings_zh-CN.xtb
index 46a3adb..ad275da 100644
--- a/components/strings/components_strings_zh-CN.xtb
+++ b/components/strings/components_strings_zh-CN.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">提供其他详细信息</translation>
 <translation id="1021110881106174305">接受的信用卡</translation>
 <translation id="1032854598605920125">顺时针旋转</translation>
-<translation id="1035334672863811645">登录 Chrome</translation>
 <translation id="1038842779957582377">未知名称</translation>
 <translation id="1050038467049342496">关闭其他应用</translation>
 <translation id="1055184225775184556">撤消添加(&amp;U)</translation>
diff --git a/components/strings/components_strings_zh-TW.xtb b/components/strings/components_strings_zh-TW.xtb
index 2b71fb6..db82e76 100644
--- a/components/strings/components_strings_zh-TW.xtb
+++ b/components/strings/components_strings_zh-TW.xtb
@@ -6,7 +6,6 @@
 <translation id="1015730422737071372">提供其他詳細資訊</translation>
 <translation id="1021110881106174305">接受的信用卡</translation>
 <translation id="1032854598605920125">順時針旋轉</translation>
-<translation id="1035334672863811645">登入 Chrome</translation>
 <translation id="1038842779957582377">不明名稱</translation>
 <translation id="1050038467049342496">關閉其他應用程式</translation>
 <translation id="1055184225775184556">復原新增(&amp;U)</translation>
diff --git a/components/test/data/autofill/heuristics/input/152_garbarino_document_number_not_cc.html b/components/test/data/autofill/heuristics/input/152_garbarino_document_number_not_cc.html
new file mode 100644
index 0000000..fdee018
--- /dev/null
+++ b/components/test/data/autofill/heuristics/input/152_garbarino_document_number_not_cc.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title></title>
+  </head>
+  <body>
+    <form action="http://www.google.com/" method="post">
+        <fieldset>
+            <h3 class="box-subtitle facturacion-subtitle">DATOS DEL TITULAR DEL MEDIO DE PAGO</h3>
+            <div class="form-content noResumenSessionBillings ">
+                <div class="row">
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 form-group">
+                        <label>Nombre <span class="required" aria-required="true">*</span></label>
+                        <input type="text" name="firstName" id="firstName" autocomplete="given-name" class="form-control" value="" title="Nombre" placeholder="Como figura en tu documento" aria-required="true" tabindex="3" required="" autofocus="">
+                    </div>
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 form-group">
+                        <label>Apellido <span class="required" aria-required="true">*</span></label>
+                        <input type="text" name="lastName" id="lastName" autocomplete="family-name" class="form-control" value="" title="Apellido" placeholder="Como figura en tu documento" aria-required="true" tabindex="4" required="">
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 ">
+                        <div class="row ">
+                            <div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 dni form-group">
+                                <label>Tipo <span class="required" aria-required="true">*</span></label>
+                                <div class="form-group">
+                                    <select class="gb-select" id="id_type" name="id_type" tabindex="7">
+                                        <option value="DNI" selected="selected">DNI</option>
+                                        <option value="CI">CI</option>
+                                        <option value="LC">LC</option>
+                                        <option value="LE">LE</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="col-xs-8 col-sm-8 col-md-8 col-lg-8 dni-numero form-group">
+                                <label>Número de documento <span class="required" aria-required="true">*</span></label>
+                                <input type="tel" name="id_value" id="id_value" class="form-control" value="" title="Nro de Documento" aria-required="true" tabindex="8" autocomplete="new-doc" required="">
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 ">
+                        <label> Fecha de Nacimiento <span class="required" aria-required="true">*</span></label>
+                        <div class="row fecha-nacimiento ">
+                            <div class="col-xs-3 col-sm-3 col-md-3 col-lg-3 inline form-group fecha-dia">
+                                <select id="day_select" class="gb-select" name="day_select" aria-required="true" tabindex="9" required="">
+                                    <option value="0">Dia</option>
+                                    <option value="01">1</option>
+                                    <option value="02">2</option>
+                                    <option value="03">3</option>
+                                    <option value="04">4</option>
+                                    <option value="05">5</option>
+                                    <option value="06">6</option>
+                                    <option value="07">7</option>
+                                    <option value="08">8</option>
+                                    <option value="09">9</option>
+                                    <option value="10">10</option>
+                                    <option value="11">11</option>
+                                    <option value="12">12</option>
+                                    <option value="13">13</option>
+                                    <option value="14">14</option>
+                                    <option value="15">15</option>
+                                    <option value="16">16</option>
+                                    <option value="17">17</option>
+                                    <option value="18">18</option>
+                                    <option value="19">19</option>
+                                    <option value="20">20</option>
+                                    <option value="21">21</option>
+                                    <option value="22">22</option>
+                                    <option value="23">23</option>
+                                    <option value="24">24</option>
+                                    <option value="25">25</option>
+                                    <option value="26">26</option>
+                                    <option value="27">27</option>
+                                    <option value="28">28</option>
+                                    <option value="29">29</option>
+                                    <option value="30">30</option>
+                                    <option value="31">31</option>
+                                </select>
+                            </div>
+                            <div class="col-xs-6 col-sm-6 col-md-5 col-lg-6 inline form-group fecha-mes">
+                                <select name="month_select" id="month_select" class="gb-select" aria-required="true" tabindex="10" required="">
+                                    <option value="0">Mes</option>
+                                    <option value="01">Enero</option>
+                                    <option value="02">Febrero</option>
+                                    <option value="03">Marzo</option>
+                                    <option value="04">Abril</option>
+                                    <option value="05">Mayo</option>
+                                    <option value="06">Junio</option>
+                                    <option value="07">Julio</option>
+                                    <option value="08">Agosto</option>
+                                    <option value="09">Septiembre</option>
+                                    <option value="10">Octubre</option>
+                                    <option value="11">Noviembre</option>
+                                    <option value="12">Diciembre</option>
+                                </select>
+                            </div>
+                            <div class="col-xs-3 col-sm-3 col-md-4 col-lg-3 inline form-group fecha-anio">
+                                <select name="year_select" id="year_select" class="gb-select" tabindex="11" data-validate="">
+                                    <option value="0">Año</option>
+                                                <option value="2001">2001</option>
+                                                <option value="2000">2000</option>
+                                                <option value="1999">1999</option>
+                                                <option value="1998">1998</option>
+                                                <option value="1997">1997</option>
+                                                <option value="1996">1996</option>
+                                                <option value="1995">1995</option>
+                                                <option value="1994">1994</option>
+                                                <option value="1993">1993</option>
+                                                <option value="1992">1992</option>
+                                                <option value="1991">1991</option>
+                                                <option value="1990">1990</option>
+                                                <option value="1989">1989</option>
+                                                <option value="1988">1988</option>
+                                                <option value="1987">1987</option>
+                                                <option value="1986">1986</option>
+                                                <option value="1985">1985</option>
+                                                <option value="1984">1984</option>
+                                                <option value="1983">1983</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 form-group genero">
+                        <label class="title-genero">Género <span class="required" aria-required="true">*</span></label>
+                        <div class="row">
+                            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
+                                <div class="item-genero">
+                                    <input type="radio" aria-required="true" id="masculino" name="gender" autocomplete="sex" value="MALE" tabindex="13" required="">
+                                    <label for="masculino">Masculino</label>
+                                </div>
+                                <div class="item-genero">
+                                    <input type="radio" aria-required="true" id="femenino" name="gender" autocomplete="sex" value="FEMALE" tabindex="12" required="">
+                                    <label for="femenino">Femenino</label>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <h3 class="box-subtitle facturacion-subtitle">DATOS DE CONTACTO</h3>
+
+            <div class="form-content resumenSessionContact ">
+                <div class="row">
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 form-group">
+                        <label>E-mail <span class="required" aria-required="true">*</span></label>
+                            <input type="email" name="email" id="email" autocomplete="email" class="form-control" value="" title="Email" placeholder="Ingresá tu e-mail" aria-required="true" tabindex="13" required="">
+                    </div>
+                    <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 form-group">
+                        <label>Teléfono <span class="required" aria-required="true">*</span></label>
+                        <input type="tel" name="phone" id="phone" autocomplete="tel" class="form-control" value="" placeholder="Ej: 1145887000" tabindex="14" aria-required="true" required="">
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+  </body>
+</html>
diff --git a/components/test/data/autofill/heuristics/output/152_garbarino_document_number_not_cc.out b/components/test/data/autofill/heuristics/output/152_garbarino_document_number_not_cc.out
new file mode 100644
index 0000000..b272a4da
--- /dev/null
+++ b/components/test/data/autofill/heuristics/output/152_garbarino_document_number_not_cc.out
@@ -0,0 +1,11 @@
+HTML_TYPE_GIVEN_NAME | firstName | Nombre * |  | firstName_1-default
+HTML_TYPE_FAMILY_NAME | lastName | Apellido * |  | firstName_1-default
+UNKNOWN_TYPE | id_type | Tipo * | DNI | firstName_1-default
+UNKNOWN_TYPE | id_value | Número de documento * |  | firstName_1-default
+UNKNOWN_TYPE | day_select | Fecha de Nacimiento * | 0 | firstName_1-default
+UNKNOWN_TYPE | month_select | Fecha de Nacimiento * | 0 | firstName_1-default
+UNKNOWN_TYPE | year_select | Fecha de Nacimiento * | 0 | firstName_1-default
+UNKNOWN_TYPE | gender | Masculino | MALE | firstName_1-default
+UNKNOWN_TYPE | gender | Femenino | FEMALE | firstName_1-default
+HTML_TYPE_EMAIL | email | E-mail * |  | firstName_1-default
+HTML_TYPE_TEL | phone | Teléfono * |  | firstName_1-default
diff --git a/components/variations/client_filterable_state.h b/components/variations/client_filterable_state.h
index a244f79..bd2f86d 100644
--- a/components/variations/client_filterable_state.h
+++ b/components/variations/client_filterable_state.h
@@ -47,6 +47,11 @@
   // Based on base::SysInfo::IsLowEndDevice().
   bool is_low_end_device = false;
 
+  // Whether this platform supports experiments which retain their group
+  // assignments across runs.
+  // TODO(paulmiller): Remove this once https://crbug.com/866722 is resolved.
+  bool supports_permanent_consistency = true;
+
   // The country code to use for studies configured with session consistency.
   std::string session_consistency_country;
 
diff --git a/components/variations/service/BUILD.gn b/components/variations/service/BUILD.gn
index e3c0c1e..c77020f 100644
--- a/components/variations/service/BUILD.gn
+++ b/components/variations/service/BUILD.gn
@@ -12,6 +12,7 @@
     "variations_field_trial_creator.h",
     "variations_service.cc",
     "variations_service.h",
+    "variations_service_client.cc",
     "variations_service_client.h",
   ]
 
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc
index 5f33665..ab2cfce 100644
--- a/components/variations/service/variations_field_trial_creator.cc
+++ b/components/variations/service/variations_field_trial_creator.cc
@@ -259,6 +259,8 @@
   // evaluated, that field trial would not be able to apply for this case.
   state->is_low_end_device = base::SysInfo::IsLowEndDevice();
 #endif
+  state->supports_permanent_consistency =
+      client_->GetSupportsPermanentConsistency();
   state->session_consistency_country = GetLatestCountry();
   state->permanent_consistency_country = LoadPermanentConsistencyCountry(
       version, state->session_consistency_country);
diff --git a/components/variations/service/variations_service_client.cc b/components/variations/service/variations_service_client.cc
new file mode 100644
index 0000000..c2baa85c
--- /dev/null
+++ b/components/variations/service/variations_service_client.cc
@@ -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.
+
+#include "components/variations/service/variations_service_client.h"
+
+namespace variations {
+
+bool VariationsServiceClient::GetSupportsPermanentConsistency() {
+  return true;
+}
+
+}  // namespace variations
diff --git a/components/variations/service/variations_service_client.h b/components/variations/service/variations_service_client.h
index 2b466bb..4e2c644 100644
--- a/components/variations/service/variations_service_client.h
+++ b/components/variations/service/variations_service_client.h
@@ -45,6 +45,11 @@
   // Gets the channel of the embedder.
   virtual version_info::Channel GetChannel() = 0;
 
+  // Gets whether this platform supports experiments which retain their group
+  // assignments across runs.
+  // TODO(paulmiller): Remove this once https://crbug.com/866722 is resolved.
+  virtual bool GetSupportsPermanentConsistency();
+
   // Returns whether the embedder overrides the value of the restrict parameter.
   // |parameter| is an out-param that will contain the value of the restrict
   // parameter if true is returned.
diff --git a/components/variations/study_filtering.cc b/components/variations/study_filtering.cc
index eaca58a..6f1e2177 100644
--- a/components/variations/study_filtering.cc
+++ b/components/variations/study_filtering.cc
@@ -12,6 +12,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "components/variations/client_filterable_state.h"
+#include "components/variations/proto/study.pb.h"
 
 namespace variations {
 namespace {
@@ -266,6 +267,14 @@
     }
   }
 
+  // TODO(paulmiller): Remove this once https://crbug.com/866722 is resolved.
+  if (study.consistency() == Study_Consistency_PERMANENT &&
+      !client_state.supports_permanent_consistency) {
+    DVLOG(1) << "Filtered out study " << study.name()
+             << " due to supports_permanent_consistency.";
+    return false;
+  }
+
   DVLOG(1) << "Kept study " << study.name() << ".";
   return true;
 }
diff --git a/components/viz/service/display/bsp_tree_perftest.cc b/components/viz/service/display/bsp_tree_perftest.cc
index d1832a1..ecb9897 100644
--- a/components/viz/service/display/bsp_tree_perftest.cc
+++ b/components/viz/service/display/bsp_tree_perftest.cc
@@ -107,7 +107,7 @@
     cc::RenderSurfaceList update_list;
     cc::LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
         active_tree->root_layer_for_testing(),
-        active_tree->DeviceViewport().size(), host_impl->DrawTransform(),
+        active_tree->GetDeviceViewport().size(), host_impl->DrawTransform(),
         active_tree->device_scale_factor(),
         active_tree->current_page_scale_factor(),
         active_tree->InnerViewportContainerLayer(),
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index b3b74a3..ee77a50 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -42,10 +42,6 @@
 
 const char kUmaValidSurface[] =
     "Compositing.SurfaceAggregator.SurfaceDrawQuad.ValidSurface";
-const char kUmaMissingSurface[] =
-    "Compositing.SurfaceAggregator.SurfaceDrawQuad.MissingSurface";
-const char kUmaNoActiveFrame[] =
-    "Compositing.SurfaceAggregator.SurfaceDrawQuad.NoActiveFrame";
 const char kUmaUsingFallbackSurface[] =
     "Compositing.SurfaceAggregator.SurfaceDrawQuad.UsingFallbackSurface";
 const char kUmaManhattanDistanceToPrimary[] =
@@ -213,18 +209,22 @@
     return;
   }
 
-  // If there's no fallback surface ID provided, then simply emit a
-  // SolidColorDrawQuad with the provided default background color.
-  if (!surface_quad->surface_range.start()) {
+  Surface* latest_surface = nullptr;
+  if (surface_quad->surface_range.start()) {
+    latest_surface = manager_->GetLatestInFlightSurface(
+        primary_surface_id, *surface_quad->surface_range.start());
+  }
+
+  // If there's no fallback surface ID available, then simply emit a
+  // SolidColorDrawQuad with the provided default background color. This
+  // can happen after a Viz process crash.
+  if (!latest_surface || !latest_surface->HasActiveFrame()) {
     EmitDefaultBackgroundColorQuad(surface_quad, target_transform, clip_rect,
                                    dest_pass);
     return;
   }
-  Surface* latest_surface = manager_->GetLatestInFlightSurface(
-      primary_surface_id, *surface_quad->surface_range.start());
 
-  if (latest_surface &&
-      primary_surface_id.frame_sink_id() ==
+  if (primary_surface_id.frame_sink_id() ==
           latest_surface->surface_id().frame_sink_id() &&
       primary_surface_id.local_surface_id().embed_token() ==
           latest_surface->surface_id().local_surface_id().embed_token()) {
@@ -233,16 +233,6 @@
         latest_surface->surface_id().ManhattanDistanceTo(primary_surface_id));
   }
 
-  // If the fallback is specified and missing then that's an error. Report the
-  // error to console, and log the UMA.
-  if (!latest_surface || !latest_surface->HasActiveFrame()) {
-    ReportMissingFallbackSurface(*surface_quad->surface_range.start(),
-                                 latest_surface);
-    EmitDefaultBackgroundColorQuad(surface_quad, target_transform, clip_rect,
-                                   dest_pass);
-    return;
-  }
-
   if (!surface_quad->stretch_content_to_fill_bounds) {
     const CompositorFrame& fallback_frame = latest_surface->GetActiveFrame();
 
@@ -552,20 +542,6 @@
   }
 }
 
-void SurfaceAggregator::ReportMissingFallbackSurface(
-    const SurfaceId& fallback_surface_id,
-    const Surface* fallback_surface) {
-  // If the fallback surface is unavailable then that's an error.
-  if (!fallback_surface) {
-    DLOG(ERROR) << fallback_surface_id << " is missing during aggregation";
-    ++uma_stats_.missing_surface;
-  } else {
-    DLOG(ERROR) << fallback_surface_id
-                << " has no active frame during aggregation";
-    ++uma_stats_.no_active_frame;
-  }
-}
-
 void SurfaceAggregator::AddColorConversionPass() {
   if (dest_pass_list_->empty())
     return;
@@ -1267,10 +1243,6 @@
   // aggregated together and any failures.
   UMA_HISTOGRAM_EXACT_LINEAR(kUmaValidSurface, uma_stats_.valid_surface,
                              kUmaStatMaxSurfaces);
-  UMA_HISTOGRAM_EXACT_LINEAR(kUmaMissingSurface, uma_stats_.missing_surface,
-                             kUmaStatMaxSurfaces);
-  UMA_HISTOGRAM_EXACT_LINEAR(kUmaNoActiveFrame, uma_stats_.no_active_frame,
-                             kUmaStatMaxSurfaces);
   UMA_HISTOGRAM_EXACT_LINEAR(kUmaUsingFallbackSurface,
                              uma_stats_.using_fallback_surface,
                              kUmaStatMaxSurfaces);
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 877fee4..c2794d1 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -85,8 +85,6 @@
   struct SurfaceDrawQuadUmaStats {
     void Reset() {
       valid_surface = 0;
-      missing_surface = 0;
-      no_active_frame = 0;
       using_fallback_surface = 0;
     }
 
@@ -147,9 +145,6 @@
       SkColor background_color,
       RenderPass* dest_pass);
 
-  void ReportMissingFallbackSurface(const SurfaceId& fallback_surface_id,
-                                    const Surface* fallback_surface);
-
   SharedQuadState* CopySharedQuadState(const SharedQuadState* source_sqs,
                                        const gfx::Transform& target_transform,
                                        const ClipData& clip_rect,
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc
index 561a5bae..a5e2ba4 100644
--- a/components/viz/service/surfaces/surface_manager.cc
+++ b/components/viz/service/surfaces/surface_manager.cc
@@ -30,8 +30,8 @@
 
 const char kUmaAliveSurfaces[] = "Compositing.SurfaceManager.AliveSurfaces";
 
-const char kUmaTemporarySurfaces[] =
-    "Compositing.SurfaceManager.TemporarySurfaces";
+const char kUmaTemporaryReferences[] =
+    "Compositing.SurfaceManager.TemporaryReferences";
 
 constexpr base::TimeDelta kExpireInterval = base::TimeDelta::FromSeconds(10);
 
@@ -237,7 +237,7 @@
   UMA_HISTOGRAM_CUSTOM_COUNTS(kUmaAliveSurfaces, reachable_surfaces.size(), 1,
                               200, 50);
   // Log the number of temporary references after a garbage collection.
-  UMA_HISTOGRAM_CUSTOM_COUNTS(kUmaTemporarySurfaces,
+  UMA_HISTOGRAM_CUSTOM_COUNTS(kUmaTemporaryReferences,
                               temporary_references_.size(), 1, 200, 50);
 
   std::vector<SurfaceId> surfaces_to_delete;
diff --git a/components/zucchini/BUILD.gn b/components/zucchini/BUILD.gn
index c871d9d1..4e289e3 100644
--- a/components/zucchini/BUILD.gn
+++ b/components/zucchini/BUILD.gn
@@ -78,6 +78,8 @@
     "rel32_finder.h",
     "rel32_utils.cc",
     "rel32_utils.h",
+    "reloc_elf.cc",
+    "reloc_elf.h",
     "reloc_win32.cc",
     "reloc_win32.h",
     "suffix_array.h",
@@ -86,6 +88,7 @@
     "targets_affinity.cc",
     "targets_affinity.h",
     "type_dex.h",
+    "type_elf.h",
     "type_win_pe.h",
     "typed_value.h",
     "zucchini.h",
@@ -169,6 +172,7 @@
     "reference_set_unittest.cc",
     "rel32_finder_unittest.cc",
     "rel32_utils_unittest.cc",
+    "reloc_elf_unittest.cc",
     "reloc_win32_unittest.cc",
     "suffix_array_unittest.cc",
     "target_pool_unittest.cc",
diff --git a/components/zucchini/buffer_view.h b/components/zucchini/buffer_view.h
index 66925c4..727ebd1d 100644
--- a/components/zucchini/buffer_view.h
+++ b/components/zucchini/buffer_view.h
@@ -131,16 +131,30 @@
 
   template <class U>
   const U& read(size_type pos) const {
-    CHECK_LE(pos + sizeof(U), size());
+    // TODO(huangs): Use can_access<U>(pos) after fixing can_access().
+    CHECK_LE(sizeof(U), size());
+    CHECK_LE(pos, size() - sizeof(U));
     return *reinterpret_cast<const U*>(begin() + pos);
   }
 
   template <class U>
   void write(size_type pos, const U& value) {
-    CHECK_LE(pos + sizeof(U), size());
+    // TODO(huangs): Use can_access<U>(pos) after fixing can_access().
+    CHECK_LE(sizeof(U), size());
+    CHECK_LE(pos, size() - sizeof(U));
     *reinterpret_cast<U*>(begin() + pos) = value;
   }
 
+  // Returns a mutable reference to an object type U whose raw storage starts
+  // at location |pos|.
+  template <class U>
+  U& modify(size_type pos) {
+    // TODO(huangs): Use can_access<U>(pos) after fixing can_access().
+    CHECK_LE(sizeof(U), size());
+    CHECK_LE(pos, size() - sizeof(U));
+    return *reinterpret_cast<U*>(begin() + pos);
+  }
+
   template <class U>
   bool can_access(size_type pos) const {
     return pos < size() && size() - pos >= sizeof(U);
diff --git a/components/zucchini/buffer_view_unittest.cc b/components/zucchini/buffer_view_unittest.cc
index 7df34b27..30170d7 100644
--- a/components/zucchini/buffer_view_unittest.cc
+++ b/components/zucchini/buffer_view_unittest.cc
@@ -130,6 +130,26 @@
   EXPECT_DEATH(buffer.write<uint32_t>(7, 0xFFFFFFFF), "");
 }
 
+TEST_F(BufferViewTest, Modify) {
+  struct TestStruct {
+    uint32_t a;
+    uint32_t b;
+  };
+
+  MutableBufferView buffer(bytes_.data(), bytes_.size());
+
+  buffer.modify<TestStruct>(0).a = 0x01234567;
+  buffer.modify<TestStruct>(0).b = 0x89ABCDEF;
+  EXPECT_EQ(ParseHexString("67 45 23 01 EF CD AB 89 10 00"),
+            std::vector<uint8_t>(buffer.begin(), buffer.end()));
+
+  buffer.modify<uint8_t>(9);
+  EXPECT_DEATH(buffer.modify<uint8_t>(10), "");
+
+  buffer.modify<uint32_t>(6);
+  EXPECT_DEATH(buffer.modify<uint32_t>(7), "");
+}
+
 TEST_F(BufferViewTest, CanAccess) {
   MutableBufferView buffer(bytes_.data(), bytes_.size());
   EXPECT_TRUE(buffer.can_access<uint32_t>(0));
diff --git a/components/zucchini/reloc_elf.cc b/components/zucchini/reloc_elf.cc
new file mode 100644
index 0000000..6a32184
--- /dev/null
+++ b/components/zucchini/reloc_elf.cc
@@ -0,0 +1,162 @@
+// 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/zucchini/reloc_elf.h"
+
+#include <algorithm>
+#include <tuple>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "components/zucchini/algorithm.h"
+
+namespace zucchini {
+
+/******** RelocReaderElf ********/
+
+RelocReaderElf::RelocReaderElf(
+    ConstBufferView image,
+    Bitness bitness,
+    const std::vector<SectionDimensionsElf>& reloc_section_dims,
+    uint32_t rel_type,
+    offset_t lo,
+    offset_t hi,
+    const AddressTranslator& translator)
+    : image_(image),
+      bitness_(bitness),
+      rel_type_(rel_type),
+      reloc_section_dimensions_(reloc_section_dims),
+      hi_(hi),
+      target_rva_to_offset_(translator) {
+  DCHECK(bitness_ == kBit32 || bitness_ == kBit64);
+
+  // Find the relocation section at or right before |lo|.
+  cur_section_dimensions_ = std::upper_bound(
+      reloc_section_dimensions_.begin(), reloc_section_dimensions_.end(), lo);
+  if (cur_section_dimensions_ != reloc_section_dimensions_.begin())
+    --cur_section_dimensions_;
+
+  // |lo| and |hi_| do not cut across a reloc reference (e.g.,
+  // Elf_Rel::r_offset), but may cut across a reloc struct (e.g. Elf_Rel)!
+  // GetNext() emits all reloc references in |[lo, hi_)|, but needs to examine
+  // the entire reloc struct for context. Knowing that |r_offset| is the first
+  // entry in a reloc struct, |cursor_| and |hi_| are adjusted by the following:
+  // - If |lo| is in a reloc section, then |cursor_| is chosen, as |lo| aligned
+  //   up to the next reloc struct, to exclude reloc struct that |lo| may cut
+  //   across.
+  // - If |hi_| is in a reloc section, then align it up, to include reloc struct
+  //   that |hi_| may cut across.
+  cursor_ =
+      base::checked_cast<offset_t>(cur_section_dimensions_->region.offset);
+  if (cursor_ < lo)
+    cursor_ +=
+        AlignCeil<offset_t>(lo - cursor_, cur_section_dimensions_->entry_size);
+
+  auto end_section = std::upper_bound(reloc_section_dimensions_.begin(),
+                                      reloc_section_dimensions_.end(), hi_);
+  if (end_section != reloc_section_dimensions_.begin()) {
+    --end_section;
+    if (hi_ - end_section->region.offset < end_section->region.size) {
+      offset_t end_region_offset =
+          base::checked_cast<offset_t>(end_section->region.offset);
+      hi_ = end_region_offset + AlignCeil<offset_t>(hi_ - end_region_offset,
+                                                    end_section->entry_size);
+    }
+  }
+}
+
+RelocReaderElf::~RelocReaderElf() = default;
+
+rva_t RelocReaderElf::GetRelocationTarget(elf::Elf32_Rel rel) const {
+  // The least significant byte of |rel.r_info| is the type. The other 3 bytes
+  // store the symbol, which we ignore.
+  uint32_t type = static_cast<uint32_t>(rel.r_info & 0xFF);
+  if (type == rel_type_)
+    return rel.r_offset;
+  return kInvalidRva;
+}
+
+rva_t RelocReaderElf::GetRelocationTarget(elf::Elf64_Rel rel) const {
+  // The least significant 4 bytes of |rel.r_info| is the type. The other 4
+  // bytes store the symbol, which we ignore.
+  uint32_t type = static_cast<uint32_t>(rel.r_info & 0xFFFFFFFF);
+  if (type == rel_type_) {
+    // Assume |rel.r_offset| fits within 32-bit integer.
+    if ((rel.r_offset & 0xFFFFFFFF) == rel.r_offset)
+      return static_cast<rva_t>(rel.r_offset);
+    // Otherwise output warning.
+    LOG(WARNING) << "Warning: Skipping r_offset whose value exceeds 32-bits.";
+  }
+  return kInvalidRva;
+}
+
+base::Optional<Reference> RelocReaderElf::GetNext() {
+  offset_t cur_entry_size = cur_section_dimensions_->entry_size;
+  offset_t cur_section_dimensions_end =
+      base::checked_cast<offset_t>(cur_section_dimensions_->region.hi());
+
+  for (; cursor_ + cur_entry_size <= hi_; cursor_ += cur_entry_size) {
+    while (cursor_ >= cur_section_dimensions_end) {
+      ++cur_section_dimensions_;
+      if (cur_section_dimensions_ == reloc_section_dimensions_.end())
+        return base::nullopt;
+      cur_entry_size = cur_section_dimensions_->entry_size;
+      cursor_ =
+          base::checked_cast<offset_t>(cur_section_dimensions_->region.offset);
+      if (cursor_ + cur_entry_size > hi_)
+        return base::nullopt;
+      cur_section_dimensions_end =
+          base::checked_cast<offset_t>(cur_section_dimensions_->region.hi());
+    }
+    rva_t target_rva = kInvalidRva;
+    // TODO(huangs): Fix RELA sections: Need to process |r_addend|.
+    switch (bitness_) {
+      case kBit32:
+        target_rva = GetRelocationTarget(image_.read<elf::Elf32_Rel>(cursor_));
+        break;
+      case kBit64:
+        target_rva = GetRelocationTarget(image_.read<elf::Elf64_Rel>(cursor_));
+        break;
+    }
+    if (target_rva == kInvalidRva)
+      continue;
+    // |target| will be used to obtain abs32 references, so we must ensure that
+    // it lies inside |image_|.
+    offset_t target = target_rva_to_offset_.Convert(target_rva);
+    if (target == kInvalidOffset || !image_.covers({target, sizeof(offset_t)}))
+      continue;
+    offset_t location = cursor_;
+    cursor_ += cur_entry_size;
+    return Reference{location, target};
+  }
+  return base::nullopt;
+}
+
+/******** RelocWriterElf ********/
+
+RelocWriterElf::RelocWriterElf(MutableBufferView image,
+                               Bitness bitness,
+                               const AddressTranslator& translator)
+    : image_(image), bitness_(bitness), target_offset_to_rva_(translator) {
+  DCHECK(bitness_ == kBit32 || bitness_ == kBit64);
+}
+
+RelocWriterElf::~RelocWriterElf() = default;
+
+void RelocWriterElf::PutNext(Reference ref) {
+  switch (bitness_) {
+    case kBit32:
+      image_.modify<elf::Elf32_Rel>(ref.location).r_offset =
+          target_offset_to_rva_.Convert(ref.target);
+      break;
+    case kBit64:
+      image_.modify<elf::Elf64_Rel>(ref.location).r_offset =
+          target_offset_to_rva_.Convert(ref.target);
+      break;
+  }
+  // Leave |reloc.r_info| alone.
+}
+
+}  // namespace zucchini
diff --git a/components/zucchini/reloc_elf.h b/components/zucchini/reloc_elf.h
new file mode 100644
index 0000000..1b5ba11
--- /dev/null
+++ b/components/zucchini/reloc_elf.h
@@ -0,0 +1,102 @@
+// 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_ZUCCHINI_RELOC_ELF_H_
+#define COMPONENTS_ZUCCHINI_RELOC_ELF_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/optional.h"
+#include "components/zucchini/address_translator.h"
+#include "components/zucchini/buffer_source.h"
+#include "components/zucchini/buffer_view.h"
+#include "components/zucchini/image_utils.h"
+#include "components/zucchini/type_elf.h"
+
+namespace zucchini {
+
+// Section dimensions for ELF files, to store relevant dimensions data from
+// Elf32_Shdr and Elf64_Shdr, while reducing code duplication from templates.
+struct SectionDimensionsElf {
+  SectionDimensionsElf() = default;
+
+  template <class Elf_Shdr>
+  explicit SectionDimensionsElf(const Elf_Shdr& section)
+      : region(BufferRegion{base::checked_cast<size_t>(section.sh_offset),
+                            base::checked_cast<size_t>(section.sh_size)}),
+        entry_size(base::checked_cast<offset_t>(section.sh_entsize)) {}
+
+  friend bool operator<(const SectionDimensionsElf& a,
+                        const SectionDimensionsElf& b) {
+    return a.region.offset < b.region.offset;
+  }
+
+  friend bool operator<(offset_t offset, const SectionDimensionsElf& section) {
+    return offset < section.region.offset;
+  }
+
+  BufferRegion region;
+  offset_t entry_size;  // Varies across REL / RELA sections.
+};
+
+// A Generator to visit all reloc structs located in [|lo|, |hi|) (excluding
+// truncated strct at |lo| but inlcuding truncated struct at |hi|), and emit
+// valid References with |rel_type|. This implements a nested loop unrolled into
+// a generator: the outer loop has |cur_section_dimensions_| visiting
+// |reloc_section_dims| (sorted by |region.offset|), and the inner loop has
+// |cursor_| visiting successive reloc structs within |cur_section_dimensions_|.
+class RelocReaderElf : public ReferenceReader {
+ public:
+  RelocReaderElf(
+      ConstBufferView image,
+      Bitness bitness,
+      const std::vector<SectionDimensionsElf>& reloc_section_dimensions,
+      uint32_t rel_type,
+      offset_t lo,
+      offset_t hi,
+      const AddressTranslator& translator);
+  ~RelocReaderElf() override;
+
+  // If |rel| contains |r_offset| for |rel_type_|, return the RVA. Otherwise
+  // return |kInvalidRva|. These also handle Elf*_Rela, by using the fact that
+  // Elf*_Rel is a prefix of Elf*_Rela.
+  rva_t GetRelocationTarget(elf::Elf32_Rel rel) const;
+  rva_t GetRelocationTarget(elf::Elf64_Rel rel) const;
+
+  // ReferenceReader:
+  base::Optional<Reference> GetNext() override;
+
+ private:
+  const ConstBufferView image_;
+  const Bitness bitness_;
+  const uint32_t rel_type_;
+  const std::vector<SectionDimensionsElf>& reloc_section_dimensions_;
+  std::vector<SectionDimensionsElf>::const_iterator cur_section_dimensions_;
+  offset_t hi_;
+  offset_t cursor_;
+  AddressTranslator::RvaToOffsetCache target_rva_to_offset_;
+};
+
+class RelocWriterElf : public ReferenceWriter {
+ public:
+  RelocWriterElf(MutableBufferView image,
+                 Bitness bitness,
+                 const AddressTranslator& translator);
+  ~RelocWriterElf() override;
+
+  // ReferenceWriter:
+  void PutNext(Reference ref) override;
+
+ private:
+  MutableBufferView image_;
+  const Bitness bitness_;
+  AddressTranslator::OffsetToRvaCache target_offset_to_rva_;
+};
+
+}  // namespace zucchini
+
+#endif  // COMPONENTS_ZUCCHINI_RELOC_ELF_H_
diff --git a/components/zucchini/reloc_elf_unittest.cc b/components/zucchini/reloc_elf_unittest.cc
new file mode 100644
index 0000000..104694e
--- /dev/null
+++ b/components/zucchini/reloc_elf_unittest.cc
@@ -0,0 +1,127 @@
+// 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/zucchini/reloc_elf.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+#include "base/numerics/safe_conversions.h"
+#include "components/zucchini/address_translator.h"
+#include "components/zucchini/algorithm.h"
+#include "components/zucchini/image_utils.h"
+#include "components/zucchini/test_utils.h"
+#include "components/zucchini/type_elf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace zucchini {
+
+namespace {
+
+template <class Elf_Shdr>
+SectionDimensionsElf MakeSectionDimensions(const BufferRegion& region,
+                                           offset_t entry_size) {
+  using sh_offset_t = decltype(Elf_Shdr::sh_offset);
+  using sh_size_t = decltype(Elf_Shdr::sh_size);
+  using sh_entsize_t = decltype(Elf_Shdr::sh_entsize);
+  return SectionDimensionsElf{Elf_Shdr{
+      0,  // sh_name
+      0,  // sh_type
+      0,  // sh_flags
+      0,  // sh_addr
+      // sh_offset
+      base::checked_cast<sh_offset_t>(region.offset),
+      // sh_size
+      base::checked_cast<sh_size_t>(region.size),
+      0,  // sh_link
+      0,  // sh_info
+      0,  // sh_addralign
+      // sh_entsize
+      base::checked_cast<sh_entsize_t>(entry_size),
+  }};
+}
+
+}  // namespace
+
+TEST(RelocElfTest, ReadWrite32) {
+  // Set up mock image: Size = 0x3000, .reloc at 0x600. RVA is 0x40000 + offset.
+  constexpr rva_t kBaseRva = 0x40000;
+  std::vector<uint8_t> image_data(0x3000, 0xFF);
+  // "C0 10 04 00 08 00 00 00" represents
+  // (r_sym, r_type, r_offset) = (0x000000, 0x08, 0x000410C0).
+  // r_type = 0x08 = R_386_RELATIVE, and under this r_offset is an RVA
+  // 0x000410C0. Zucchini does not care about r_sym.
+  std::vector<uint8_t> reloc_data1 = ParseHexString(
+      "C0 10 04 00 08 00 00 00 "  // R_386_RELATIVE.
+      "F8 10 04 00 08 AB CD EF "  // R_386_RELATIVE.
+      "00 10 04 00 00 AB CD EF "  // R_386_NONE.
+      "00 10 04 00 07 AB CD EF"   // R_386_JMP_SLOT.
+      );
+  BufferRegion reloc_region1 = {0x600, reloc_data1.size()};
+  std::copy(reloc_data1.begin(), reloc_data1.end(),
+            image_data.begin() + reloc_region1.lo());
+
+  std::vector<uint8_t> reloc_data2 = ParseHexString(
+      "BC 20 04 00 08 00 00 00 "  // R_386_RELATIVE.
+      "A0 20 04 00 08 AB CD EF"   // R_386_RELATIVE.
+      );
+  BufferRegion reloc_region2 = {0x620, reloc_data2.size()};
+  std::copy(reloc_data2.begin(), reloc_data2.end(),
+            image_data.begin() + reloc_region2.lo());
+
+  ConstBufferView image = {image_data.data(), image_data.size()};
+  offset_t image_size = base::checked_cast<offset_t>(image_data.size());
+
+  AddressTranslator translator;
+  translator.Initialize({{0, image_size, kBaseRva, image_size}});
+
+  std::vector<SectionDimensionsElf> section_dimensions{
+      MakeSectionDimensions<elf::Elf32_Shdr>(reloc_region1, 8),
+      MakeSectionDimensions<elf::Elf32_Shdr>(reloc_region2, 8)};
+
+  // Make RelocReaderElf.
+  auto reader = std::make_unique<RelocReaderElf>(
+      image, kBit32, section_dimensions, elf::R_386_RELATIVE, 0, image_size,
+      translator);
+
+  // Read all references and check.
+  std::vector<Reference> refs;
+  for (base::Optional<Reference> ref = reader->GetNext(); ref.has_value();
+       ref = reader->GetNext()) {
+    refs.push_back(ref.value());
+  }
+  // Only R_386_RELATIVE references are extracted. Targets are translated from
+  // address (e.g., 0x000420BC) to offset (e.g., 0x20BC).
+  std::vector<Reference> exp_refs{
+      {0x600, 0x10C0}, {0x608, 0x10F8}, {0x620, 0x20BC}, {0x628, 0x20A0}};
+  EXPECT_EQ(exp_refs, refs);
+
+  // Write reference, extract bytes and check.
+  MutableBufferView mutable_image(&image_data[0], image_data.size());
+  auto writer =
+      std::make_unique<RelocWriterElf>(mutable_image, kBit32, translator);
+
+  writer->PutNext({0x608, 0x1F83});
+  std::vector<uint8_t> exp_reloc_data1 = ParseHexString(
+      "C0 10 04 00 08 00 00 00 "  // R_386_RELATIVE.
+      "83 1F 04 00 08 AB CD EF "  // R_386_RELATIVE (address modified).
+      "00 10 04 00 00 AB CD EF "  // R_386_NONE.
+      "00 10 04 00 07 AB CD EF "  // R_386_JMP_SLOT.
+      );
+  EXPECT_EQ(exp_reloc_data1,
+            Sub(image_data, reloc_region1.lo(), reloc_region1.hi()));
+
+  writer->PutNext({0x628, 0x2950});
+  std::vector<uint8_t> exp_reloc_data2 = ParseHexString(
+      "BC 20 04 00 08 00 00 00 "  // R_386_RELATIVE.
+      "50 29 04 00 08 AB CD EF"   // R_386_RELATIVE (address modified).
+      );
+  EXPECT_EQ(exp_reloc_data2,
+            Sub(image_data, reloc_region2.lo(), reloc_region2.hi()));
+}
+
+}  // namespace zucchini
diff --git a/components/zucchini/reloc_win32_unittest.cc b/components/zucchini/reloc_win32_unittest.cc
index ca9bbe6..eaf55e1 100644
--- a/components/zucchini/reloc_win32_unittest.cc
+++ b/components/zucchini/reloc_win32_unittest.cc
@@ -23,25 +23,6 @@
 
 namespace zucchini {
 
-namespace {
-
-// Returns a vector that's the contatenation of two vectors of the same type.
-// Elements are copied by value.
-template <class T>
-std::vector<T> Cat(const std::vector<T>& a, const std::vector<T>& b) {
-  std::vector<T> ret(a);
-  ret.insert(ret.end(), b.begin(), b.end());
-  return ret;
-}
-
-// Returns a subvector of a vector. Elements are copied by value.
-template <class T>
-std::vector<T> Sub(const std::vector<T>& a, size_t lo, size_t hi) {
-  return std::vector<T>(a.begin() + lo, a.begin() + hi);
-}
-
-}  // namespace
-
 class RelocUtilsWin32Test : public testing::Test {
  protected:
   using Units = std::vector<RelocUnitWin32>;
diff --git a/components/zucchini/test_utils.h b/components/zucchini/test_utils.h
index 7ed735d..e922343 100644
--- a/components/zucchini/test_utils.h
+++ b/components/zucchini/test_utils.h
@@ -15,6 +15,21 @@
 // Parses space-separated list of byte hex values into list.
 std::vector<uint8_t> ParseHexString(const std::string& hex_string);
 
+// Returns a vector that's the contatenation of two vectors of the same type.
+// Elements are copied by value.
+template <class T>
+std::vector<T> Cat(const std::vector<T>& a, const std::vector<T>& b) {
+  std::vector<T> ret(a);
+  ret.insert(ret.end(), b.begin(), b.end());
+  return ret;
+}
+
+// Returns a subvector of a vector. Elements are copied by value.
+template <class T>
+std::vector<T> Sub(const std::vector<T>& a, size_t lo, size_t hi) {
+  return std::vector<T>(a.begin() + lo, a.begin() + hi);
+}
+
 }  // namespace zucchini
 
 #endif  // COMPONENTS_ZUCCHINI_TEST_UTILS_H_
diff --git a/components/zucchini/type_elf.h b/components/zucchini/type_elf.h
new file mode 100644
index 0000000..99dcba2
--- /dev/null
+++ b/components/zucchini/type_elf.h
@@ -0,0 +1,252 @@
+// 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_ZUCCHINI_TYPE_ELF_H_
+#define COMPONENTS_ZUCCHINI_TYPE_ELF_H_
+
+#include <stdint.h>
+
+namespace zucchini {
+
+// Structures and constants taken from linux/elf.h and following identical
+// layout. This is used for parsing of Executable and Linkable Format (ELF).
+namespace elf {
+// Supported by MSVC, g++, and clang++. Ensures no gaps in packing.
+#pragma pack(push, 1)
+
+// This header defines various types from the ELF file spec, but no code
+// related to using them.
+
+typedef uint32_t Elf32_Addr;  // Unsigned program address.
+typedef uint16_t Elf32_Half;  // Unsigned medium integer.
+typedef uint32_t Elf32_Off;   // Unsigned file offset.
+typedef int32_t Elf32_Sword;  // Signed large integer.
+typedef uint32_t Elf32_Word;  // Unsigned large integer.
+
+typedef uint64_t Elf64_Addr;   // Unsigned program address.
+typedef uint16_t Elf64_Half;   // Unsigned medium integer.
+typedef uint64_t Elf64_Off;    // Unsigned file offset.
+typedef int32_t Elf64_Sword;   // Signed large integer.
+typedef uint32_t Elf64_Word;   // Unsigned large integer.
+typedef int64_t Elf64_Sxword;  // Signed extra large integer.
+typedef uint64_t Elf64_Xword;  // Unsigned extra large integer.
+
+// The header at the top of the file.
+struct Elf32_Ehdr {
+  unsigned char e_ident[16];
+  Elf32_Half e_type;
+  Elf32_Half e_machine;
+  Elf32_Word e_version;
+  Elf32_Addr e_entry;
+  Elf32_Off e_phoff;
+  Elf32_Off e_shoff;
+  Elf32_Word e_flags;
+  Elf32_Half e_ehsize;
+  Elf32_Half e_phentsize;
+  Elf32_Half e_phnum;
+  Elf32_Half e_shentsize;
+  Elf32_Half e_shnum;
+  Elf32_Half e_shstrndx;
+};
+
+struct Elf64_Ehdr {
+  unsigned char e_ident[16];
+  Elf64_Half e_type;
+  Elf64_Half e_machine;
+  Elf64_Word e_version;
+  Elf64_Addr e_entry;
+  Elf64_Off e_phoff;
+  Elf64_Off e_shoff;
+  Elf64_Word e_flags;
+  Elf64_Half e_ehsize;
+  Elf64_Half e_phentsize;
+  Elf64_Half e_phnum;
+  Elf64_Half e_shentsize;
+  Elf64_Half e_shnum;
+  Elf64_Half e_shstrndx;
+};
+
+// Values for header->e_type.
+enum e_type_values {
+  ET_NONE = 0,         // No file type
+  ET_REL = 1,          // Relocatable file
+  ET_EXEC = 2,         // Executable file
+  ET_DYN = 3,          // Shared object file
+  ET_CORE = 4,         // Core file
+  ET_LOPROC = 0xFF00,  // Processor-specific
+  ET_HIPROC = 0xFFFF   // Processor-specific
+};
+
+// Values for header->e_machine.
+enum e_machine_values {
+  EM_NONE = 0,       // No machine.
+  EM_386 = 3,        // Intel Architecture.
+  EM_ARM = 40,       // ARM Architecture.
+  EM_X86_64 = 62,    // Intel x86-64 Architecture.
+  EM_AARCH64 = 183,  // ARM Architecture, 64-bit.
+  // Other values skipped.
+};
+
+// A section header in the section header table.
+struct Elf32_Shdr {
+  Elf32_Word sh_name;
+  Elf32_Word sh_type;
+  Elf32_Word sh_flags;
+  Elf32_Addr sh_addr;
+  Elf32_Off sh_offset;
+  Elf32_Word sh_size;
+  Elf32_Word sh_link;
+  Elf32_Word sh_info;
+  Elf32_Word sh_addralign;
+  Elf32_Word sh_entsize;
+};
+
+struct Elf64_Shdr {
+  Elf64_Word sh_name;
+  Elf64_Word sh_type;
+  Elf64_Xword sh_flags;
+  Elf64_Addr sh_addr;
+  Elf64_Off sh_offset;
+  Elf64_Xword sh_size;
+  Elf64_Word sh_link;
+  Elf64_Word sh_info;
+  Elf64_Xword sh_addralign;
+  Elf64_Xword sh_entsize;
+};
+
+// Values for the section type field in a section header.
+enum sh_type_values {
+  SHT_NULL = 0,
+  SHT_PROGBITS = 1,
+  SHT_SYMTAB = 2,
+  SHT_STRTAB = 3,
+  SHT_RELA = 4,
+  SHT_HASH = 5,
+  SHT_DYNAMIC = 6,
+  SHT_NOTE = 7,
+  SHT_NOBITS = 8,
+  SHT_REL = 9,
+  SHT_SHLIB = 10,
+  SHT_DYNSYM = 11,
+  SHT_INIT_ARRAY = 14,
+  SHT_FINI_ARRAY = 15,
+  SHT_LOPROC = 0x70000000,
+  SHT_HIPROC = 0x7FFFFFFF,
+  SHT_LOUSER = 0x80000000,
+  SHT_HIUSER = 0xFFFFFFFF
+};
+
+enum sh_flag_masks {
+  SHF_WRITE = 1 << 0,
+  SHF_ALLOC = 1 << 1,
+  SHF_EXECINSTR = 1 << 2,
+};
+
+struct Elf32_Phdr {
+  Elf32_Word p_type;
+  Elf32_Off p_offset;
+  Elf32_Addr p_vaddr;
+  Elf32_Addr p_paddr;
+  Elf32_Word p_filesz;
+  Elf32_Word p_memsz;
+  Elf32_Word p_flags;
+  Elf32_Word p_align;
+};
+
+struct Elf64_Phdr {
+  Elf64_Word p_type;
+  Elf64_Word p_flags;
+  Elf64_Off p_offset;
+  Elf64_Addr p_vaddr;
+  Elf64_Addr p_paddr;
+  Elf64_Xword p_filesz;
+  Elf64_Xword p_memsz;
+  Elf64_Xword p_align;
+};
+
+// Values for the segment type field in a program segment header.
+enum ph_type_values {
+  PT_NULL = 0,
+  PT_LOAD = 1,
+  PT_DYNAMIC = 2,
+  PT_INTERP = 3,
+  PT_NOTE = 4,
+  PT_SHLIB = 5,
+  PT_PHDR = 6,
+  PT_LOPROC = 0x70000000,
+  PT_HIPROC = 0x7FFFFFFF
+};
+
+struct Elf32_Rel {
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+};
+
+struct Elf64_Rel {
+  Elf64_Addr r_offset;
+  Elf64_Xword r_info;
+};
+
+struct Elf32_Rela {
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+  Elf32_Sword r_addend;
+};
+
+struct Elf64_Rela {
+  Elf64_Addr r_offset;
+  Elf64_Xword r_info;
+  Elf64_Sxword r_addend;
+};
+
+enum elf32_rel_386_type_values {
+  R_386_NONE = 0,
+  R_386_32 = 1,
+  R_386_PC32 = 2,
+  R_386_GOT32 = 3,
+  R_386_PLT32 = 4,
+  R_386_COPY = 5,
+  R_386_GLOB_DAT = 6,
+  R_386_JMP_SLOT = 7,
+  R_386_RELATIVE = 8,
+  R_386_GOTOFF = 9,
+  R_386_GOTPC = 10,
+  R_386_TLS_TPOFF = 14,
+};
+
+enum elf32_rel_x86_64_type_values {
+  R_X86_64_NONE = 0,
+  R_X86_64_64 = 1,
+  R_X86_64_PC32 = 2,
+  R_X86_64_GOT32 = 3,
+  R_X86_64_PLT32 = 4,
+  R_X86_64_COPY = 5,
+  R_X86_64_GLOB_DAT = 6,
+  R_X86_64_JUMP_SLOT = 7,
+  R_X86_64_RELATIVE = 8,
+  R_X86_64_GOTPCREL = 9,
+  R_X86_64_32 = 10,
+  R_X86_64_32S = 11,
+  R_X86_64_16 = 12,
+  R_X86_64_PC16 = 13,
+  R_X86_64_8 = 14,
+  R_X86_64_PC8 = 15,
+};
+
+enum elf32_rel_arm_type_values {
+  R_ARM_RELATIVE = 23,
+};
+
+enum elf64_rel_aarch64_type_values {
+  R_AARCH64_GLOB_DAT = 0x401,
+  R_AARCH64_JUMP_SLOT = 0x402,
+  R_AARCH64_RELATIVE = 0x403,
+};
+
+#pragma pack(pop)
+
+}  // namespace elf
+}  // namespace zucchini
+
+#endif  // COMPONENTS_ZUCCHINI_TYPE_ELF_H_
diff --git a/content/app/strings/translations/content_strings_ar.xtb b/content/app/strings/translations/content_strings_ar.xtb
index c5b663f..380b81cc 100644
--- a/content/app/strings/translations/content_strings_ar.xtb
+++ b/content/app/strings/translations/content_strings_ar.xtb
@@ -12,6 +12,7 @@
 <translation id="1206693055195146388">شريط تمرير</translation>
 <translation id="1211441953136645838">تعليق ختامي</translation>
 <translation id="1281252709823657822">مربع حوار</translation>
+<translation id="1289247557029249093">الخروج من وضع "نافذة ضمن النافذة"</translation>
 <translation id="1335095011850992622">إسهامات</translation>
 <translation id="1342835525016946179">article</translation>
 <translation id="1359897965706325498">إعلان بانر</translation>
@@ -51,6 +52,7 @@
 <translation id="2653659639078652383">إرسال</translation>
 <translation id="2657045182931379222">كائن رسومي</translation>
 <translation id="2674318244760992338">تذييل</translation>
+<translation id="2706474812903655270">يتم تشغيل هذا الفيديو في الوضع "نافذة ضمن النافذة".</translation>
 <translation id="2709516037105925701">الملء التلقائي</translation>
 <translation id="2723001399770238859">الصوت</translation>
 <translation id="2746543609216772311">يجب أن تكون القيمة <ph name="MINIMUM_DATE_OR_TIME" /> أو بعد ذلك.</translation>
@@ -189,6 +191,7 @@
 <translation id="7720026100085573005">المدة المتبقية</translation>
 <translation id="7740016676195725605">إيقاف عرض الترجمة والشرح</translation>
 <translation id="7740050170769002709">‏محتوى HTML</translation>
+<translation id="7750228210027921155">نافذة ضمن النافذة</translation>
 <translation id="7789962463072032349">إيقاف مؤقت</translation>
 <translation id="7802800022689234070">مثلث الإفصاح</translation>
 <translation id="7888071071722539607">يُرجى تضمين العلامة "<ph name="ATSIGN" />" في عنوان البريد الإلكتروني، حيث يفتقر "<ph name="INVALIDADDRESS" />" إلى العلامة "<ph name="ATSIGN" />".</translation>
diff --git a/content/app/strings/translations/content_strings_bn.xtb b/content/app/strings/translations/content_strings_bn.xtb
index 5ce005c..4cad3eb 100644
--- a/content/app/strings/translations/content_strings_bn.xtb
+++ b/content/app/strings/translations/content_strings_bn.xtb
@@ -12,6 +12,7 @@
 <translation id="1206693055195146388">স্লাইডার</translation>
 <translation id="1211441953136645838">এন্ডনোট</translation>
 <translation id="1281252709823657822">ডায়ালগ</translation>
+<translation id="1289247557029249093">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
 <translation id="1335095011850992622">ক্রেডিট</translation>
 <translation id="1342835525016946179">নিবন্ধ</translation>
 <translation id="1359897965706325498">ব্যানার</translation>
@@ -51,6 +52,7 @@
 <translation id="2653659639078652383">জমা দিন</translation>
 <translation id="2657045182931379222">গ্রাফিক্স অবজেক্ট</translation>
 <translation id="2674318244760992338">পাদলেখ</translation>
+<translation id="2706474812903655270">এই ভিডিওটি ছবির-মধ্যে-ছবি মোডে চালানো হচ্ছে</translation>
 <translation id="2709516037105925701">স্বয়ংপূরণ</translation>
 <translation id="2723001399770238859">অডিও</translation>
 <translation id="2746543609216772311">মানকে অবশ্যই <ph name="MINIMUM_DATE_OR_TIME" /> বা পরবর্তী হতে হবে৷</translation>
@@ -189,6 +191,7 @@
 <translation id="7720026100085573005">অবশিষ্ট সময়</translation>
 <translation id="7740016676195725605">বদ্ধ পরিচয়লিপিগুলির প্রদর্শন থামান</translation>
 <translation id="7740050170769002709">HTML সামগ্রী</translation>
+<translation id="7750228210027921155">ছবির-মধ্যে-ছবি</translation>
 <translation id="7789962463072032349">বিরাম</translation>
 <translation id="7802800022689234070">উম্মোচন ত্রিভুজ</translation>
 <translation id="7888071071722539607">ইমেল ঠিনাকাটিতে দয়া করে একটি '<ph name="ATSIGN" />' অন্তর্ভুক্ত করুন৷ '<ph name="INVALIDADDRESS" />' এ একটি '<ph name="ATSIGN" />' অনুপস্থিত৷</translation>
diff --git a/content/app/strings/translations/content_strings_ru.xtb b/content/app/strings/translations/content_strings_ru.xtb
index 7bb2a51..4ebbc1c 100644
--- a/content/app/strings/translations/content_strings_ru.xtb
+++ b/content/app/strings/translations/content_strings_ru.xtb
@@ -12,6 +12,7 @@
 <translation id="1206693055195146388">ползунок</translation>
 <translation id="1211441953136645838">концевая сноска</translation>
 <translation id="1281252709823657822">диалоговое окно</translation>
+<translation id="1289247557029249093">Выйти из режима "Картинка в картинке"</translation>
 <translation id="1335095011850992622">выходные сведения</translation>
 <translation id="1342835525016946179">article</translation>
 <translation id="1359897965706325498">баннер</translation>
@@ -51,6 +52,7 @@
 <translation id="2653659639078652383">Отправить</translation>
 <translation id="2657045182931379222">графический объект</translation>
 <translation id="2674318244760992338">нижний колонтитул</translation>
+<translation id="2706474812903655270">Видео воспроизводится в режиме "Картинка в картинке".</translation>
 <translation id="2709516037105925701">Автозаполнение</translation>
 <translation id="2723001399770238859">аудио</translation>
 <translation id="2746543609216772311">Минимальное значение должно быть <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
@@ -189,6 +191,7 @@
 <translation id="7720026100085573005">оставшееся время</translation>
 <translation id="7740016676195725605">скрыть субтитры</translation>
 <translation id="7740050170769002709">HTML-содержание</translation>
+<translation id="7750228210027921155">Картинка в картинке</translation>
 <translation id="7789962463072032349">Пауза</translation>
 <translation id="7802800022689234070">треугольник развертывания</translation>
 <translation id="7888071071722539607">Адрес электронной почты должен содержать символ "<ph name="ATSIGN" />". В адресе "<ph name="INVALIDADDRESS" />" отсутствует символ "<ph name="ATSIGN" />".</translation>
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 43e712c..d61a444 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -752,8 +752,6 @@
     "download/download_request_utils.cc",
     "download/download_resource_handler.cc",
     "download/download_resource_handler.h",
-    "download/download_url_loader_factory_getter_impl.cc",
-    "download/download_url_loader_factory_getter_impl.h",
     "download/download_utils.cc",
     "download/download_utils.h",
     "download/drag_download_file.cc",
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc
index cc2c5f0..2e6f1b9 100644
--- a/content/browser/background_fetch/background_fetch_context.cc
+++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -182,7 +182,8 @@
 
 void BackgroundFetchContext::UpdateUI(
     const BackgroundFetchRegistrationId& registration_id,
-    const std::string& title,
+    const base::Optional<std::string>& title,
+    const base::Optional<SkBitmap>& icon,
     blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -193,7 +194,7 @@
     return;
   }
 
-  data_manager_->UpdateRegistrationUI(registration_id, title,
+  data_manager_->UpdateRegistrationUI(registration_id, title, icon,
                                       std::move(callback));
 }
 
diff --git a/content/browser/background_fetch/background_fetch_context.h b/content/browser/background_fetch/background_fetch_context.h
index f2ec5e3..683595b 100644
--- a/content/browser/background_fetch/background_fetch_context.h
+++ b/content/browser/background_fetch/background_fetch_context.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
 #include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
 #include "content/browser/background_fetch/background_fetch_event_dispatcher.h"
@@ -105,12 +106,15 @@
       const std::string& unique_id,
       blink::mojom::BackgroundFetchRegistrationObserverPtr observer);
 
-  // Updates the title of the Background Fetch identified by |registration_id|.
-  // The |callback| will be invoked when the title has been updated, or an error
-  // occurred that prevents it from doing so.
+  // Updates the title or icon of the Background Fetch identified by
+  // |registration_id|. The |callback| will be invoked when the title has been
+  // updated, or an error occurred that prevents it from doing so.
+  // The icon is wrapped in an optional. If the optional has a value then the
+  // internal |icon| is guarnteed to be not null.
   void UpdateUI(
       const BackgroundFetchRegistrationId& registration_id,
-      const std::string& title,
+      const base::Optional<std::string>& title,
+      const base::Optional<SkBitmap>& icon,
       blink::mojom::BackgroundFetchService::UpdateUICallback callback);
 
   // BackgroundFetchDataManagerObserver implementation.
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index b2b3d9e4..3157dc5 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -116,12 +116,13 @@
 
 void BackgroundFetchDataManager::UpdateRegistrationUI(
     const BackgroundFetchRegistrationId& registration_id,
-    const std::string& title,
+    const base::Optional<std::string>& title,
+    const base::Optional<SkBitmap>& icon,
     blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AddDatabaseTask(std::make_unique<background_fetch::UpdateRegistrationUITask>(
-      this, registration_id, title, std::move(callback)));
+      this, registration_id, title, icon, std::move(callback)));
 }
 
 void BackgroundFetchDataManager::PopNextRequest(
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h
index 6dd5b81..cdc4d36 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "content/browser/background_fetch/background_fetch.pb.h"
 #include "content/browser/background_fetch/background_fetch_registration_id.h"
 #include "content/browser/background_fetch/background_fetch_scheduler.h"
@@ -111,7 +112,8 @@
   // Updates the UI values for a Background Fetch registration.
   void UpdateRegistrationUI(
       const BackgroundFetchRegistrationId& registration_id,
-      const std::string& title,
+      const base::Optional<std::string>& title,
+      const base::Optional<SkBitmap>& icon,
       blink::mojom::BackgroundFetchService::UpdateUICallback callback);
 
   // Reads the settled fetches for the given |registration_id| based on
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index 9ac1b3e..b94712f 100644
--- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "content/browser/background_fetch/background_fetch_test_base.h"
 #include "content/browser/background_fetch/background_fetch_test_data_manager.h"
 #include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/image_helpers.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/public/browser/background_fetch_response.h"
@@ -148,6 +149,23 @@
   return requests;
 }
 
+SkBitmap CreateTestIcon(int size = 42, SkColor color = SK_ColorGREEN) {
+  SkBitmap icon;
+  icon.allocN32Pixels(size, size);
+  icon.eraseColor(SK_ColorGREEN);
+  return icon;
+}
+
+void ExpectIconProperties(const SkBitmap& icon, int size, SkColor color) {
+  EXPECT_FALSE(icon.isNull());
+  EXPECT_EQ(icon.width(), size);
+  EXPECT_EQ(icon.height(), size);
+  for (int i = 0; i < icon.width(); i++) {
+    for (int j = 0; j < icon.height(); j++)
+      EXPECT_EQ(icon.getColor(i, j), color);
+  }
+}
+
 }  // namespace
 
 class BackgroundFetchDataManagerTest
@@ -245,13 +263,14 @@
 
   void UpdateRegistrationUI(
       const BackgroundFetchRegistrationId& registration_id,
-      const std::string& updated_title,
+      const base::Optional<std::string>& updated_title,
+      const base::Optional<SkBitmap>& updated_icon,
       blink::mojom::BackgroundFetchError* out_error) {
     DCHECK(out_error);
 
     base::RunLoop run_loop;
     background_fetch_data_manager_->UpdateRegistrationUI(
-        registration_id, updated_title,
+        registration_id, updated_title, updated_icon,
         base::BindOnce(&BackgroundFetchDataManagerTest::DidUpdateRegistrationUI,
                        base::Unretained(this), run_loop.QuitClosure(),
                        out_error));
@@ -406,7 +425,8 @@
     return result;
   }
 
-  proto::BackgroundFetchUIOptions GetUIOptions(
+  // Returns the title and the icon.
+  std::pair<std::string, SkBitmap> GetUIOptions(
       int64_t service_worker_registration_id) {
     auto results = GetRegistrationUserDataByKeyPrefix(
         service_worker_registration_id, background_fetch::kUIOptionsKeyPrefix);
@@ -415,11 +435,33 @@
 
     proto::BackgroundFetchUIOptions ui_options;
     if (results.empty())
-      return ui_options;
+      return {"", SkBitmap()};
 
     bool did_parse = ui_options.ParseFromString(results[0]);
     DCHECK(did_parse);
-    return ui_options;
+
+    std::pair<std::string, SkBitmap> result{ui_options.title(), SkBitmap()};
+
+    if (ui_options.icon().empty())
+      return result;
+
+    // Deserialize icon.
+    {
+      base::RunLoop run_loop;
+      background_fetch::DeserializeIcon(
+          std::unique_ptr<std::string>(ui_options.release_icon()),
+          base::BindOnce(
+              [](base::OnceClosure quit_closure, SkBitmap* out_icon,
+                 SkBitmap icon) {
+                DCHECK(out_icon);
+                *out_icon = std::move(icon);
+                std::move(quit_closure).Run();
+              },
+              run_loop.QuitClosure(), &result.second));
+      run_loop.Run();
+    }
+
+    return result;
   }
 
   // Gets information about the number of background fetch requests by state.
@@ -780,9 +822,8 @@
   BackgroundFetchOptions options;
   blink::mojom::BackgroundFetchError error;
 
-  SkBitmap icon;
-  icon.allocN32Pixels(512, 512);
-  icon.eraseColor(SK_ColorGREEN);
+  SkBitmap icon = CreateTestIcon(512 /* size */);
+  ASSERT_FALSE(background_fetch::ShouldPersistIcon(icon));
 
   // Create a single registration.
   {
@@ -798,7 +839,7 @@
   EXPECT_EQ(metadata->origin(), origin().Serialize());
   EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
   EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
-  EXPECT_TRUE(GetUIOptions(sw_id).icon().empty());
+  EXPECT_TRUE(GetUIOptions(sw_id).second.isNull());
 }
 
 TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
@@ -814,31 +855,88 @@
   blink::mojom::BackgroundFetchError error;
 
   // There should be no title before the registration.
-  EXPECT_TRUE(GetUIOptions(sw_id).title().empty());
+  EXPECT_TRUE(GetUIOptions(sw_id).first.empty());
 
   // Create a single registration.
   {
     EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
 
-    CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+    CreateRegistration(registration_id, requests, options, CreateTestIcon(),
+                       &error);
     ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
   }
 
-  // Verify that the title can be retrieved.
-  ASSERT_EQ(GetUIOptions(sw_id).title(), kInitialTitle);
+  // Verify that the UI Options can be retrieved.
+  {
+    auto ui_options = GetUIOptions(sw_id);
+    EXPECT_EQ(ui_options.first, kInitialTitle);
+    EXPECT_NO_FATAL_FAILURE(
+        ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN));
+  }
 
-  // Update the title.
+  // Update only the title.
   {
     EXPECT_CALL(*this, OnUpdatedUI(registration_id, kUpdatedTitle));
 
-    UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+    UpdateRegistrationUI(registration_id, kUpdatedTitle, base::nullopt, &error);
     ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+    auto ui_options = GetUIOptions(sw_id);
+    // Expect new title.
+    EXPECT_EQ(ui_options.first, kUpdatedTitle);
+    // Expect same icon as before.
+    EXPECT_NO_FATAL_FAILURE(
+        ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN));
   }
 
-  RestartDataManagerFromPersistentStorage();
+  // Update only the icon.
+  {
+    // TODO(crbug.com/865063): Icon updates are not supported yet.
+    EXPECT_CALL(*this, OnUpdatedUI(registration_id, kUpdatedTitle)).Times(0);
 
-  // After a restart, GetMetadata should find the new title.
-  ASSERT_EQ(GetUIOptions(sw_id).title(), kUpdatedTitle);
+    UpdateRegistrationUI(registration_id, base::nullopt,
+                         CreateTestIcon(24 /* size */), &error);
+    ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+    auto ui_options = GetUIOptions(sw_id);
+    // Expect the same title as before.
+    EXPECT_EQ(ui_options.first, kUpdatedTitle);
+    // Expect the new icon with the different size.
+    EXPECT_NO_FATAL_FAILURE(
+        ExpectIconProperties(ui_options.second, 24, SK_ColorGREEN));
+  }
+
+  // Update both the title and icon.
+  {
+    EXPECT_CALL(*this, OnUpdatedUI(registration_id, kInitialTitle));
+
+    UpdateRegistrationUI(registration_id, kInitialTitle,
+                         CreateTestIcon(66 /* size */), &error);
+    ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+    auto ui_options = GetUIOptions(sw_id);
+    // Expect the initial title again.
+    EXPECT_EQ(ui_options.first, kInitialTitle);
+    // Expect the new icon with the different size.
+    EXPECT_NO_FATAL_FAILURE(
+        ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN));
+  }
+
+  // New title and an icon that's too large.
+  {
+    EXPECT_CALL(*this, OnUpdatedUI(registration_id, kUpdatedTitle));
+
+    UpdateRegistrationUI(registration_id, kUpdatedTitle,
+                         CreateTestIcon(512 /* size */), &error);
+    ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+    auto ui_options = GetUIOptions(sw_id);
+    // Expect the new title.
+    EXPECT_EQ(ui_options.first, kUpdatedTitle);
+    // Expect same icon as before.
+    EXPECT_NO_FATAL_FAILURE(
+        ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN));
+  }
 }
 
 TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
@@ -1425,14 +1523,12 @@
   // Register a Background Fetch.
   BackgroundFetchRegistrationId registration_id(
       sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
-  SkBitmap icon;
-  icon.allocN32Pixels(42, 42);
-  icon.eraseColor(SK_ColorGREEN);
 
   {
     EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
 
-    CreateRegistration(registration_id, requests, options, icon, &error);
+    CreateRegistration(registration_id, requests, options, CreateTestIcon(),
+                       &error);
     ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
   }
 
@@ -1454,12 +1550,7 @@
 
     // Check icon.
     ASSERT_FALSE(init.icon.drawsNothing());
-    EXPECT_EQ(icon.width(), init.icon.width());
-    EXPECT_EQ(icon.height(), init.icon.height());
-    for (int i = 0; i < icon.width(); i++) {
-      for (int j = 0; j < icon.height(); j++)
-        EXPECT_EQ(init.icon.getColor(i, j), SK_ColorGREEN);
-    }
+    EXPECT_NO_FATAL_FAILURE(ExpectIconProperties(init.icon, 42, SK_ColorGREEN));
   }
 
   // Mark one request as complete and start another.
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc
index 864a1704c..6aa5ad29 100644
--- a/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -111,9 +111,7 @@
     UpdateUICallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  // TODO(crbug.com/865063): Remove the check for |title| when updating both the
-  // title and icons is supported.
-  if (!ValidateUniqueId(unique_id) || !title || !ValidateTitle(*title)) {
+  if (!ValidateUniqueId(unique_id) || (title && !ValidateTitle(*title))) {
     std::move(callback).Run(
         blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
     return;
@@ -121,7 +119,12 @@
 
   BackgroundFetchRegistrationId registration_id(
       service_worker_registration_id, origin_, developer_id, unique_id);
-  background_fetch_context_->UpdateUI(registration_id, *title,
+
+  // Wrap the icon in an optional for clarity.
+  auto optional_icon =
+      icon.isNull() ? base::nullopt : base::Optional<SkBitmap>(icon);
+
+  background_fetch_context_->UpdateUI(registration_id, title, optional_icon,
                                       std::move(callback));
 }
 
diff --git a/content/browser/background_fetch/storage/update_registration_ui_task.cc b/content/browser/background_fetch/storage/update_registration_ui_task.cc
index d4b0d36..206af94 100644
--- a/content/browser/background_fetch/storage/update_registration_ui_task.cc
+++ b/content/browser/background_fetch/storage/update_registration_ui_task.cc
@@ -7,6 +7,7 @@
 #include "content/browser/background_fetch/background_fetch_data_manager.h"
 #include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
 #include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/image_helpers.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
 
@@ -17,27 +18,77 @@
 UpdateRegistrationUITask::UpdateRegistrationUITask(
     DatabaseTaskHost* host,
     const BackgroundFetchRegistrationId& registration_id,
-    const std::string& updated_title,
+    const base::Optional<std::string>& title,
+    const base::Optional<SkBitmap>& icon,
     UpdateRegistrationUICallback callback)
     : DatabaseTask(host),
       registration_id_(registration_id),
-      updated_title_(updated_title),
+      title_(title),
+      icon_(icon),
       callback_(std::move(callback)),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  DCHECK(title_ || icon_);
+}
 
 UpdateRegistrationUITask::~UpdateRegistrationUITask() = default;
 
 void UpdateRegistrationUITask::Start() {
-  // TODO(crbug.com/865063): Persist new icon if applicable and don't
-  // overwrite unupdated values.
-  proto::BackgroundFetchUIOptions ui_options;
-  ui_options.set_title(updated_title_);
+  if (title_ && icon_ && ShouldPersistIcon(*icon_)) {
+    // Directly overwrite whatever's stored in the SWDB.
+    SerializeIcon(*icon_,
+                  base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon,
+                                 weak_factory_.GetWeakPtr()));
+    return;
+  }
+
+  service_worker_context()->GetRegistrationUserData(
+      registration_id_.service_worker_registration_id(),
+      {UIOptionsKey(registration_id_.unique_id())},
+      base::BindOnce(&UpdateRegistrationUITask::DidGetUIOptions,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void UpdateRegistrationUITask::DidGetUIOptions(
+    const std::vector<std::string>& data,
+    blink::ServiceWorkerStatusCode status) {
+  switch (ToDatabaseStatus(status)) {
+    case DatabaseStatus::kFailed:
+      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+      return;
+    case DatabaseStatus::kNotFound:
+    case DatabaseStatus::kOk:
+      break;
+  }
+
+  if (data.empty() || !ui_options_.ParseFromString(data[0])) {
+    FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+    return;
+  }
+
+  if (icon_ && ShouldPersistIcon(*icon_)) {
+    ui_options_.clear_icon();
+    SerializeIcon(*icon_,
+                  base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon,
+                                 weak_factory_.GetWeakPtr()));
+  } else {
+    StoreUIOptions();
+  }
+}
+
+void UpdateRegistrationUITask::DidSerializeIcon(std::string serialized_icon) {
+  ui_options_.set_icon(std::move(serialized_icon));
+  StoreUIOptions();
+}
+
+void UpdateRegistrationUITask::StoreUIOptions() {
+  if (title_)
+    ui_options_.set_title(*title_);
 
   service_worker_context()->StoreRegistrationUserData(
       registration_id_.service_worker_registration_id(),
       registration_id_.origin().GetURL(),
       {{UIOptionsKey(registration_id_.unique_id()),
-        ui_options.SerializeAsString()}},
+        ui_options_.SerializeAsString()}},
       base::BindOnce(&UpdateRegistrationUITask::DidUpdateUIOptions,
                      weak_factory_.GetWeakPtr()));
 }
@@ -53,14 +104,16 @@
       return;
   }
 
-  for (auto& observer : data_manager()->observers())
-    observer.OnUpdatedUI(registration_id_, updated_title_);
-
   FinishWithError(blink::mojom::BackgroundFetchError::NONE);
 }
 
 void UpdateRegistrationUITask::FinishWithError(
     blink::mojom::BackgroundFetchError error) {
+  for (auto& observer : data_manager()->observers()) {
+    if (title_)
+      observer.OnUpdatedUI(registration_id_, *title_);
+  }
+
   std::move(callback_).Run(error);
   Finished();  // Destroys |this|.
 }
diff --git a/content/browser/background_fetch/storage/update_registration_ui_task.h b/content/browser/background_fetch/storage/update_registration_ui_task.h
index f3e7a0e..c5fe433 100644
--- a/content/browser/background_fetch/storage/update_registration_ui_task.h
+++ b/content/browser/background_fetch/storage/update_registration_ui_task.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/optional.h"
 #include "content/browser/background_fetch/background_fetch.pb.h"
 #include "content/browser/background_fetch/storage/database_task.h"
 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
@@ -25,7 +26,8 @@
 
   UpdateRegistrationUITask(DatabaseTaskHost* host,
                            const BackgroundFetchRegistrationId& registration_id,
-                           const std::string& updated_title,
+                           const base::Optional<std::string>& title,
+                           const base::Optional<SkBitmap>& icon,
                            UpdateRegistrationUICallback callback);
 
   ~UpdateRegistrationUITask() override;
@@ -33,12 +35,22 @@
   void Start() override;
 
  private:
+  void DidGetUIOptions(const std::vector<std::string>& data,
+                       blink::ServiceWorkerStatusCode status);
+
+  void DidSerializeIcon(std::string serialized_icon);
+
+  void StoreUIOptions();
+
   void DidUpdateUIOptions(blink::ServiceWorkerStatusCode status);
 
   void FinishWithError(blink::mojom::BackgroundFetchError error) override;
 
   BackgroundFetchRegistrationId registration_id_;
-  std::string updated_title_;
+  base::Optional<std::string> title_;
+  base::Optional<SkBitmap> icon_;
+
+  proto::BackgroundFetchUIOptions ui_options_;
 
   UpdateRegistrationUICallback callback_;
 
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index a04987f..813b1b5 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -33,6 +33,7 @@
 #include "components/download/public/common/download_stats.h"
 #include "components/download/public/common/download_task_runner.h"
 #include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "components/download/public/common/download_url_loader_factory_getter_impl.h"
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/download_utils.h"
 #include "components/download/public/common/url_download_handler_factory.h"
@@ -41,7 +42,6 @@
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
 #include "content/browser/download/byte_stream_input_stream.h"
 #include "content/browser/download/download_resource_handler.h"
-#include "content/browser/download/download_url_loader_factory_getter_impl.h"
 #include "content/browser/download/download_utils.h"
 #include "content/browser/download/file_download_url_loader_factory_getter.h"
 #include "content/browser/download/file_system_download_url_loader_factory_getter.h"
@@ -1131,7 +1131,7 @@
   if (blob_url_loader_factory) {
     DCHECK(params->url().SchemeIsBlob());
     url_loader_factory_getter =
-        base::MakeRefCounted<DownloadURLLoaderFactoryGetterImpl>(
+        base::MakeRefCounted<download::DownloadURLLoaderFactoryGetterImpl>(
             blob_url_loader_factory->Clone());
   } else if (params->url().SchemeIsFile()) {
     url_loader_factory_getter =
diff --git a/content/browser/frame_host/debug_urls.cc b/content/browser/frame_host/debug_urls.cc
index f66e16a..78868e2 100644
--- a/content/browser/frame_host/debug_urls.cc
+++ b/content/browser/frame_host/debug_urls.cc
@@ -26,6 +26,10 @@
 #include "ppapi/proxy/ppapi_messages.h"  // nogncheck
 #endif
 
+#if defined(OS_WIN)
+#include "base/debug/invalid_access_win.h"
+#endif
+
 namespace content {
 
 class ScopedAllowWaitForDebugURL {
@@ -142,6 +146,14 @@
     return true;
   }
 
+#if defined(OS_WIN)
+  if (url == kChromeUIBrowserHeapCorruptionURL) {
+    // Induce an intentional heap corruption in the browser process.
+    base::debug::win::TerminateWithHeapCorruption();
+    return true;
+  }
+#endif
+
   if (url == kChromeUIBrowserUIHang) {
     HangCurrentThread();
     return true;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 8e5af3e..57c9276 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2103,8 +2103,11 @@
 
   // Reset frame tree state associated with this process.  This must happen
   // before RenderViewTerminated because observers expect the subframes of any
-  // affected frames to be cleared first.
-  frame_tree_node_->ResetForNewProcess();
+  // affected frames to be cleared first.  Only do this if this is the current
+  // RenderFrameHost; if the process goes away for a pending delete or
+  // speculative RFH, we shouldn't remove subframes from the current RFH.
+  if (IsCurrent())
+    frame_tree_node_->ResetForNewProcess();
 
   // Reset state for the current RenderFrameHost once the FrameTreeNode has been
   // reset.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 1ce2598..285742afa7 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -819,6 +819,9 @@
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
                            WebUIJavascriptDisallowedAfterSwapOut);
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, LastCommittedOrigin);
+  FRIEND_TEST_ALL_PREFIXES(
+      RenderFrameHostManagerUnloadBrowserTest,
+      PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes);
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, FindImmediateLocalRoots);
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index 6224225..f97ec5a 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -4885,4 +4885,53 @@
   EXPECT_EQ("bar", message);
 }
 
+// Ensure that when a pending delete RenderFrameHost's process dies, the
+// current RenderFrameHost does not lose its child frames.  See
+// https://crbug.com/867274.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+                       PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes) {
+  GURL first_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), first_url));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  RenderFrameHostImpl* rfh = root->current_frame_host();
+
+  // Set up an unload handler which never finishes to force |rfh| to stay
+  // around in pending delete state and never receive the swapout ACK.
+  EXPECT_TRUE(
+      ExecuteScript(rfh, "window.onunload = function(e) { while(1); };\n"));
+  rfh->DisableSwapOutTimerForTesting();
+
+  // Navigate to another page with two subframes.
+  RenderFrameDeletedObserver rfh_observer(rfh);
+  GURL second_url(embedded_test_server()->GetURL(
+      "b.com", "/cross_site_iframe_factory.html?b(c,b)"));
+  EXPECT_TRUE(NavigateToURL(shell(), second_url));
+
+  // At this point, |rfh| should still be live and pending deletion.
+  EXPECT_FALSE(rfh_observer.deleted());
+  EXPECT_FALSE(rfh->is_active());
+  EXPECT_TRUE(rfh->IsRenderFrameLive());
+
+  // Meanwhile, the new page should have two subframes.
+  EXPECT_EQ(2U, root->child_count());
+
+  // Kill the pending delete RFH's process.
+  RenderProcessHostWatcher crash_observer(
+      rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+  rfh->GetProcess()->Shutdown(0);
+  crash_observer.Wait();
+
+  // The process kill should simulate a swapout ACK and trigger destruction of
+  // the pending delete RFH.
+  rfh_observer.WaitUntilDeleted();
+
+  // Ensure that the process kill didn't incorrectly remove subframes from the
+  // new page.
+  ASSERT_EQ(2U, root->child_count());
+  EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+  EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive());
+}
+
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 034a34e0..cc518bf9 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -142,7 +142,7 @@
 }
 
 void IndexedDBDispatcherHost::AddBinding(
-    ::indexed_db::mojom::FactoryAssociatedRequest request) {
+    ::indexed_db::mojom::FactoryRequest request) {
   bindings_.AddBinding(this, std::move(request));
 }
 
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index dc17704..df583047bc 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -49,7 +49,7 @@
       scoped_refptr<IndexedDBContextImpl> indexed_db_context,
       scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
 
-  void AddBinding(::indexed_db::mojom::FactoryAssociatedRequest request);
+  void AddBinding(::indexed_db::mojom::FactoryRequest request);
 
   void AddDatabaseBinding(
       std::unique_ptr<::indexed_db::mojom::Database> database,
@@ -117,7 +117,7 @@
   // Used to set file permissions for blob storage.
   const int ipc_process_id_;
 
-  mojo::AssociatedBindingSet<::indexed_db::mojom::Factory> bindings_;
+  mojo::BindingSet<::indexed_db::mojom::Factory> bindings_;
 
   mojo::StrongAssociatedBindingSet<::indexed_db::mojom::Database>
       database_bindings_;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index ff71819..1ad304b72 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -43,8 +43,7 @@
 using indexed_db::mojom::DatabaseCallbacks;
 using indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
 using indexed_db::mojom::Factory;
-using indexed_db::mojom::FactoryAssociatedPtr;
-using indexed_db::mojom::FactoryAssociatedRequest;
+using indexed_db::mojom::FactoryPtr;
 using indexed_db::mojom::KeyPath;
 using indexed_db::mojom::Value;
 using indexed_db::mojom::ValuePtr;
@@ -184,9 +183,7 @@
   }
 
   void SetUp() override {
-    FactoryAssociatedRequest request =
-        ::mojo::MakeRequestAssociatedWithDedicatedPipe(&idb_mojo_factory_);
-    host_->AddBinding(std::move(request));
+    host_->AddBinding(::mojo::MakeRequest(&idb_mojo_factory_));
   }
 
  protected:
@@ -199,7 +196,7 @@
   scoped_refptr<IndexedDBContextImpl> context_impl_;
   std::unique_ptr<IndexedDBDispatcherHost, BrowserThread::DeleteOnIOThread>
       host_;
-  FactoryAssociatedPtr idb_mojo_factory_;
+  FactoryPtr idb_mojo_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherHostTest);
 };
diff --git a/content/browser/notifications/notification_database.cc b/content/browser/notifications/notification_database.cc
index 28ff2f4..afc494d 100644
--- a/content/browser/notifications/notification_database.cc
+++ b/content/browser/notifications/notification_database.cc
@@ -107,8 +107,9 @@
 
 }  // namespace
 
-NotificationDatabase::NotificationDatabase(const base::FilePath& path)
-    : path_(path) {}
+NotificationDatabase::NotificationDatabase(const base::FilePath& path,
+                                           UkmCallback callback)
+    : path_(path), record_notification_to_ukm_callback_(std::move(callback)) {}
 
 NotificationDatabase::~NotificationDatabase() {
   DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -182,11 +183,13 @@
   // Update the appropriate fields for UKM logging purposes.
   switch (interaction) {
     case PlatformNotificationContext::Interaction::CLOSED:
+      notification_database_data->closed_reason =
+          NotificationDatabaseData::ClosedReason::USER;
       notification_database_data->time_until_close_millis =
           base::Time::Now() - notification_database_data->creation_time_millis;
       break;
     case PlatformNotificationContext::Interaction::NONE:
-      return status;
+      break;
     case PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED:
       notification_database_data->num_action_button_clicks += 1;
       UpdateNotificationClickTimestamps(notification_database_data);
@@ -262,6 +265,13 @@
   DCHECK(!notification_id.empty());
   DCHECK(origin.is_valid());
 
+  NotificationDatabaseData data;
+  Status status = ReadNotificationData(notification_id, origin, &data);
+  if (status == STATUS_OK && record_notification_to_ukm_callback_) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(record_notification_to_ukm_callback_, data));
+  }
   std::string key = CreateDataKey(origin, notification_id);
   return LevelDBStatusToNotificationDatabaseStatus(
       db_->Delete(leveldb::WriteOptions(), key));
@@ -381,6 +391,13 @@
       continue;
     }
 
+    if (record_notification_to_ukm_callback_) {
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE,
+          base::BindOnce(record_notification_to_ukm_callback_,
+                         notification_database_data));
+    }
+
     batch.Delete(iter->key());
 
     DCHECK(!notification_database_data.notification_id.empty());
diff --git a/content/browser/notifications/notification_database.h b/content/browser/notifications/notification_database.h
index 5237a8e3..6ed4658 100644
--- a/content/browser/notifications/notification_database.h
+++ b/content/browser/notifications/notification_database.h
@@ -14,8 +14,8 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/sequence_checker.h"
-#include "content/browser/notifications/platform_notification_context_impl.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/platform_notification_context.h"
 
 class GURL;
 
@@ -23,7 +23,7 @@
 class DB;
 class Env;
 class FilterPolicy;
-}
+}  // namespace leveldb
 
 namespace content {
 
@@ -40,6 +40,9 @@
 // file I/O. The same thread or task runner must be used for all method calls.
 class CONTENT_EXPORT NotificationDatabase {
  public:
+  using UkmCallback =
+      base::RepeatingCallback<void(const NotificationDatabaseData&)>;
+
   // Result status codes for interations with the database. Will be used for
   // UMA, so the assigned ids must remain stable.
   enum Status {
@@ -69,7 +72,8 @@
     STATUS_COUNT = 7
   };
 
-  explicit NotificationDatabase(const base::FilePath& path);
+  NotificationDatabase(const base::FilePath& path, UkmCallback callback);
+
   ~NotificationDatabase();
 
   // Opens the database. If |path| is non-empty, it will be created on the given
@@ -212,6 +216,9 @@
 
   base::SequenceChecker sequence_checker_;
 
+  // Callback to use for recording UKM metrics. Must be posted to the UI thread.
+  UkmCallback record_notification_to_ukm_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(NotificationDatabase);
 };
 
diff --git a/content/browser/notifications/notification_database_unittest.cc b/content/browser/notifications/notification_database_unittest.cc
index f6fdef1..fb0d6cb 100644
--- a/content/browser/notifications/notification_database_unittest.cc
+++ b/content/browser/notifications/notification_database_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/notification_database_data.h"
 #include "content/public/common/platform_notification_data.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
@@ -39,15 +40,19 @@
     {"https://chrome.com", "foo" /* tag */, 0}};
 
 class NotificationDatabaseTest : public ::testing::Test {
+ public:
+  NotificationDatabaseTest()
+      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
  protected:
   // Creates a new NotificationDatabase instance in memory.
   NotificationDatabase* CreateDatabaseInMemory() {
-    return new NotificationDatabase(base::FilePath());
+    return new NotificationDatabase(base::FilePath(), callback());
   }
 
   // Creates a new NotificationDatabase instance in |path|.
   NotificationDatabase* CreateDatabaseOnFileSystem(const base::FilePath& path) {
-    return new NotificationDatabase(path);
+    return new NotificationDatabase(path, callback());
   }
 
   // Creates a new notification for |service_worker_registration_id| belonging
@@ -108,6 +113,12 @@
 
   // Generates a random notification ID. The format of the ID is opaque.
   std::string GenerateNotificationId() { return base::GenerateGUID(); }
+
+  NotificationDatabase::UkmCallback callback() { return callback_; }
+
+  TestBrowserThreadBundle thread_bundle_;  // Must be first member.
+
+  NotificationDatabase::UkmCallback callback_;
 };
 
 TEST_F(NotificationDatabaseTest, OpenCloseMemory) {
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc
index 627e8db..a5c56da 100644
--- a/content/browser/notifications/platform_notification_context_impl.cc
+++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -66,6 +66,10 @@
       browser_context_,
       base::Bind(&PlatformNotificationContextImpl::DidGetNotificationsOnUI,
                  this));
+
+  ukm_callback_ = base::BindRepeating(
+      &PlatformNotificationService::RecordNotificationUkmEvent,
+      base::Unretained(service), browser_context_);
 }
 
 void PlatformNotificationContextImpl::DidGetNotificationsOnUI(
@@ -490,7 +494,7 @@
     return;
   }
 
-  database_.reset(new NotificationDatabase(GetDatabasePath()));
+  database_.reset(new NotificationDatabase(GetDatabasePath(), ukm_callback_));
   NotificationDatabase::Status status =
       database_->Open(true /* create_if_missing */);
 
@@ -502,7 +506,7 @@
     prune_database_on_open_ = false;
     DestroyDatabase();
 
-    database_.reset(new NotificationDatabase(GetDatabasePath()));
+    database_.reset(new NotificationDatabase(GetDatabasePath(), ukm_callback_));
     status = database_->Open(true /* create_if_missing */);
 
     // TODO(peter): Find the appropriate UMA to cover in regards to
@@ -513,7 +517,8 @@
   // away the contents of the directory and try re-opening the database.
   if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) {
     if (DestroyDatabase()) {
-      database_.reset(new NotificationDatabase(GetDatabasePath()));
+      database_.reset(
+          new NotificationDatabase(GetDatabasePath(), ukm_callback_));
       status = database_->Open(true /* create_if_missing */);
 
       UMA_HISTOGRAM_ENUMERATION(
diff --git a/content/browser/notifications/platform_notification_context_impl.h b/content/browser/notifications/platform_notification_context_impl.h
index 7ea92b6..4ad41a15 100644
--- a/content/browser/notifications/platform_notification_context_impl.h
+++ b/content/browser/notifications/platform_notification_context_impl.h
@@ -16,6 +16,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "content/browser/notifications/notification_database.h"
 #include "content/browser/notifications/notification_id_generator.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/common/content_export.h"
@@ -37,7 +38,6 @@
 
 class BlinkNotificationServiceImpl;
 class BrowserContext;
-class NotificationDatabase;
 struct NotificationDatabaseData;
 class ServiceWorkerContextWrapper;
 
@@ -212,6 +212,8 @@
   // removed when either this class is destroyed or the Mojo pipe disconnects.
   std::vector<std::unique_ptr<BlinkNotificationServiceImpl>> services_;
 
+  NotificationDatabase::UkmCallback ukm_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(PlatformNotificationContextImpl);
 };
 
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc
index c8c5e3b..16e30e8 100644
--- a/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -52,7 +52,9 @@
       DCHECK(!suppress_manipulation_events_);
       DCHECK(!touchscreen_scroll_in_progress_);
       touchscreen_scroll_in_progress_ = true;
-      DCHECK(scrolling_touch_action_.has_value());
+      // TODO(https://crbug.com/851644): Make sure the value is properly set.
+      if (!scrolling_touch_action_.has_value())
+        SetTouchAction(cc::kTouchActionAuto);
       suppress_manipulation_events_ =
           ShouldSuppressManipulation(*gesture_event);
       return suppress_manipulation_events_
@@ -116,6 +118,9 @@
     // If double tap is disabled, there's no reason for the tap delay.
     case WebInputEvent::kGestureTapUnconfirmed: {
       DCHECK_EQ(1, gesture_event->data.tap.tap_count);
+      // TODO(https://crbug.com/851644): Make sure the value is properly set.
+      if (!scrolling_touch_action_.has_value())
+        SetTouchAction(cc::kTouchActionAuto);
       allow_current_double_tap_event_ = (scrolling_touch_action_.value() &
                                          cc::kTouchActionDoubleTapZoom) != 0;
       if (!allow_current_double_tap_event_) {
@@ -139,6 +144,11 @@
       if (gesture_event->is_source_touch_event_set_non_blocking)
         SetTouchAction(cc::kTouchActionAuto);
       scrolling_touch_action_ = allowed_touch_action_;
+      // TODO(https://crbug.com/851644): The value may not set in the case when
+      // the gesture event is flushed due to touch ack time out after the finger
+      // is lifted up. Make sure the value is properly set.
+      if (!scrolling_touch_action_.has_value())
+        SetTouchAction(cc::kTouchActionAuto);
       DCHECK(!drop_current_tap_ending_event_);
       break;
 
diff --git a/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/content/browser/renderer_host/input/touch_action_filter_unittest.cc
index 69dc42a..9a5d4a8 100644
--- a/content/browser/renderer_host/input/touch_action_filter_unittest.cc
+++ b/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -888,8 +888,8 @@
 
   EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
             FilterGestureEventResult::kFilterGestureEventAllowed);
-  EXPECT_FALSE(filter_.allowed_touch_action().has_value());
-  EXPECT_FALSE(ScrollingTouchAction().has_value());
+  EXPECT_TRUE(filter_.allowed_touch_action().has_value());
+  EXPECT_TRUE(ScrollingTouchAction().has_value());
 }
 
 TEST_F(TouchActionFilterTest, TouchpadScroll) {
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 60ece39..5dcfede 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1911,10 +1911,6 @@
 void RenderProcessHostImpl::RegisterMojoInterfaces() {
   auto registry = std::make_unique<service_manager::BinderRegistry>();
 
-  channel_->AddAssociatedInterfaceForIOThread(
-      base::Bind(&IndexedDBDispatcherHost::AddBinding,
-                 base::Unretained(indexed_db_factory_.get())));
-
   channel_->AddAssociatedInterfaceForIOThread(base::BindRepeating(
       &ServiceWorkerDispatcherHost::AddBinding,
       base::Unretained(service_worker_dispatcher_host_.get())));
@@ -1996,6 +1992,10 @@
   }
 
   registry->AddInterface(
+      base::BindRepeating(&IndexedDBDispatcherHost::AddBinding,
+                          base::Unretained(indexed_db_factory_.get())));
+
+  registry->AddInterface(
       base::Bind(
           &WebDatabaseHostImpl::Create, GetID(),
           base::WrapRefCounted(storage_partition_impl_->GetDatabaseTracker())),
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 2522542..8317c806 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -1188,11 +1188,6 @@
       map_size_key,
       base::StringPrintf("%u", static_cast<int>(owner_map_.size())));
 
-  if (events_being_flushed_) {
-    touchscreen_gesture_target_.target->host()
-        ->input_router()
-        ->ForceSetTouchActionAuto();
-  }
   touchscreen_gesture_target_.target->ProcessGestureEvent(event, latency);
 }
 
@@ -1325,11 +1320,6 @@
   return RenderWidgetTargetResult();
 }
 
-void RenderWidgetHostInputEventRouter::SetEventsBeingFlushed(
-        bool events_being_flushed) {
-  events_being_flushed_ = events_being_flushed;
-}
-
 void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
     RenderWidgetHostViewBase* root_view,
     RenderWidgetHostViewBase* target,
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 7417c3a..6bdfce2f 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -272,9 +272,6 @@
       const blink::WebInputEvent& event,
       const ui::LatencyInfo& latency,
       const base::Optional<gfx::PointF>& target_location) override;
-  // Notify whether the events in the queue are being flushed due to touch ack
-  // timeout, or the flushing has completed.
-  void SetEventsBeingFlushed(bool events_being_flushed) override;
 
   FrameSinkIdOwnerMap owner_map_;
   TargetMap touchscreen_gesture_target_map_;
@@ -311,7 +308,6 @@
 
   std::unique_ptr<RenderWidgetTargeter> event_targeter_;
   bool use_viz_hit_test_ = false;
-  bool events_being_flushed_ = false;
 
   std::unique_ptr<TouchEmulator> touch_emulator_;
 
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index 1239e5d..4a5acc5 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -215,7 +215,6 @@
 }
 
 void RenderWidgetTargeter::FlushEventQueue() {
-  bool events_being_flushed = false;
   while (!request_in_flight_ && !requests_.empty()) {
     auto request = std::move(requests_.front());
     requests_.pop();
@@ -225,16 +224,9 @@
       continue;
     }
     request.tracker->Stop();
-    // Only notify the delegate once that the current event queue is being
-    // flushed. Once all the events are flushed, notify the delegate again.
-    if (!events_being_flushed) {
-      delegate_->SetEventsBeingFlushed(true);
-      events_being_flushed = true;
-    }
     FindTargetAndDispatch(request.root_view.get(), *request.event,
                           request.latency);
   }
-  delegate_->SetEventsBeingFlushed(false);
 }
 
 void RenderWidgetTargeter::FoundFrameSinkId(
diff --git a/content/browser/renderer_host/render_widget_targeter.h b/content/browser/renderer_host/render_widget_targeter.h
index 6399b2ad..e9b3e2a 100644
--- a/content/browser/renderer_host/render_widget_targeter.h
+++ b/content/browser/renderer_host/render_widget_targeter.h
@@ -70,8 +70,6 @@
         const ui::LatencyInfo& latency,
         const base::Optional<gfx::PointF>& target_location) = 0;
 
-    virtual void SetEventsBeingFlushed(bool events_being_flushed) = 0;
-
     virtual RenderWidgetHostViewBase* FindViewFromFrameSinkId(
         const viz::FrameSinkId& frame_sink_id) const = 0;
   };
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 922b5e0..81e71d6 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -15,7 +15,6 @@
 #include "build/build_config.h"
 #include "components/viz/common/features.h"
 #include "content/browser/renderer_host/cursor_manager.h"
-#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
 #include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
 #include "content/browser/renderer_host/input/touch_emulator.h"
 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -1309,92 +1308,6 @@
   RunTest(TouchActionBubbling);
 }
 
-#if defined(OS_ANDROID) || defined(USE_AURA)
-namespace {
-// This function is used in TouchActionAckTimeout and 
-// SubframeGestureEventRouting, which is defined either under Android or Aura.
-void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
-                                 SyntheticGesture::Result result) {
-  EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
-  runner->Quit();
-}
-
-}  // namespace
-#endif
-
-// Regression test for https://crbug.com/851644. The test passes as long as it
-// doesn't crash.
-// Touch action ack timeout is enabled on Android only.
-#if defined(OS_ANDROID)
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
-                       TouchActionAckTimeout) {
-  GURL main_url(
-      embedded_test_server()->GetURL("/frame_tree/page_with_janky_frame.html"));
-  ASSERT_TRUE(NavigateToURL(shell(), main_url));
-  FrameTreeNode* root = web_contents()->GetFrameTree()->root();
-  ASSERT_EQ(1U, root->child_count());
-  GURL frame_url(embedded_test_server()->GetURL(
-      "baz.com", "/page_with_touch_start_janking_main_thread.html"));
-  auto* child_frame_host = root->child_at(0)->current_frame_host();
-
-  RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
-      root->current_frame_host()->GetRenderWidgetHost()->GetView());
-  RenderWidgetHostViewChildFrame* rwhv_child =
-      static_cast<RenderWidgetHostViewChildFrame*>(
-          child_frame_host->GetRenderWidgetHost()->GetView());
-
-  WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
-
-  // Compute the point so that the gesture event can target the child frame.
-  const gfx::Rect root_bounds = rwhv_root->GetViewBounds();
-  const gfx::Rect child_bounds = rwhv_child->GetViewBounds();
-  RenderFrameSubmissionObserver render_frame_submission_observer(
-      shell()->web_contents());
-  const float page_scale_factor =
-      render_frame_submission_observer.LastRenderFrameMetadata()
-          .page_scale_factor;
-  const gfx::PointF point_in_child(
-      (child_bounds.x() - root_bounds.x() + 25) * page_scale_factor,
-      (child_bounds.y() - root_bounds.y() + 25) * page_scale_factor);
-
-  SyntheticSmoothScrollGestureParams params;
-  params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
-  params.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
-  params.distances.push_back(gfx::Vector2dF(0, -10));
-  // Make this scroll slow so that the second scroll will be queued even before
-  // this one ends.
-  params.speed_in_pixels_s = 1000;
-  std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
-      new SyntheticSmoothScrollGesture(params));
-
-  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
-  RenderWidgetHostImpl* render_widget_host =
-      root->current_frame_host()->GetRenderWidgetHost();
-  render_widget_host->QueueSyntheticGesture(
-      std::move(gesture), base::BindOnce(OnSyntheticGestureCompleted, runner));
-
-  SyntheticSmoothScrollGestureParams params2;
-  params2.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
-  params2.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
-  params2.distances.push_back(gfx::Vector2dF(0, -10));
-  params2.speed_in_pixels_s = 100000;
-  std::unique_ptr<SyntheticSmoothScrollGesture> gesture2(
-      new SyntheticSmoothScrollGesture(params2));
-  render_widget_host->QueueSyntheticGesture(
-      std::move(gesture2), base::BindOnce(OnSyntheticGestureCompleted, runner));
-
-  runner->Run();
-  runner = nullptr;
-
-  // Give enough time to make sure all gesture are flushed and handled.
-  base::RunLoop run_loop;
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, run_loop.QuitClosure(),
-      base::TimeDelta::FromMilliseconds(2500));
-  run_loop.Run();
-}
-#endif  // defined(OS_ANDROID)
-
 #if defined(USE_AURA) || defined(OS_ANDROID)
 
 // When unconsumed scrolls in a child bubble to the root and start an
@@ -3115,6 +3028,17 @@
             render_widget_host->input_router()->AllowedTouchAction());
 }
 
+namespace {
+
+// Declared here to be close to the SubframeGestureEventRouting test.
+void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
+                                 SyntheticGesture::Result result) {
+  EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+  runner->Quit();
+}
+
+}  // anonymous namespace
+
 // https://crbug.com/592320
 IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
                        DISABLED_SubframeGestureEventRouting) {
diff --git a/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h b/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h
deleted file mode 100644
index 0603a9b..0000000
--- a/content/browser/web_contents/web_contents_view_overscroll_animator_mac.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-namespace content {
-class WebContentsImpl;
-
-// The direction of the overscroll animations. Backwards means that the user
-// wants to navigate backwards in the navigation history. The opposite applies
-// to forwards.
-enum OverscrollAnimatorDirection {
-  OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS,
-  OVERSCROLL_ANIMATOR_DIRECTION_FORWARDS,
-};
-}  // namespace content
-
-// NSViews that intend to manage the animation associated with an overscroll
-// must implement this protocol.
-@protocol WebContentsOverscrollAnimator
-// Some implementations require the WebContentsView to supply a snapshot of a
-// previous navigation state. This method determines whether the snapshot passed
-// to the overscroll animator is expected to be non-nil.
-- (BOOL)needsNavigationSnapshot;
-
-// Begin an overscroll animation. The method -needsNavigationSnapshot determines
-// whether |snapshot| can be nil.
-- (void)beginOverscrollInDirection:
-            (content::OverscrollAnimatorDirection)direction
-                navigationSnapshot:(NSImage*)snapshot;
-
-// Due to the nature of some of the overscroll animations, implementators of
-// this protocol must have control over the layout of the RenderWidgetHost's
-// NativeView. When there is no overscroll animation in progress, the
-// implementor must guarantee that the frame of the RenderWidgetHost's
-// NativeView in screen coordinates is the same as its own frame in screen
-// coordinates.
-// Due to the odd ownership cycles of the RenderWidgetHost's NativeView, it is
-// important that its presence in the NSView hierarchy is the only strong
-// reference, and that when it gets removed from the NSView hierarchy, it will
-// be dealloc'ed shortly thereafter.
-- (void)addRenderWidgetHostNativeView:(NSView*)view;
-
-// During an overscroll animation, |progress| ranges from 0 to 2, and indicates
-// how close the overscroll is to completing. If the overscroll ends with
-// |progress| >= 1, then the overscroll is considered completed.
-- (void)updateOverscrollProgress:(CGFloat)progress;
-
-// Animate the finish of the overscroll and perform a navigation. The navigation
-// may not happen synchronously, but is guaranteed to eventually occur.
-- (void)completeOverscroll:(content::WebContentsImpl*)webContents;
-
-// Animate the cancellation of the overscroll.
-- (void)cancelOverscroll;
-@end
-
-#endif  // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_MAC_H_
diff --git a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h b/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h
deleted file mode 100644
index 326c868..0000000
--- a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#include "content/browser/web_contents/web_contents_view_overscroll_animator_mac.h"
-
-namespace overscroll_animator {
-class WebContentsPaintObserver;
-}  // namespace overscroll_animator
-
-@interface OverscrollAnimatorSliderView
-    : NSView<WebContentsOverscrollAnimator> {
-  // This container view holds the RenderWidgetHost's NativeViews. Most of the
-  // time, its frame in screen coordinates is the same as SliderView's frame in
-  // screen coordinates. During an overscroll animation, it may temporarily be
-  // relocated, but it will return to its original position after the overscroll
-  // animation is finished.
-  base::scoped_nsobject<NSView> middleView_;
-
-  // This view is a sibling of middleView_, and is guaranteed to live below it.
-  // Most of the time, it is hidden. During a backwards overscroll animation,
-  // middleView_ is slid to the right, and bottomView_ peeks out from the
-  // original position of middleView_.
-  base::scoped_nsobject<NSImageView> bottomView_;
-
-  // This view is a sibling of middleView_, and is guaranteed to live above it.
-  // Most of the time, it is hidden. During a forwards overscroll animation,
-  // topView_ is slid to the left from off screen, its final position exactly
-  // covering middleView_.
-  base::scoped_nsobject<NSImageView> topView_;
-
-  // The direction of the current overscroll animation. This property has no
-  // meaning when inOverscroll_ is false.
-  content::OverscrollAnimatorDirection direction_;
-
-  // Indicates that this view is completing or cancelling the overscroll. This
-  // animation cannot be cancelled.
-  BOOL animating_;
-
-  // Reflects whether this view is in the process of handling an overscroll.
-  BOOL inOverscroll_;
-
-  // The most recent value passed to -updateOverscrollProgress:.
-  CGFloat progress_;
-
-  // An observer that reports the first non-empty paint of a WebContents. This
-  // is used when completing an overscroll animation.
-  std::unique_ptr<overscroll_animator::WebContentsPaintObserver> observer_;
-}
-@end
-
-#endif  // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_VIEW_OVERSCROLL_ANIMATOR_SLIDER_MAC_H_
diff --git a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm b/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
deleted file mode 100644
index b614fb1..0000000
--- a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <QuartzCore/QuartzCore.h>
-
-#include "content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.h"
-
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace {
-// The minimum possible progress of an overscroll animation.
-CGFloat kMinProgress = 0;
-// The maximum possible progress of an overscroll animation.
-CGFloat kMaxProgress = 2.0;
-// The maximum duration of the completion or cancellation animations. The
-// effective maximum is half of this value, since the longest animation is from
-// progress = 1.0 to progress = 2.0;
-CGFloat kMaxAnimationDuration = 0.2;
-}  // namespace
-
-// OverscrollAnimatorSliderView Private Category -------------------------------
-
-@interface OverscrollAnimatorSliderView ()
-// Callback from WebContentsPaintObserver.
-- (void)webContentsFinishedNonEmptyPaint;
-
-// Resets overscroll animation state.
-- (void)reset;
-
-// Given a |progress| from 0 to 2, the expected frame origin of the -movingView.
-- (NSPoint)frameOriginWithProgress:(CGFloat)progress;
-
-// The NSView that is moving during the overscroll animation.
-- (NSView*)movingView;
-
-// The expected duration of an animation from progress_ to |progress|
-- (CGFloat)animationDurationForProgress:(CGFloat)progress;
-
-// NSView override. During an overscroll animation, the cursor may no longer
-// rest on the RenderWidgetHost's NativeView, which prevents wheel events from
-// reaching the NativeView. The overscroll animation is driven by wheel events
-// so they must be explicitly forwarded to the NativeView.
-- (void)scrollWheel:(NSEvent*)event;
-@end
-
-// Helper Class (ResizingView) -------------------------------------------------
-
-// This NSView subclass is intended to be the RenderWidgetHost's NativeView's
-// parent NSView. It is possible for the RenderWidgetHost's NativeView's size to
-// become out of sync with its parent NSView. The override of
-// -resizeSubviewsWithOldSize: ensures that the sizes will eventually become
-// consistent.
-// http://crbug.com/264207
-@interface ResizingView : NSView
-@end
-
-@implementation ResizingView
-- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
-  for (NSView* subview in self.subviews)
-    [subview setFrame:self.bounds];
-}
-@end
-
-// Helper Class (WebContentsPaintObserver) -------------------------------------
-
-namespace overscroll_animator {
-class WebContentsPaintObserver : public content::WebContentsObserver {
- public:
-  WebContentsPaintObserver(content::WebContents* web_contents,
-                           OverscrollAnimatorSliderView* slider_view)
-      : WebContentsObserver(web_contents), slider_view_(slider_view) {}
-
-  void DidFirstVisuallyNonEmptyPaint() override {
-    [slider_view_ webContentsFinishedNonEmptyPaint];
-  }
-
- private:
-  OverscrollAnimatorSliderView* slider_view_;  // Weak reference.
-};
-}  // namespace overscroll_animator
-
-// OverscrollAnimatorSliderView Implementation ---------------------------------
-
-@implementation OverscrollAnimatorSliderView
-
-- (instancetype)initWithFrame:(NSRect)frame {
-  self = [super initWithFrame:frame];
-  if (self) {
-    bottomView_.reset([[NSImageView alloc] initWithFrame:self.bounds]);
-    bottomView_.get().imageScaling = NSImageScaleNone;
-    bottomView_.get().autoresizingMask =
-        NSViewWidthSizable | NSViewHeightSizable;
-    bottomView_.get().imageAlignment = NSImageAlignTop;
-    [self addSubview:bottomView_];
-    middleView_.reset([[ResizingView alloc] initWithFrame:self.bounds]);
-    middleView_.get().autoresizingMask =
-        NSViewWidthSizable | NSViewHeightSizable;
-    [self addSubview:middleView_];
-    topView_.reset([[NSImageView alloc] initWithFrame:self.bounds]);
-    topView_.get().autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
-    topView_.get().imageScaling = NSImageScaleNone;
-    topView_.get().imageAlignment = NSImageAlignTop;
-    [self addSubview:topView_];
-
-    [self reset];
-  }
-  return self;
-}
-
-- (void)webContentsFinishedNonEmptyPaint {
-  observer_.reset();
-  [self reset];
-}
-
-- (void)reset {
-  DCHECK(!animating_);
-  inOverscroll_ = NO;
-  progress_ = kMinProgress;
-
-  [CATransaction begin];
-  [CATransaction setDisableActions:YES];
-  bottomView_.get().hidden = YES;
-  middleView_.get().hidden = NO;
-  topView_.get().hidden = YES;
-
-  [bottomView_ setFrameOrigin:NSMakePoint(0, 0)];
-  [middleView_ setFrameOrigin:NSMakePoint(0, 0)];
-  [topView_ setFrameOrigin:NSMakePoint(0, 0)];
-  [CATransaction commit];
-}
-
-- (NSPoint)frameOriginWithProgress:(CGFloat)progress {
-  if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
-    return NSMakePoint(progress / kMaxProgress * self.bounds.size.width, 0);
-  return NSMakePoint((1 - progress / kMaxProgress) * self.bounds.size.width, 0);
-}
-
-- (NSView*)movingView {
-  if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
-    return middleView_;
-  return topView_;
-}
-
-- (CGFloat)animationDurationForProgress:(CGFloat)progress {
-  CGFloat progressPercentage =
-      fabs(progress_ - progress) / (kMaxProgress - kMinProgress);
-  return progressPercentage * kMaxAnimationDuration;
-}
-
-- (void)scrollWheel:(NSEvent*)event {
-  NSView* latestRenderWidgetHostView = [[middleView_ subviews] lastObject];
-  [latestRenderWidgetHostView scrollWheel:event];
-}
-
-// WebContentsOverscrollAnimator Implementation --------------------------------
-
-- (BOOL)needsNavigationSnapshot {
-  return YES;
-}
-
-- (void)beginOverscrollInDirection:
-            (content::OverscrollAnimatorDirection)direction
-                navigationSnapshot:(NSImage*)snapshot {
-  // TODO(erikchen): If snapshot is nil, need a placeholder.
-  if (animating_ || inOverscroll_)
-    return;
-
-  inOverscroll_ = YES;
-  direction_ = direction;
-  if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS) {
-    // The middleView_ will slide to the right, revealing bottomView_.
-    bottomView_.get().hidden = NO;
-    [bottomView_ setImage:snapshot];
-  } else {
-    // The topView_ will slide in from the right, concealing middleView_.
-    topView_.get().hidden = NO;
-    [topView_ setFrameOrigin:NSMakePoint(self.bounds.size.width, 0)];
-    [topView_ setImage:snapshot];
-  }
-
-  [self updateOverscrollProgress:kMinProgress];
-}
-
-- (void)addRenderWidgetHostNativeView:(NSView*)view {
-  [middleView_ addSubview:view];
-}
-
-- (void)updateOverscrollProgress:(CGFloat)progress {
-  if (animating_)
-    return;
-  DCHECK_LE(progress, kMaxProgress);
-  DCHECK_GE(progress, kMinProgress);
-  progress_ = progress;
-  [[self movingView] setFrameOrigin:[self frameOriginWithProgress:progress]];
-}
-
-- (void)completeOverscroll:(content::WebContentsImpl*)webContents {
-  if (animating_ || !inOverscroll_)
-    return;
-
-  animating_ = YES;
-
-  NSView* view = [self movingView];
-  [NSAnimationContext beginGrouping];
-  [NSAnimationContext currentContext].duration =
-      [self animationDurationForProgress:kMaxProgress];
-  [[NSAnimationContext currentContext] setCompletionHandler:^{
-      animating_ = NO;
-
-      // Animation is complete. Now perform page load.
-      if (direction_ == content::OVERSCROLL_ANIMATOR_DIRECTION_BACKWARDS)
-        webContents->GetController().GoBack();
-      else
-        webContents->GetController().GoForward();
-
-      // Reset the position of the middleView_, but wait for the page to paint
-      // before showing it.
-      middleView_.get().hidden = YES;
-      [middleView_ setFrameOrigin:NSMakePoint(0, 0)];
-      observer_.reset(
-          new overscroll_animator::WebContentsPaintObserver(webContents, self));
-  }];
-
-  // Animate the moving view to its final position.
-  [[view animator] setFrameOrigin:[self frameOriginWithProgress:kMaxProgress]];
-
-  [NSAnimationContext endGrouping];
-}
-
-- (void)cancelOverscroll {
-  if (animating_)
-    return;
-
-  if (!inOverscroll_) {
-    [self reset];
-    return;
-  }
-
-  animating_ = YES;
-
-  NSView* view = [self movingView];
-  [NSAnimationContext beginGrouping];
-  [NSAnimationContext currentContext].duration =
-      [self animationDurationForProgress:kMinProgress];
-  [[NSAnimationContext currentContext] setCompletionHandler:^{
-      // Animation is complete. Reset the state.
-      animating_ = NO;
-      [self reset];
-  }];
-
-  // Animate the moving view to its initial position.
-  [[view animator] setFrameOrigin:[self frameOriginWithProgress:kMinProgress]];
-
-  [NSAnimationContext endGrouping];
-}
-
-@end
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 96f8e82..62ef1d7 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -61,6 +61,7 @@
           "device.mojom.BatteryMonitor",
           "device.mojom.GamepadHapticsManager",
           "discardable_memory.mojom.DiscardableSharedMemoryManager",
+          "indexed_db.mojom.Factory",
           "media.mojom.KeySystemSupport",
           "media.mojom.VideoCaptureHost",
           "media.mojom.VideoDecodePerfHistory",
diff --git a/content/public/browser/platform_notification_service.h b/content/public/browser/platform_notification_service.h
index 228fc3024..0e9ce43 100644
--- a/content/public/browser/platform_notification_service.h
+++ b/content/public/browser/platform_notification_service.h
@@ -14,6 +14,7 @@
 
 #include "base/callback_forward.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/notification_database_data.h"
 #include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
 
 class GURL;
@@ -75,6 +76,11 @@
   // increments the value, as it is called once per notification write.
   virtual int64_t ReadNextPersistentNotificationId(
       BrowserContext* browser_context) = 0;
+
+  // Records a given notification to UKM.
+  virtual void RecordNotificationUkmEvent(
+      BrowserContext* browser_context,
+      const NotificationDatabaseData& data) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index f7bef58c..e4f7d81 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -58,6 +58,11 @@
 #if defined(OS_ANDROID)
 const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
 #endif
+#if defined(OS_WIN)
+const char kChromeUIBrowserHeapCorruptionURL[] =
+    "chrome://inducebrowserheapcorruption/";
+const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
+#endif
 #if defined(ADDRESS_SANITIZER)
 const char kChromeUICrashHeapOverflowURL[] = "chrome://crash/heap-overflow";
 const char kChromeUICrashHeapUnderflowURL[] = "chrome://crash/heap-underflow";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 0da500f..d134378 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -69,6 +69,10 @@
 #if defined(OS_ANDROID)
 CONTENT_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
 #endif
+#if defined(OS_WIN)
+CONTENT_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
+CONTENT_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
+#endif
 #if defined(ADDRESS_SANITIZER)
 CONTENT_EXPORT extern const char kChromeUICrashHeapOverflowURL[];
 CONTENT_EXPORT extern const char kChromeUICrashHeapUnderflowURL[];
diff --git a/content/public/common/url_utils.cc b/content/public/common/url_utils.cc
index e14b5d9..5c373cde 100644
--- a/content/public/common/url_utils.cc
+++ b/content/public/common/url_utils.cc
@@ -90,6 +90,11 @@
   }
 #endif
 
+#if defined(OS_WIN)
+  if (url == kChromeUIHeapCorruptionCrashURL)
+    return true;
+#endif
+
 #if DCHECK_IS_ON()
   if (url == kChromeUICrashDcheckURL)
     return true;
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 5d3dcf5..bae792b6 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -92,7 +92,9 @@
     // releasing the internal reference counts and destroying the internal
     // state.
     ViewMsg_Close msg(render_view->GetRoutingID());
-    static_cast<RenderViewImpl*>(render_view)->OnMessageReceived(msg);
+    RenderWidget* render_widget =
+        static_cast<RenderViewImpl*>(render_view)->GetWidget();
+    render_widget->OnMessageReceived(msg);
     return true;
   }
 
@@ -665,7 +667,7 @@
 
 blink::WebWidget* RenderViewTest::GetWebWidget() {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
-  return impl->GetWebWidget();
+  return impl->GetWidget()->GetWebWidget();
 }
 
 ContentClient* RenderViewTest::CreateContentClient() {
diff --git a/content/renderer/indexed_db/webidbfactory_impl.cc b/content/renderer/indexed_db/webidbfactory_impl.cc
index 753c35a..a2b771b 100644
--- a/content/renderer/indexed_db/webidbfactory_impl.cc
+++ b/content/renderer/indexed_db/webidbfactory_impl.cc
@@ -20,21 +20,22 @@
 using blink::WebString;
 using indexed_db::mojom::CallbacksAssociatedPtrInfo;
 using indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
-using indexed_db::mojom::FactoryAssociatedPtr;
+using indexed_db::mojom::FactoryPtr;
+using indexed_db::mojom::FactoryPtrInfo;
 
 namespace content {
 
 class WebIDBFactoryImpl::IOThreadHelper {
  public:
-  IOThreadHelper(scoped_refptr<IPC::SyncMessageFilter> sync_message_filter);
+  IOThreadHelper();
   ~IOThreadHelper();
 
-  FactoryAssociatedPtr& GetService();
   CallbacksAssociatedPtrInfo GetCallbacksProxy(
       std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
   DatabaseCallbacksAssociatedPtrInfo GetDatabaseCallbacksProxy(
       std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks);
 
+  void Bind(FactoryPtrInfo factory_info);
   void GetDatabaseNames(std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
                         const url::Origin& origin);
   void Open(const base::string16& name,
@@ -49,17 +50,19 @@
                       bool force_close);
 
  private:
-  scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
-  FactoryAssociatedPtr service_;
+  FactoryPtr factory_;
 
   DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
 };
 
 WebIDBFactoryImpl::WebIDBFactoryImpl(
-    scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
+    FactoryPtrInfo factory_info,
     scoped_refptr<base::SingleThreadTaskRunner> io_runner)
-    : io_helper_(new IOThreadHelper(std::move(sync_message_filter))),
-      io_runner_(std::move(io_runner)) {}
+    : io_helper_(new IOThreadHelper()), io_runner_(std::move(io_runner)) {
+  io_runner_->PostTask(FROM_HERE, base::BindOnce(&IOThreadHelper::Bind,
+                                                 base::Unretained(io_helper_),
+                                                 std::move(factory_info)));
+}
 
 WebIDBFactoryImpl::~WebIDBFactoryImpl() {
   io_runner_->DeleteSoon(FROM_HERE, io_helper_);
@@ -117,16 +120,12 @@
                                 force_close));
 }
 
-WebIDBFactoryImpl::IOThreadHelper::IOThreadHelper(
-    scoped_refptr<IPC::SyncMessageFilter> sync_message_filter)
-    : sync_message_filter_(std::move(sync_message_filter)) {}
+WebIDBFactoryImpl::IOThreadHelper::IOThreadHelper() = default;
 
 WebIDBFactoryImpl::IOThreadHelper::~IOThreadHelper() {}
 
-FactoryAssociatedPtr& WebIDBFactoryImpl::IOThreadHelper::GetService() {
-  if (!service_)
-    sync_message_filter_->GetRemoteAssociatedInterface(&service_);
-  return service_;
+void WebIDBFactoryImpl::IOThreadHelper::Bind(FactoryPtrInfo factory_info) {
+  factory_.Bind(std::move(factory_info));
 }
 
 CallbacksAssociatedPtrInfo WebIDBFactoryImpl::IOThreadHelper::GetCallbacksProxy(
@@ -149,8 +148,7 @@
 void WebIDBFactoryImpl::IOThreadHelper::GetDatabaseNames(
     std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
     const url::Origin& origin) {
-  GetService()->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks)),
-                                 origin);
+  factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks)), origin);
 }
 
 void WebIDBFactoryImpl::IOThreadHelper::Open(
@@ -160,9 +158,9 @@
     std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
     std::unique_ptr<IndexedDBDatabaseCallbacksImpl> database_callbacks,
     const url::Origin& origin) {
-  GetService()->Open(GetCallbacksProxy(std::move(callbacks)),
-                     GetDatabaseCallbacksProxy(std::move(database_callbacks)),
-                     origin, name, version, transaction_id);
+  factory_->Open(GetCallbacksProxy(std::move(callbacks)),
+                 GetDatabaseCallbacksProxy(std::move(database_callbacks)),
+                 origin, name, version, transaction_id);
 }
 
 void WebIDBFactoryImpl::IOThreadHelper::DeleteDatabase(
@@ -170,8 +168,8 @@
     std::unique_ptr<IndexedDBCallbacksImpl> callbacks,
     const url::Origin& origin,
     bool force_close) {
-  GetService()->DeleteDatabase(GetCallbacksProxy(std::move(callbacks)), origin,
-                               name, force_close);
+  factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks)), origin,
+                           name, force_close);
 }
 
 }  // namespace content
diff --git a/content/renderer/indexed_db/webidbfactory_impl.h b/content/renderer/indexed_db/webidbfactory_impl.h
index 5195900..2dfeca44 100644
--- a/content/renderer/indexed_db/webidbfactory_impl.h
+++ b/content/renderer/indexed_db/webidbfactory_impl.h
@@ -17,15 +17,11 @@
 class WebString;
 }
 
-namespace IPC {
-class SyncMessageFilter;
-}
-
 namespace content {
 
 class WebIDBFactoryImpl : public blink::WebIDBFactory {
  public:
-  WebIDBFactoryImpl(scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
+  WebIDBFactoryImpl(indexed_db::mojom::FactoryPtrInfo factory_info,
                     scoped_refptr<base::SingleThreadTaskRunner> io_runner);
   ~WebIDBFactoryImpl() override;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 75ead44..688550b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -239,6 +239,7 @@
 #endif
 
 #if defined(OS_WIN)
+#include "base/debug/invalid_access_win.h"
 #include "base/process/kill.h"
 #elif defined(OS_POSIX)
 #include <signal.h>
@@ -1063,6 +1064,15 @@
     CHECK(false);
   }
 
+#if defined(OS_WIN)
+  if (url == kChromeUIHeapCorruptionCrashURL) {
+    LOG(ERROR)
+        << "Intentionally causing heap corruption because user navigated to "
+        << url.spec();
+    base::debug::win::TerminateWithHeapCorruption();
+  }
+#endif
+
 #if DCHECK_IS_ON()
   if (url == kChromeUICrashDcheckURL) {
     LOG(ERROR) << "Intentionally causing DCHECK because user navigated to "
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 9e33172c..859a433a 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -256,7 +256,9 @@
 
   ViewMsg_WasShown was_shown_message(0, true, base::TimeTicks());
   // Test passes if this does not crash.
-  static_cast<RenderViewImpl*>(view_)->OnMessageReceived(was_shown_message);
+  RenderWidget* render_widget =
+      static_cast<RenderViewImpl*>(view_)->GetWidget();
+  render_widget->OnMessageReceived(was_shown_message);
 }
 
 // Test that LoFi state only updates for new main frame documents. Subframes
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index caa6b4a..3c3c84c 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -2714,7 +2714,8 @@
 }  // namespace
 
 TEST_F(RenderViewImplEnableZoomForDSFTest, AutoResizeWithZoomForDSF) {
-  view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+  view()->GetWidget()->EnableAutoResizeForTesting(gfx::Size(5, 5),
+                                                  gfx::Size(1000, 1000));
   LoadHTML(kAutoResizeTestPage);
   gfx::Size size_at_1x = view()->GetWidget()->size();
   ASSERT_FALSE(size_at_1x.IsEmpty());
@@ -2726,7 +2727,8 @@
 }
 
 TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) {
-  view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+  view()->GetWidget()->EnableAutoResizeForTesting(gfx::Size(5, 5),
+                                                  gfx::Size(1000, 1000));
   LoadHTML(kAutoResizeTestPage);
   gfx::Size size_at_1x = view()->GetWidget()->size();
   ASSERT_FALSE(size_at_1x.IsEmpty());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 03d9cda..c83399d19 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -75,7 +75,6 @@
 #include "content/renderer/drop_data_builder.h"
 #include "content/renderer/gpu/layer_tree_view.h"
 #include "content/renderer/history_serialization.h"
-#include "content/renderer/idle_user_detector.h"
 #include "content/renderer/ime_event_guard.h"
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/loader/request_extra_data.h"
@@ -437,29 +436,7 @@
                    task_runner),
       routing_id_(params.view_id),
       webkit_preferences_(params.web_preferences),
-      send_content_state_immediately_(false),
-      send_preferred_size_changes_(false),
-      navigation_gesture_(NavigationGestureUnknown),
-      history_list_offset_(-1),
-      history_list_length_(0),
-      frames_in_progress_(0),
-      target_url_status_(TARGET_NONE),
-#if defined(OS_ANDROID)
-      top_controls_constraints_(BROWSER_CONTROLS_STATE_BOTH),
-#endif
-      browser_controls_shrink_blink_size_(false),
-      top_controls_height_(0.f),
-      bottom_controls_height_(0.f),
-      webview_(nullptr),
-      page_zoom_level_(0),
-      main_render_frame_(nullptr),
-      frame_widget_(nullptr),
-#if defined(OS_ANDROID)
-      was_created_by_renderer_(false),
-#endif
-      enumeration_completion_id_(0),
       session_storage_namespace_id_(params.session_storage_namespace_id),
-      renderer_wide_named_frame_lookup_(false),
       weak_ptr_factory_(this) {
   GetWidget()->set_owner_delegate(this);
   RenderThread::Get()->AddRoute(routing_id_, this);
@@ -583,10 +560,8 @@
 
   UpdateWebViewWithDeviceScaleFactor();
   OnSetRendererPrefs(params->renderer_preferences);
-
   OnSynchronizeVisualProperties(params->visual_properties);
-
-  idle_user_detector_.reset(new IdleUserDetector());
+  RenderWidget::SetUpIdleUserDetector();
 
   GetContentClient()->renderer()->RenderViewCreated(this);
   page_zoom_level_ = 0;
@@ -616,7 +591,6 @@
     DCHECK_NE(this, it->second) << "Failed to call Close?";
 #endif
 
-  idle_user_detector_.reset();
   for (auto& observer : observers_)
     observer.RenderViewGone();
   for (auto& observer : observers_)
@@ -1037,21 +1011,25 @@
   return webview_;
 }
 
-// RenderWidgetInputHandlerDelegate -----------------------------------------
+// RenderWidgetOwnerDelegate -----------------------------------------
 
-bool RenderViewImpl::RenderWidgetWillHandleMouseEvent(
+blink::WebWidget* RenderViewImpl::GetWebWidgetForWidget() const {
+  return frame_widget_;
+}
+
+bool RenderViewImpl::RenderWidgetWillHandleMouseEventForWidget(
     const blink::WebMouseEvent& event) {
   // If the mouse is locked, only the current owner of the mouse lock can
   // process mouse events.
-  return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
+  return GetWidget()->mouse_lock_dispatcher()->WillHandleMouseEvent(event);
 }
 
-void RenderViewImpl::SetActive(bool active) {
+void RenderViewImpl::SetActiveForWidget(bool active) {
   if (webview())
     webview()->SetIsActive(active);
 }
 
-void RenderViewImpl::SetBackgroundOpaque(bool opaque) {
+void RenderViewImpl::SetBackgroundOpaqueForWidget(bool opaque) {
   if (!frame_widget_)
     return;
 
@@ -1064,7 +1042,235 @@
   }
 }
 
-// IPC::Listener implementation ----------------------------------------------
+bool RenderViewImpl::SupportsMultipleWindowsForWidget() {
+  return webkit_preferences_.supports_multiple_windows;
+}
+
+void RenderViewImpl::DidHandleGestureEventForWidget(
+    const WebGestureEvent& event) {
+  for (auto& observer : observers_)
+    observer.DidHandleGestureEvent(event);
+}
+
+void RenderViewImpl::OverrideCloseForWidget() {
+  DCHECK(frame_widget_);
+  frame_widget_->Close();
+  frame_widget_ = nullptr;
+}
+
+void RenderViewImpl::DidCloseWidget() {
+  // The webview_ is already destroyed by the time we get here, remove any
+  // references to it.
+  g_view_map.Get().erase(webview_);
+  webview_ = nullptr;
+  g_routing_id_view_map.Get().erase(GetRoutingID());
+  // TODO(ajwong): Does this message actually get sent?
+  RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
+}
+
+void RenderViewImpl::ApplyNewSizeForWidget(const gfx::Size& old_size,
+                                           const gfx::Size& new_size) {
+  if (webview()) {
+    // Only hide popups when the size changes. There are situations (e.g. hiding
+    // the ChromeOS virtual keyboard) where we send a resize message with no
+    // change in size, but we don't want to close popups.
+    // See https://crbug.com/761908.
+    if (new_size != old_size)
+      webview()->HidePopups();
+
+    if (send_preferred_size_changes_ &&
+        webview()->MainFrame()->IsWebLocalFrame()) {
+      webview()->MainFrame()->ToWebLocalFrame()->SetCanHaveScrollbars(
+          ShouldDisplayScrollbars(new_size.width(), new_size.height()));
+    }
+  }
+}
+
+void RenderViewImpl::ApplyNewDisplayModeForWidget(
+    const blink::WebDisplayMode& new_display_mode) {
+  if (webview())
+    webview()->SetDisplayMode(new_display_mode);
+}
+
+void RenderViewImpl::ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+                                                    const gfx::Size& max_size) {
+  webview()->EnableAutoResizeMode(min_size, max_size);
+}
+
+void RenderViewImpl::DisableAutoResizeForWidget() {
+  webview()->DisableAutoResizeMode();
+}
+
+void RenderViewImpl::ScrollFocusedNodeIntoViewForWidget() {
+  if (WebLocalFrame* focused_frame = GetWebView()->FocusedFrame()) {
+    auto* frame_widget = focused_frame->LocalRoot()->FrameWidget();
+    frame_widget->ScrollFocusedEditableElementIntoView();
+  }
+}
+
+void RenderViewImpl::DidReceiveSetFocusEventForWidget() {
+  // This message must always be received when the main frame is a
+  // WebLocalFrame.
+  // TODO(ajwong): Can this be removed and just check |owner_delegate_| in
+  // RenderWidget instead?
+  CHECK(webview()->MainFrame()->IsWebLocalFrame());
+}
+
+void RenderViewImpl::DidChangeFocusForWidget() {
+  // Notify all BrowserPlugins of the RenderView's focus state.
+  if (BrowserPluginManager::Get())
+    BrowserPluginManager::Get()->UpdateFocusState();
+}
+
+GURL RenderViewImpl::GetURLForGraphicsContext3DForWidget() {
+  DCHECK(webview());
+  WebFrame* main_frame = webview()->MainFrame();
+  if (main_frame && main_frame->IsWebLocalFrame())
+    return GURL(main_frame->ToWebLocalFrame()->GetDocument().Url());
+  else
+    return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
+}
+
+void RenderViewImpl::DidCommitCompositorFrameForWidget() {
+  for (auto& observer : observers_)
+    observer.DidCommitCompositorFrame();
+}
+
+void RenderViewImpl::DidCompletePageScaleAnimationForWidget() {
+  if (auto* focused_frame = GetWebView()->FocusedFrame()) {
+    if (focused_frame->AutofillClient())
+      focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
+  }
+}
+
+void RenderViewImpl::ResizeWebWidgetForWidget(
+    const gfx::Size& size,
+    float top_controls_height,
+    float bottom_controls_height,
+    bool browser_controls_shrink_blink_size) {
+  webview()->ResizeWithBrowserControls(size, top_controls_height,
+                                       bottom_controls_height,
+                                       browser_controls_shrink_blink_size);
+}
+
+void RenderViewImpl::RequestScheduleAnimationForWidget() {
+  // Schedule the animation on the WidgetClient() which may not be the
+  // RenderWidget directly in layout tests.
+  WidgetClient()->ScheduleAnimation();
+}
+
+void RenderViewImpl::SetScreenMetricsEmulationParametersForWidget(
+    bool enabled,
+    const blink::WebDeviceEmulationParams& params) {
+  if (webview() && GetWidget()->layer_tree_view()) {
+    if (enabled)
+      webview()->EnableDeviceEmulation(params);
+    else
+      webview()->DisableDeviceEmulation();
+  }
+}
+
+// IPC message handlers -----------------------------------------
+
+void RenderViewImpl::OnSelectWordAroundCaret() {
+  // TODO(ajwong): Move this into RenderWidget. http://crbug.com/545684
+  // Set default values for the ACK
+  bool did_select = false;
+  int start_adjust = 0;
+  int end_adjust = 0;
+
+  if (webview()) {
+    WebLocalFrame* focused_frame = GetWebView()->FocusedFrame();
+    if (focused_frame) {
+      input_handler_->set_handling_input_event(true);
+      blink::WebRange initial_range = focused_frame->SelectionRange();
+      if (!initial_range.IsNull())
+        did_select = focused_frame->SelectWordAroundCaret();
+      if (did_select) {
+        blink::WebRange adjusted_range = focused_frame->SelectionRange();
+        start_adjust =
+            adjusted_range.StartOffset() - initial_range.StartOffset();
+        end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
+      }
+      input_handler_->set_handling_input_event(false);
+    }
+  }
+  Send(new ViewHostMsg_SelectWordAroundCaretAck(
+      GetWidget()->routing_id(), did_select, start_adjust, end_adjust));
+}
+
+void RenderViewImpl::OnUpdateTargetURLAck() {
+  // Check if there is a targeturl waiting to be sent.
+  if (target_url_status_ == TARGET_PENDING)
+    Send(new ViewHostMsg_UpdateTargetURL(GetRoutingID(), pending_target_url_));
+
+  target_url_status_ = TARGET_NONE;
+}
+
+void RenderViewImpl::OnSetHistoryOffsetAndLength(int history_offset,
+                                                 int history_length) {
+  // -1 <= history_offset < history_length <= kMaxSessionHistoryEntries(50).
+  DCHECK_LE(-1, history_offset);
+  DCHECK_LT(history_offset, history_length);
+  DCHECK_LE(history_length, kMaxSessionHistoryEntries);
+
+  history_list_offset_ = history_offset;
+  history_list_length_ = history_length;
+}
+
+void RenderViewImpl::OnSetInitialFocus(bool reverse) {
+  if (!webview())
+    return;
+  webview()->SetInitialFocus(reverse);
+}
+
+void RenderViewImpl::OnUpdateWindowScreenRect(gfx::Rect window_screen_rect) {
+  // Defers to the RenderWidget message handler.
+  RenderWidget::OnUpdateWindowScreenRect(window_screen_rect);
+}
+
+void RenderViewImpl::OnAudioStateChanged(bool is_audio_playing) {
+  webview()->AudioStateChanged(is_audio_playing);
+}
+
+void RenderViewImpl::OnPausePageScheduledTasks(bool paused) {
+  webview()->PausePageScheduledTasks(paused);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void RenderViewImpl::ShowCreatedPopupWidget(RenderWidget* popup_widget,
+                                            WebNavigationPolicy policy,
+                                            const gfx::Rect& initial_rect) {
+  Send(new ViewHostMsg_ShowWidget(GetRoutingID(), popup_widget->routing_id(),
+                                  initial_rect));
+}
+
+void RenderViewImpl::ShowCreatedFullscreenWidget(
+    RenderWidget* fullscreen_widget,
+    WebNavigationPolicy policy,
+    const gfx::Rect& initial_rect) {
+  Send(new ViewHostMsg_ShowFullscreenWidget(GetRoutingID(),
+                                            fullscreen_widget->routing_id()));
+}
+
+void RenderViewImpl::SendFrameStateUpdates() {
+  // Tell each frame with pending state to send its UpdateState message.
+  for (int render_frame_routing_id : frames_with_pending_state_) {
+    RenderFrameImpl* frame =
+        RenderFrameImpl::FromRoutingID(render_frame_routing_id);
+    if (frame)
+      frame->SendUpdateState();
+  }
+  frames_with_pending_state_.clear();
+}
+
+void RenderViewImpl::ApplyWebPreferencesInternal(const WebPreferences& prefs,
+                                                 blink::WebView* web_view) {
+  ApplyWebPreferences(prefs, web_view);
+}
+
+// IPC::Listener -------------------------------------------------------------
 
 bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
   WebFrame* main_frame = webview() ? webview()->MainFrame() : nullptr;
@@ -1127,103 +1333,6 @@
   return handled;
 }
 
-void RenderViewImpl::OnSelectWordAroundCaret() {
-  // TODO(ajwong): Move this into RenderWidget. http://crbug.com/545684
-  // Set default values for the ACK
-  bool did_select = false;
-  int start_adjust = 0;
-  int end_adjust = 0;
-
-  if (webview()) {
-    WebLocalFrame* focused_frame = GetWebView()->FocusedFrame();
-    if (focused_frame) {
-      input_handler_->set_handling_input_event(true);
-      blink::WebRange initial_range = focused_frame->SelectionRange();
-      if (!initial_range.IsNull())
-        did_select = focused_frame->SelectWordAroundCaret();
-      if (did_select) {
-        blink::WebRange adjusted_range = focused_frame->SelectionRange();
-        start_adjust =
-            adjusted_range.StartOffset() - initial_range.StartOffset();
-        end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
-      }
-      input_handler_->set_handling_input_event(false);
-    }
-  }
-  Send(new ViewHostMsg_SelectWordAroundCaretAck(
-      GetWidget()->routing_id(), did_select, start_adjust, end_adjust));
-}
-
-void RenderViewImpl::OnUpdateTargetURLAck() {
-  // Check if there is a targeturl waiting to be sent.
-  if (target_url_status_ == TARGET_PENDING)
-    Send(new ViewHostMsg_UpdateTargetURL(GetRoutingID(), pending_target_url_));
-
-  target_url_status_ = TARGET_NONE;
-}
-
-void RenderViewImpl::OnSetHistoryOffsetAndLength(int history_offset,
-                                                 int history_length) {
-  // -1 <= history_offset < history_length <= kMaxSessionHistoryEntries(50).
-  DCHECK_LE(-1, history_offset);
-  DCHECK_LT(history_offset, history_length);
-  DCHECK_LE(history_length, kMaxSessionHistoryEntries);
-
-  history_list_offset_ = history_offset;
-  history_list_length_ = history_length;
-}
-
-void RenderViewImpl::OnSetInitialFocus(bool reverse) {
-  if (!webview())
-    return;
-  webview()->SetInitialFocus(reverse);
-}
-
-void RenderViewImpl::OnUpdateWindowScreenRect(gfx::Rect window_screen_rect) {
-  RenderWidget::OnUpdateWindowScreenRect(window_screen_rect);
-}
-
-void RenderViewImpl::OnAudioStateChanged(bool is_audio_playing) {
-  webview()->AudioStateChanged(is_audio_playing);
-}
-
-void RenderViewImpl::OnPausePageScheduledTasks(bool paused) {
-  webview()->PausePageScheduledTasks(paused);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void RenderViewImpl::ShowCreatedPopupWidget(RenderWidget* popup_widget,
-                                            WebNavigationPolicy policy,
-                                            const gfx::Rect& initial_rect) {
-  Send(new ViewHostMsg_ShowWidget(GetRoutingID(), popup_widget->routing_id(),
-                                  initial_rect));
-}
-
-void RenderViewImpl::ShowCreatedFullscreenWidget(
-    RenderWidget* fullscreen_widget,
-    WebNavigationPolicy policy,
-    const gfx::Rect& initial_rect) {
-  Send(new ViewHostMsg_ShowFullscreenWidget(GetRoutingID(),
-                                            fullscreen_widget->routing_id()));
-}
-
-void RenderViewImpl::SendFrameStateUpdates() {
-  // Tell each frame with pending state to send its UpdateState message.
-  for (int render_frame_routing_id : frames_with_pending_state_) {
-    RenderFrameImpl* frame =
-        RenderFrameImpl::FromRoutingID(render_frame_routing_id);
-    if (frame)
-      frame->SendUpdateState();
-  }
-  frames_with_pending_state_.clear();
-}
-
-void RenderViewImpl::ApplyWebPreferencesInternal(const WebPreferences& prefs,
-                                                 blink::WebView* web_view) {
-  ApplyWebPreferences(prefs, web_view);
-}
-
 // blink::WebViewClient ------------------------------------------------------
 
 // TODO(csharrison): Migrate this method to WebLocalFrameClient /
@@ -1389,7 +1498,7 @@
                         frame->Top()->IsWebRemoteFrame());
 
   RenderFrameImpl::FromWebFrame(frame)->ScriptedPrint(
-      input_handler().handling_input_event());
+      input_handler_->handling_input_event());
 }
 
 bool RenderViewImpl::EnumerateChosenDirectory(
@@ -1597,40 +1706,6 @@
 
 // blink::WebWidgetClient ----------------------------------------------------
 
-void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
-  // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
-  //                 we won't have to test for user gesture anymore and we can
-  //                 move that code back to render_widget.cc
-  if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) &&
-      !RenderThreadImpl::current()->layout_test_mode()) {
-    Send(new ViewHostMsg_Focus(GetRoutingID()));
-
-    // Tattle on the frame that called |window.focus()|.
-    RenderFrameImpl* calling_render_frame =
-        RenderFrameImpl::FromWebFrame(calling_frame);
-    if (calling_render_frame)
-      calling_render_frame->FrameDidCallFocus();
-  }
-}
-
-// We are supposed to get a single call to show() for a newly created RenderView
-// that was created via RenderViewImpl::createView.  We wait until this point to
-// run |show_callback|, which is bound to our opener's ShowCreatedViewWidget()
-// method.
-//
-// This method provides us with the information about how to display the newly
-// created RenderView (i.e., as a blocked popup or as a new tab).
-void RenderViewImpl::Show(WebNavigationPolicy policy) {
-  if (did_show_ && !webkit_preferences_.supports_multiple_windows) {
-    // When supports_multiple_windows is disabled, popups are reusing
-    // the same view. In some scenarios, this makes WebKit to call show() twice.
-    return;
-  }
-
-  RenderWidget::Show(policy);
-}
-
-
 bool RenderViewImpl::CanHandleGestureEvent() {
   return true;
 }
@@ -1639,16 +1714,6 @@
   return true;
 }
 
-void RenderViewImpl::DidHandleGestureEvent(const WebGestureEvent& event,
-                                           bool event_cancelled) {
-  RenderWidget::DidHandleGestureEvent(event, event_cancelled);
-
-  if (!event_cancelled) {
-    for (auto& observer : observers_)
-      observer.DidHandleGestureEvent(event);
-  }
-}
-
 blink::WebWidgetClient* RenderViewImpl::WidgetClient() {
   return this;
 }
@@ -1705,6 +1770,10 @@
 // RenderView implementation ---------------------------------------------------
 
 bool RenderViewImpl::Send(IPC::Message* message) {
+  // This method is an override of IPC::Sender, but RenderWidget also has an
+  // override of IPC::Sender, so this method also overrides RenderWidget. Thus
+  // we must call to the base class, not via an upcast or virtual dispatch would
+  // go back here.
   return RenderWidget::Send(message);
 }
 
@@ -1859,6 +1928,7 @@
 void RenderViewImpl::OnClose() {
   if (closing_)
     RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
+  // OnClose() is a protected member of RenderWidget.
   RenderWidget::OnClose();
 }
 #endif
@@ -1868,113 +1938,6 @@
     webview()->HidePopups();
 }
 
-void RenderViewImpl::ResizeWebWidget() {
-  webview()->ResizeWithBrowserControls(
-      GetSizeForWebWidget(), top_controls_height_, bottom_controls_height_,
-      browser_controls_shrink_blink_size_);
-}
-
-void RenderViewImpl::RequestScheduleAnimation() {
-  // RenderWidget is a WebWidgetClient but layout tests want to override the
-  // client for WebViews, and can't do it by subclassing RenderWidget since they
-  // have a RenderViewImpl in this case, which is-a RenderWidget.
-  WidgetClient()->ScheduleAnimation();
-}
-
-void RenderViewImpl::OnSynchronizeVisualProperties(
-    const VisualProperties& params) {
-  TRACE_EVENT0("renderer", "RenderViewImpl::OnSynchronizeVisualProperties");
-
-  if (webview()) {
-    // Only hide popups when the size changes. There are situations (e.g. hiding
-    // the ChromeOS virtual keyboard) where we send a resize message with no
-    // change in size, but we don't want to close popups.
-    // See https://crbug.com/761908.
-    if (params.new_size != GetSize())
-      webview()->HidePopups();
-
-    if (send_preferred_size_changes_ &&
-        webview()->MainFrame()->IsWebLocalFrame()) {
-      webview()->MainFrame()->ToWebLocalFrame()->SetCanHaveScrollbars(
-          ShouldDisplayScrollbars(params.new_size.width(),
-                                  params.new_size.height()));
-    }
-    if (display_mode_ != params.display_mode) {
-      display_mode_ = params.display_mode;
-      webview()->SetDisplayMode(display_mode_);
-    }
-  }
-
-  bool auto_resize_mode_changed =
-      auto_resize_mode_ != params.auto_resize_enabled;
-  auto_resize_mode_ = params.auto_resize_enabled;
-  min_size_for_auto_resize_ = params.min_size_for_auto_resize;
-  max_size_for_auto_resize_ = params.max_size_for_auto_resize;
-  if (auto_resize_mode_) {
-    if (IsUseZoomForDSFEnabled()) {
-      webview()->EnableAutoResizeMode(
-          gfx::ScaleToCeiledSize(params.min_size_for_auto_resize,
-                                 params.screen_info.device_scale_factor),
-          gfx::ScaleToCeiledSize(params.max_size_for_auto_resize,
-                                 params.screen_info.device_scale_factor));
-    } else {
-      webview()->EnableAutoResizeMode(params.min_size_for_auto_resize,
-                                      params.max_size_for_auto_resize);
-    }
-  } else if (auto_resize_mode_changed) {
-    webview()->DisableAutoResizeMode();
-    if (params.new_size.IsEmpty())
-      return;
-  }
-
-  browser_controls_shrink_blink_size_ =
-      params.browser_controls_shrink_blink_size;
-  top_controls_height_ = params.top_controls_height;
-  bottom_controls_height_ = params.bottom_controls_height;
-
-  if (device_scale_factor_for_testing_) {
-    VisualProperties p(params);
-    p.screen_info.device_scale_factor = *device_scale_factor_for_testing_;
-    p.compositor_viewport_pixel_size =
-        gfx::ScaleToCeiledSize(p.new_size, p.screen_info.device_scale_factor);
-    RenderWidget::OnSynchronizeVisualProperties(p);
-  } else {
-    RenderWidget::OnSynchronizeVisualProperties(params);
-  }
-
-  if (!params.scroll_focused_node_into_view)
-    return;
-
-  if (WebLocalFrame* focused_frame = GetWebView()->FocusedFrame()) {
-    focused_frame->LocalRoot()
-        ->FrameWidget()
-        ->ScrollFocusedEditableElementIntoView();
-  }
-}
-
-blink::WebWidget* RenderViewImpl::GetWebWidget() const {
-  if (frame_widget_)
-    return frame_widget_;
-
-  return RenderWidget::GetWebWidget();
-}
-
-void RenderViewImpl::CloseForFrame() {
-  DCHECK(frame_widget_);
-  frame_widget_->Close();
-  frame_widget_ = nullptr;
-}
-
-void RenderViewImpl::Close() {
-  // We need to grab a pointer to the doomed WebView before we destroy it.
-  WebView* doomed = webview_;
-  RenderWidget::Close();
-  webview_ = nullptr;
-  g_view_map.Get().erase(doomed);
-  g_routing_id_view_map.Get().erase(GetRoutingID());
-  RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
-}
-
 void RenderViewImpl::OnPageWasHidden() {
 #if defined(OS_ANDROID)
   SuspendVideoCaptureDevices(true);
@@ -2018,46 +1981,10 @@
     webview()->SetPageFrozen(frozen);
 }
 
-GURL RenderViewImpl::GetURLForGraphicsContext3D() {
-  DCHECK(webview());
-  WebFrame* main_frame = webview()->MainFrame();
-  if (main_frame && main_frame->IsWebLocalFrame())
-    return GURL(main_frame->ToWebLocalFrame()->GetDocument().Url());
-  else
-    return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
-}
-
-void RenderViewImpl::OnSetFocus(bool enable) {
-  // This message must always be received when the main frame is a
-  // WebLocalFrame.
-  CHECK(webview()->MainFrame()->IsWebLocalFrame());
-  SetFocus(enable);
-}
-
 void RenderViewImpl::SetFocus(bool enable) {
-  RenderWidget::OnSetFocus(enable);
-
-  // Notify all BrowserPlugins of the RenderView's focus state.
-  if (BrowserPluginManager::Get())
-    BrowserPluginManager::Get()->UpdateFocusState();
-}
-
-void RenderViewImpl::DidCompletePageScaleAnimation() {
-  if (auto* focused_frame = GetWebView()->FocusedFrame()) {
-    if (focused_frame->AutofillClient())
-      focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
-  }
-}
-
-void RenderViewImpl::SetScreenMetricsEmulationParameters(
-    bool enabled,
-    const blink::WebDeviceEmulationParams& params) {
-  if (webview() && layer_tree_view()) {
-    if (enabled)
-      webview()->EnableDeviceEmulation(params);
-    else
-      webview()->DisableDeviceEmulation();
-  }
+  // This is not an IPC message, don't go through the IPC handler. This is used
+  // in cases where the IPC message should not happen.
+  GetWidget()->SetFocus(enable);
 }
 
 void RenderViewImpl::ZoomLimitsChanged(double minimum_level,
@@ -2103,13 +2030,29 @@
 }
 
 void RenderViewImpl::DidAutoResize(const blink::WebSize& newSize) {
-  RenderWidget::DidAutoResize(newSize);
+  GetWidget()->DidAutoResize(newSize);
 }
 
 blink::WebRect RenderViewImpl::RootWindowRect() {
   return WidgetClient()->WindowRect();
 }
 
+void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
+  // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
+  //                 we won't have to test for user gesture anymore and we can
+  //                 move that code back to render_widget.cc
+  if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) &&
+      !RenderThreadImpl::current()->layout_test_mode()) {
+    Send(new ViewHostMsg_Focus(GetRoutingID()));
+
+    // Tattle on the frame that called |window.focus()|.
+    RenderFrameImpl* calling_render_frame =
+        RenderFrameImpl::FromWebFrame(calling_frame);
+    if (calling_render_frame)
+      calling_render_frame->FrameDidCallFocus();
+  }
+}
+
 #if defined(OS_ANDROID)
 bool RenderViewImpl::OpenDateTimeChooser(
     const blink::WebDateTimeChooserParams& params,
@@ -2244,103 +2187,24 @@
   if (webview()->MainFrame()->IsWebRemoteFrame())
     return;
 
+  if (enable == has_focus())
+    return;
+
   if (enable) {
-    if (has_focus())
-      return;
-    SetActive(true);
+    SetActiveForWidget(true);
+    // Fake an IPC message so go through the IPC handler.
     OnSetFocus(true);
   } else {
-    if (!has_focus())
-      return;
+    // Fake an IPC message so go through the IPC handler.
     OnSetFocus(false);
-    SetActive(false);
+    SetActiveForWidget(false);
   }
 }
 
-void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
-  device_scale_factor_for_testing_ = factor;
-
-  VisualProperties visual_properties;
-  visual_properties.screen_info = screen_info_;
-  visual_properties.screen_info.device_scale_factor = factor;
-  visual_properties.new_size = size();
-  visual_properties.visible_viewport_size = visible_viewport_size_;
-  visual_properties.compositor_viewport_pixel_size =
-      gfx::ScaleToCeiledSize(size(), factor);
-  visual_properties.browser_controls_shrink_blink_size = false;
-  visual_properties.top_controls_height = 0.f;
-  visual_properties.is_fullscreen_granted = is_fullscreen_granted();
-  visual_properties.display_mode = display_mode_;
-  visual_properties.local_surface_id = local_surface_id_from_parent_;
-  // We are changing the device scale factor from the renderer, so allocate a
-  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  if (layer_tree_view())
-    layer_tree_view()->RequestNewLocalSurfaceId();
-
-  OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::SetDeviceColorSpaceForTesting(
-    const gfx::ColorSpace& color_space) {
-  VisualProperties visual_properties;
-  visual_properties.screen_info = screen_info_;
-  visual_properties.screen_info.color_space = color_space;
-  visual_properties.new_size = size();
-  visual_properties.visible_viewport_size = visible_viewport_size_;
-  visual_properties.compositor_viewport_pixel_size =
-      compositor_viewport_pixel_size_;
-  visual_properties.browser_controls_shrink_blink_size = false;
-  visual_properties.top_controls_height = 0.f;
-  visual_properties.is_fullscreen_granted = is_fullscreen_granted();
-  visual_properties.display_mode = display_mode_;
-  visual_properties.local_surface_id = local_surface_id_from_parent_;
-  // We are changing the device color space from the renderer, so allocate a
-  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  if (layer_tree_view())
-    layer_tree_view()->RequestNewLocalSurfaceId();
-  OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
-  gfx::Rect new_window_rect(RootWindowRect().x, RootWindowRect().y,
-                            new_size.width(), new_size.height());
-  SetWindowRectSynchronously(new_window_rect);
-}
-
 void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
   resizing_mode_selector_->set_is_synchronous_mode(enable);
 }
 
-void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
-                                                const gfx::Size& max_size) {
-  VisualProperties visual_properties;
-  visual_properties.auto_resize_enabled = true;
-  visual_properties.min_size_for_auto_resize = min_size;
-  visual_properties.max_size_for_auto_resize = max_size;
-  visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>(
-      viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
-  OnSynchronizeVisualProperties(visual_properties);
-}
-
-void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) {
-  if (!auto_resize_mode_)
-    return;
-
-  VisualProperties visual_properties;
-  visual_properties.auto_resize_enabled = false;
-  visual_properties.screen_info = screen_info_;
-  visual_properties.new_size = new_size;
-  visual_properties.compositor_viewport_pixel_size =
-      compositor_viewport_pixel_size_;
-  visual_properties.browser_controls_shrink_blink_size =
-      browser_controls_shrink_blink_size_;
-  visual_properties.top_controls_height = top_controls_height_;
-  visual_properties.visible_viewport_size = visible_viewport_size_;
-  visual_properties.is_fullscreen_granted = is_fullscreen_granted();
-  visual_properties.display_mode = display_mode_;
-  OnSynchronizeVisualProperties(visual_properties);
-}
-
 void RenderViewImpl::OnResolveTapDisambiguation(
     base::TimeTicks timestamp,
     const gfx::Point& tap_viewport_offset,
@@ -2349,24 +2213,4 @@
                                       is_long_press);
 }
 
-void RenderViewImpl::DidCommitCompositorFrame() {
-  RenderWidget::DidCommitCompositorFrame();
-  for (auto& observer : observers_)
-    observer.DidCommitCompositorFrame();
-}
-
-void RenderViewImpl::HandleInputEvent(
-    const blink::WebCoalescedInputEvent& input_event,
-    const ui::LatencyInfo& latency_info,
-    HandledEventCallback callback) {
-  if (is_swapped_out_) {
-    std::move(callback).Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, latency_info,
-                            nullptr, base::nullopt);
-    return;
-  }
-  idle_user_detector_->ActivityDetected();
-  RenderWidget::HandleInputEvent(input_event, latency_info,
-                                 std::move(callback));
-}
-
 }  // namespace content
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index bcd629c4..dab34d99 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -72,19 +72,12 @@
 struct WebWindowFeatures;
 }  // namespace blink
 
-namespace gfx {
-class ColorSpace;
-}
-
 namespace content {
-
-class IdleUserDetector;
 class RendererDateTimePicker;
 class RenderViewImplTest;
 class RenderViewObserver;
 class RenderViewTest;
 struct FileChooserParams;
-struct VisualProperties;
 
 namespace mojom {
 class CreateViewParams;
@@ -213,26 +206,11 @@
   // synchronously from the renderer.
   void SetFocusAndActivateForTesting(bool enable);
 
-  // Change the device scale factor and force the compositor to resize.
-  void SetDeviceScaleFactorForTesting(float factor);
-
-  // Change the device ICC color profile while running a layout test.
-  void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
-
-  // Used to force the size of a window when running layout tests.
-  void ForceResizeForTesting(const gfx::Size& new_size);
-
   void UseSynchronousResizeModeForTesting(bool enable);
 
   void DidCommitProvisionalHistoryLoad();
 
-  // Control autoresize mode.
-  void EnableAutoResizeForTesting(const gfx::Size& min_size,
-                                  const gfx::Size& max_size);
-  void DisableAutoResizeForTesting(const gfx::Size& new_size);
-
-  // IPC::Listener implementation ----------------------------------------------
-
+  // IPC::Listener implementation (via RenderWidget inheritance).
   bool OnMessageReceived(const IPC::Message& msg) override;
 
   // blink::WebViewClient implementation --------------------------------------
@@ -285,7 +263,7 @@
   blink::WebRect RootWindowRect() override;
   void DidFocus(blink::WebLocalFrame* calling_frame) override;
   bool CanHandleGestureEvent() override;
-  WebWidgetClient* WidgetClient() override;
+  blink::WebWidgetClient* WidgetClient() override;
 
 #if defined(OS_ANDROID)
   // Only used on Android since all other platforms implement
@@ -329,28 +307,12 @@
     return weak_ptr_factory_.GetWeakPtr();
   }
 
-  void HandleInputEvent(const blink::WebCoalescedInputEvent& input_event,
-                        const ui::LatencyInfo& latency_info,
-                        HandledEventCallback callback) override;
-
   bool renderer_wide_named_frame_lookup() {
     return renderer_wide_named_frame_lookup_;
   }
   void UpdateZoomLevel(double zoom_level);
 
  protected:
-  // RenderWidget overrides:
-  blink::WebWidget* GetWebWidget() const override;
-  void CloseForFrame() override;
-  void Close() override;
-  void OnSynchronizeVisualProperties(const VisualProperties& params) override;
-  void OnSetFocus(bool enable) override;
-  GURL GetURLForGraphicsContext3D() override;
-  void DidCommitCompositorFrame() override;
-  void DidCompletePageScaleAnimation() override;
-  void ResizeWebWidget() override;
-  void RequestScheduleAnimation() override;
-
   RenderViewImpl(CompositorDependencies* compositor_deps,
                  const mojom::CreateViewParams& params,
                  scoped_refptr<base::SingleThreadTaskRunner> task_runner);
@@ -358,9 +320,6 @@
   void Initialize(mojom::CreateViewParamsPtr params,
                   RenderWidget::ShowCallback show_callback,
                   scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-  void SetScreenMetricsEmulationParameters(
-      bool enabled,
-      const blink::WebDeviceEmulationParams& params) override;
 
   // Do not delete directly.  This class is reference counted.
   ~RenderViewImpl() override;
@@ -441,10 +400,38 @@
 
   // RenderWidgetOwnerDelegate implementation ----------------------------------
 
-  bool RenderWidgetWillHandleMouseEvent(
+  blink::WebWidget* GetWebWidgetForWidget() const override;
+  bool RenderWidgetWillHandleMouseEventForWidget(
       const blink::WebMouseEvent& event) override;
-  void SetActive(bool active) override;
-  void SetBackgroundOpaque(bool opaque) override;
+  void SetActiveForWidget(bool active) override;
+  void SetBackgroundOpaqueForWidget(bool opaque) override;
+  bool SupportsMultipleWindowsForWidget() override;
+  void DidHandleGestureEventForWidget(
+      const blink::WebGestureEvent& event) override;
+  void OverrideCloseForWidget() override;
+  void DidCloseWidget() override;
+  void ApplyNewSizeForWidget(const gfx::Size& old_size,
+                             const gfx::Size& new_size) override;
+  void ApplyNewDisplayModeForWidget(
+      const blink::WebDisplayMode& new_display_mode) override;
+  void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+                                      const gfx::Size& max_size) override;
+  void DisableAutoResizeForWidget() override;
+  void ScrollFocusedNodeIntoViewForWidget() override;
+  void DidReceiveSetFocusEventForWidget() override;
+  void DidChangeFocusForWidget() override;
+  GURL GetURLForGraphicsContext3DForWidget() override;
+  void DidCommitCompositorFrameForWidget() override;
+  void DidCompletePageScaleAnimationForWidget() override;
+  void ResizeWebWidgetForWidget(
+      const gfx::Size& size,
+      float top_controls_height,
+      float bottom_controls_height,
+      bool browser_controls_shrink_blink_size) override;
+  void RequestScheduleAnimationForWidget() override;
+  void SetScreenMetricsEmulationParametersForWidget(
+      bool enabled,
+      const blink::WebDeviceEmulationParams& params) override;
 
   // Old WebLocalFrameClient implementations
   // ----------------------------------------
@@ -465,12 +452,6 @@
   void ApplyWebPreferencesInternal(const WebPreferences& prefs,
                                    blink::WebView* web_view);
 
-  // blink::WebWidgetClient overrides from RenderWidget ------------------------
-
-  void Show(blink::WebNavigationPolicy policy) override;
-  void DidHandleGestureEvent(const blink::WebGestureEvent& event,
-                             bool event_cancelled) override;
-
   // IPC message handlers ------------------------------------------------------
   //
   // The documentation for these functions should be in
@@ -581,10 +562,10 @@
   // Whether content state (such as form state, scroll position and page
   // contents) should be sent to the browser immediately. This is normally
   // false, but set to true by some tests.
-  bool send_content_state_immediately_;
+  bool send_content_state_immediately_ = false;
 
   // If true, we send IPC messages when |preferred_size_| changes.
-  bool send_preferred_size_changes_;
+  bool send_preferred_size_changes_ = false;
 
   // If non-empty, and |send_preferred_size_changes_| is true, disable drawing
   // scroll bars on windows smaller than this size.  Used for windows that the
@@ -601,7 +582,7 @@
 
   // The gesture that initiated the current navigation.
   // TODO(nasko): Move to RenderFrame, as this is per-frame state.
-  NavigationGesture navigation_gesture_;
+  NavigationGesture navigation_gesture_ = NavigationGestureUnknown;
 
   // Timer used to delay the updating of nav state (see
   // StartNavStateSyncTimerIfNecessary).
@@ -614,19 +595,20 @@
   // History list --------------------------------------------------------------
 
   // The offset of the current item in the history list.
-  int history_list_offset_;
+  int history_list_offset_ = -1;
 
   // The RenderView's current impression of the history length.  This includes
   // any items that have committed in this process, but because of cross-process
   // navigations, the history may have some entries that were committed in other
   // processes.  We won't know about them until the next navigation in this
   // process.
-  int history_list_length_;
+  int history_list_length_ = 0;
 
   // Counter to track how many frames have sent start notifications but not stop
-  // notifications. TODO(avi): Remove this once DidStartLoading/DidStopLoading
-  // are gone.
-  int frames_in_progress_;
+  // notifications.
+  // TODO(avi): Remove this once FrameDidStartLoading/FrameDidStopLoading are
+  // gone.
+  int frames_in_progress_ = 0;
 
   // UI state ------------------------------------------------------------------
 
@@ -642,7 +624,7 @@
     TARGET_NONE,
     TARGET_INFLIGHT,  // We have a request in-flight, waiting for an ACK
     TARGET_PENDING    // INFLIGHT + we have a URL waiting to be sent
-  } target_url_status_;
+  } target_url_status_ = TARGET_NONE;
 
   // The URL we show the user in the status bar. We use this to determine if we
   // want to send a new one (we do not need to send duplicates). It will be
@@ -662,22 +644,12 @@
 #if defined(OS_ANDROID)
   // Cache the old browser controls state constraints. Used when updating
   // current value only without altering the constraints.
-  BrowserControlsState top_controls_constraints_;
+  BrowserControlsState top_controls_constraints_ = BROWSER_CONTROLS_STATE_BOTH;
 #endif
 
-  // Whether or not Blink's viewport size should be shrunk by the height of the
-  // URL-bar.
-  bool browser_controls_shrink_blink_size_;
-
-  // The height of the browser top controls.
-  float top_controls_height_;
-
-  // The height of the browser bottom controls.
-  float bottom_controls_height_;
-
   // View ----------------------------------------------------------------------
 
-  blink::WebView* webview_;
+  blink::WebView* webview_ = nullptr;
 
   // Cache the preferred size of the page in order to prevent sending the IPC
   // when layout() recomputes but doesn't actually change sizes.
@@ -689,15 +661,15 @@
 
   // Used to indicate the zoom level to be used during subframe loads, since
   // they should match page zoom level.
-  double page_zoom_level_;
+  double page_zoom_level_ = 0;
 
   // Helper objects ------------------------------------------------------------
 
-  RenderFrameImpl* main_render_frame_;
+  RenderFrameImpl* main_render_frame_ = nullptr;
 
   // Note: RenderViewImpl is pulling double duty: it's the RenderWidget for the
   // "view", but it's also the RenderWidget for the main frame.
-  blink::WebFrameWidget* frame_widget_;
+  blink::WebFrameWidget* frame_widget_ = nullptr;
 
 #if defined(OS_ANDROID)
   // Android Specific ---------------------------------------------------------
@@ -706,16 +678,14 @@
   std::unique_ptr<RendererDateTimePicker> date_time_picker_client_;
 
   // Whether this was a renderer-created or browser-created RenderView.
-  bool was_created_by_renderer_;
+  bool was_created_by_renderer_ = false;
 #endif
 
   // Misc ----------------------------------------------------------------------
 
   // The current directory enumeration callback
   std::map<int, blink::WebFileChooserCompletion*> enumeration_completions_;
-  int enumeration_completion_id_;
-
-  base::Optional<float> device_scale_factor_for_testing_;
+  int enumeration_completion_id_ = 0;
 
   // The SessionStorage namespace that we're assigned to has an ID, and that ID
   // is passed to us upon creation.  WebKit asks for this ID upon first use and
@@ -730,14 +700,12 @@
   // constructors call the AddObservers method of RenderViewImpl.
   std::unique_ptr<StatsCollectionObserver> stats_collection_observer_;
 
-  std::unique_ptr<IdleUserDetector> idle_user_detector_;
-
   blink::WebScopedVirtualTimePauser history_navigation_virtual_time_pauser_;
 
   // Whether lookup of frames in the created RenderView (e.g. lookup via
   // window.open or via <a target=...>) should be renderer-wide (i.e. going
   // beyond the usual opener-relationship-based BrowsingInstance boundaries).
-  bool renderer_wide_named_frame_lookup_;
+  bool renderer_wide_named_frame_lookup_ = false;
 
   // ---------------------------------------------------------------------------
   // ADDING NEW DATA? Please see if it fits appropriately in one of the above
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 398ffad4..fc5366e1 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -61,6 +61,7 @@
 #include "content/renderer/gpu/frame_swap_message_queue.h"
 #include "content/renderer/gpu/layer_tree_view.h"
 #include "content/renderer/gpu/queue_message_swap_promise.h"
+#include "content/renderer/idle_user_detector.h"
 #include "content/renderer/ime_event_guard.h"
 #include "content/renderer/input/main_thread_event_queue.h"
 #include "content/renderer/input/widget_input_handler_manager.h"
@@ -591,6 +592,10 @@
 }
 
 void RenderWidget::CloseForFrame() {
+  if (owner_delegate_) {
+    owner_delegate_->OverrideCloseForWidget();
+    return;
+  }
   OnClose();
 }
 
@@ -645,6 +650,10 @@
   }
 }
 
+void RenderWidget::SetUpIdleUserDetector() {
+  idle_user_detector_ = std::make_unique<IdleUserDetector>();
+}
+
 void RenderWidget::WasSwappedOut() {
   // If we have been swapped out and no one else is using this process,
   // it's safe to exit now.
@@ -762,29 +771,6 @@
          (has_focus_ || for_oopif_);
 }
 
-void RenderWidget::SetWindowRectSynchronously(
-    const gfx::Rect& new_window_rect) {
-  VisualProperties visual_properties;
-  visual_properties.screen_info = screen_info_;
-  visual_properties.new_size = new_window_rect.size();
-  visual_properties.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
-      new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
-  visual_properties.visible_viewport_size = new_window_rect.size();
-  visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
-  visual_properties.display_mode = display_mode_;
-  visual_properties.local_surface_id = local_surface_id_from_parent_;
-  // We are resizing the window from the renderer, so allocate a new
-  // viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  if (layer_tree_view_)
-    layer_tree_view_->RequestNewLocalSurfaceId();
-  SynchronizeVisualProperties(visual_properties);
-
-  view_screen_rect_ = new_window_rect;
-  window_screen_rect_ = new_window_rect;
-  if (!did_show_)
-    initial_rect_ = new_window_rect;
-}
-
 void RenderWidget::OnClose() {
   DCHECK(content::RenderThread::Get());
   if (closing_)
@@ -821,24 +807,72 @@
 }
 
 void RenderWidget::OnSynchronizeVisualProperties(
-    const VisualProperties& params) {
-  gfx::Size old_visible_viewport_size = visible_viewport_size_;
+    const VisualProperties& original_params) {
+  TRACE_EVENT0("renderer", "RenderWidget::OnSynchronizeVisualProperties");
 
-  if (resizing_mode_selector_->ShouldAbortOnResize(this, params)) {
-    return;
+  VisualProperties params = original_params;
+  if (owner_delegate_) {
+    owner_delegate_->ApplyNewSizeForWidget(size_, params.new_size);
+
+    if (display_mode_ != params.display_mode) {
+      display_mode_ = params.display_mode;
+      owner_delegate_->ApplyNewDisplayModeForWidget(params.display_mode);
+    }
+
+    bool auto_resize_mode_changed =
+        auto_resize_mode_ != params.auto_resize_enabled;
+    auto_resize_mode_ = params.auto_resize_enabled;
+    min_size_for_auto_resize_ = params.min_size_for_auto_resize;
+    max_size_for_auto_resize_ = params.max_size_for_auto_resize;
+
+    if (auto_resize_mode_) {
+      gfx::Size min_auto_size = min_size_for_auto_resize_;
+      gfx::Size max_auto_size = max_size_for_auto_resize_;
+      if (compositor_deps_->IsUseZoomForDSFEnabled()) {
+        min_auto_size = gfx::ScaleToCeiledSize(
+            min_auto_size, params.screen_info.device_scale_factor);
+        max_auto_size = gfx::ScaleToCeiledSize(
+            max_auto_size, params.screen_info.device_scale_factor);
+      }
+      owner_delegate_->ApplyAutoResizeLimitsForWidget(min_auto_size,
+                                                      max_auto_size);
+    } else if (auto_resize_mode_changed) {
+      owner_delegate_->DisableAutoResizeForWidget();
+      if (params.new_size.IsEmpty())
+        return;
+    }
+
+    browser_controls_shrink_blink_size_ =
+        params.browser_controls_shrink_blink_size;
+    top_controls_height_ = params.top_controls_height;
+    bottom_controls_height_ = params.bottom_controls_height;
+
+    // TODO(fsamuel): Modifies the |params| that are used for
+    // SynchronizeVisualProperties(), but does not used this modified
+    // device_scale_factor for the auto-resize values, which is probably a bug.
+    if (device_scale_factor_for_testing_) {
+      params.screen_info.device_scale_factor =
+          *device_scale_factor_for_testing_;
+      params.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+          params.new_size, params.screen_info.device_scale_factor);
+    }
   }
 
-  if (screen_metrics_emulator_) {
-    screen_metrics_emulator_->OnSynchronizeVisualProperties(params);
-    return;
+  if (!resizing_mode_selector_->ShouldAbortOnResize(this, params)) {
+    if (screen_metrics_emulator_) {
+      screen_metrics_emulator_->OnSynchronizeVisualProperties(params);
+    } else {
+      gfx::Size old_visible_viewport_size = visible_viewport_size_;
+      SynchronizeVisualProperties(params);
+      if (old_visible_viewport_size != visible_viewport_size_) {
+        for (auto& render_frame : render_frames_)
+          render_frame.DidChangeVisibleViewport();
+      }
+    }
   }
 
-  SynchronizeVisualProperties(params);
-
-  if (old_visible_viewport_size != visible_viewport_size_) {
-    for (auto& render_frame : render_frames_)
-      render_frame.DidChangeVisibleViewport();
-  }
+  if (owner_delegate_ && params.scroll_focused_node_into_view)
+    owner_delegate_->ScrollFocusedNodeIntoViewForWidget();
 }
 
 void RenderWidget::OnEnableDeviceEmulation(
@@ -916,10 +950,6 @@
   Send(new ViewHostMsg_ForceRedrawComplete(routing_id(), snapshot_id));
 }
 
-GURL RenderWidget::GetURLForGraphicsContext3D() {
-  return GURL();
-}
-
 viz::FrameSinkId RenderWidget::GetFrameSinkIdAtPoint(const gfx::Point& point) {
   return input_handler_->GetFrameSinkIdAtPoint(point);
 }
@@ -928,6 +958,13 @@
     const blink::WebCoalescedInputEvent& input_event,
     const ui::LatencyInfo& latency_info,
     HandledEventCallback callback) {
+  if (owner_delegate_ && is_swapped_out_) {
+    std::move(callback).Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, latency_info,
+                            nullptr, base::nullopt);
+    return;
+  }
+  if (idle_user_detector_)
+    idle_user_detector_->ActivityDetected();
   input_handler_->HandleInputEvent(input_event, latency_info,
                                    std::move(callback));
 }
@@ -953,15 +990,21 @@
 
 void RenderWidget::OnSetActive(bool active) {
   if (owner_delegate_)
-    owner_delegate_->SetActive(active);
+    owner_delegate_->SetActiveForWidget(active);
 }
 
 void RenderWidget::OnSetBackgroundOpaque(bool opaque) {
   if (owner_delegate_)
-    owner_delegate_->SetBackgroundOpaque(opaque);
+    owner_delegate_->SetBackgroundOpaqueForWidget(opaque);
 }
 
 void RenderWidget::OnSetFocus(bool enable) {
+  if (owner_delegate_)
+    owner_delegate_->DidReceiveSetFocusEventForWidget();
+  SetFocus(enable);
+}
+
+void RenderWidget::SetFocus(bool enable) {
   has_focus_ = enable;
 
   if (GetWebWidget())
@@ -969,6 +1012,9 @@
 
   for (auto& observer : render_frames_)
     observer.RenderWidgetSetFocus(enable);
+
+  if (owner_delegate_)
+    owner_delegate_->DidChangeFocusForWidget();
 }
 
 void RenderWidget::SetNeedsMainFrame() {
@@ -1052,9 +1098,14 @@
 }
 
 void RenderWidget::DidCommitCompositorFrame() {
+  if (owner_delegate_)
+    owner_delegate_->DidCommitCompositorFrameForWidget();
 }
 
-void RenderWidget::DidCompletePageScaleAnimation() {}
+void RenderWidget::DidCompletePageScaleAnimation() {
+  if (owner_delegate_)
+    owner_delegate_->DidCompletePageScaleAnimationForWidget();
+}
 
 void RenderWidget::DidReceiveCompositorFrameAck() {
 }
@@ -1079,6 +1130,10 @@
 }
 
 void RenderWidget::RequestScheduleAnimation() {
+  if (owner_delegate_) {
+    owner_delegate_->RequestScheduleAnimationForWidget();
+    return;
+  }
   ScheduleAnimation();
 }
 
@@ -1312,7 +1367,7 @@
       gfx::Point(event.PositionInScreen().x, event.PositionInScreen().y);
 
   if (owner_delegate_)
-    return owner_delegate_->RenderWidgetWillHandleMouseEvent(event);
+    return owner_delegate_->RenderWidgetWillHandleMouseEventForWidget(event);
 
   return false;
 }
@@ -1326,7 +1381,14 @@
 }
 
 void RenderWidget::ResizeWebWidget() {
-  GetWebWidget()->Resize(GetSizeForWebWidget());
+  gfx::Size size = GetSizeForWebWidget();
+  if (owner_delegate_) {
+    owner_delegate_->ResizeWebWidgetForWidget(
+        size, top_controls_height_, bottom_controls_height_,
+        browser_controls_shrink_blink_size_);
+    return;
+  }
+  GetWebWidget()->Resize(size);
 }
 
 gfx::Size RenderWidget::GetSizeForWebWidget() const {
@@ -1421,8 +1483,10 @@
 void RenderWidget::SetScreenMetricsEmulationParameters(
     bool enabled,
     const blink::WebDeviceEmulationParams& params) {
-  // This is only supported in RenderView.
-  NOTREACHED();
+  // This is only supported in RenderView, which has an |owner_delegate_|.
+  DCHECK(owner_delegate_);
+  owner_delegate_->SetScreenMetricsEmulationParametersForWidget(enabled,
+                                                                params);
 }
 
 void RenderWidget::SetScreenRects(const gfx::Rect& view_screen_rect,
@@ -1572,13 +1636,22 @@
 // created RenderWidget (i.e., as a blocked popup or as a new tab).
 //
 void RenderWidget::Show(WebNavigationPolicy policy) {
-  DCHECK(!did_show_) << "received extraneous Show call";
+  if (did_show_) {
+    if (owner_delegate_) {
+      // When SupportsMultipleWindows is disabled, popups are reusing
+      // the same view. In some scenarios, this makes blink to call Show()
+      // twice. But otherwise, if it is enabled, we should not visit Show() more
+      // than once.
+      DCHECK(!owner_delegate_->SupportsMultipleWindowsForWidget());
+    } else {
+      DCHECK(!did_show_) << "received extraneous Show call";
+    }
+    return;
+  }
+
   DCHECK(routing_id_ != MSG_ROUTING_NONE);
   DCHECK(show_callback_);
 
-  if (did_show_)
-    return;
-
   did_show_ = true;
 
   // The opener is responsible for actually showing this widget.
@@ -1626,6 +1699,8 @@
   screen_metrics_emulator_.reset();
   CloseWebWidget();
   layer_tree_view_.reset();
+  if (owner_delegate_)
+    owner_delegate_->DidCloseWidget();
 }
 
 void RenderWidget::CloseWebWidget() {
@@ -1895,6 +1970,29 @@
     UpdateWebViewWithDeviceScaleFactor();
 }
 
+void RenderWidget::SetWindowRectSynchronously(
+    const gfx::Rect& new_window_rect) {
+  VisualProperties visual_properties;
+  visual_properties.screen_info = screen_info_;
+  visual_properties.new_size = new_window_rect.size();
+  visual_properties.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+      new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
+  visual_properties.visible_viewport_size = new_window_rect.size();
+  visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+  visual_properties.display_mode = display_mode_;
+  visual_properties.local_surface_id = local_surface_id_from_parent_;
+  // We are resizing the window from the renderer, so allocate a new
+  // viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  if (layer_tree_view_)
+    layer_tree_view_->RequestNewLocalSurfaceId();
+  SynchronizeVisualProperties(visual_properties);
+
+  view_screen_rect_ = new_window_rect;
+  window_screen_rect_ = new_window_rect;
+  if (!did_show_)
+    initial_rect_ = new_window_rect;
+}
+
 void RenderWidget::UpdateCaptureSequenceNumber(
     uint32_t capture_sequence_number) {
   if (capture_sequence_number == last_capture_sequence_number_)
@@ -2149,6 +2247,12 @@
   }
 }
 
+GURL RenderWidget::GetURLForGraphicsContext3D() {
+  if (owner_delegate_)
+    return owner_delegate_->GetURLForGraphicsContext3DForWidget();
+  return GURL();
+}
+
 void RenderWidget::SetHidden(bool hidden) {
   if (is_hidden_ == hidden)
     return;
@@ -2401,9 +2505,12 @@
 
 void RenderWidget::DidHandleGestureEvent(const WebGestureEvent& event,
                                          bool event_cancelled) {
-#if defined(OS_ANDROID) || defined(USE_AURA)
-  if (event_cancelled)
+  if (event_cancelled) {
+    // The |owner_delegate_| doesn't need to hear about cancelled events.
     return;
+  }
+
+#if defined(OS_ANDROID) || defined(USE_AURA)
   if (event.GetType() == WebInputEvent::kGestureTap) {
     ShowVirtualKeyboard();
   } else if (event.GetType() == WebInputEvent::kGestureLongPress) {
@@ -2417,19 +2524,22 @@
 // TODO(ananta): Piggyback off existing IPCs to communicate this information,
 // crbug/420130.
 #if defined(OS_WIN)
-  if (event.GetType() != blink::WebGestureEvent::kGestureTap)
-    return;
+  if (event.GetType() == blink::WebGestureEvent::kGestureTap) {
+    // TODO(estade): hit test the event against focused node to make sure
+    // the tap actually hit the focused node.
+    blink::WebInputMethodController* controller = GetInputMethodController();
+    blink::WebTextInputType text_input_type =
+        controller ? controller->TextInputType() : blink::kWebTextInputTypeNone;
 
-  // TODO(estade): hit test the event against focused node to make sure
-  // the tap actually hit the focused node.
-  blink::WebInputMethodController* controller = GetInputMethodController();
-  blink::WebTextInputType text_input_type =
-      controller ? controller->TextInputType() : blink::kWebTextInputTypeNone;
-
-  Send(new ViewHostMsg_FocusedNodeTouched(
-      routing_id_, text_input_type != blink::kWebTextInputTypeNone));
+    Send(new ViewHostMsg_FocusedNodeTouched(
+        routing_id_, text_input_type != blink::kWebTextInputTypeNone));
+  }
 #endif
 #endif
+
+  // The |owner_delegate_| gets to respond to handling gestures last.
+  if (owner_delegate_)
+    owner_delegate_->DidHandleGestureEventForWidget(event);
 }
 
 void RenderWidget::DidOverscroll(
@@ -2879,10 +2989,6 @@
     layer_tree_view_->SetVisible(true);
 }
 
-void RenderWidget::SetHandlingInputEventForTesting(bool handling_input_event) {
-  input_handler_->set_handling_input_event(handling_input_event);
-}
-
 void RenderWidget::HasTouchEventHandlers(bool has_handlers) {
   if (has_touch_handlers_ && *has_touch_handlers_ == has_handlers)
     return;
@@ -3001,6 +3107,12 @@
 }
 
 blink::WebWidget* RenderWidget::GetWebWidget() const {
+  if (owner_delegate_) {
+    blink::WebWidget* delegate_widget =
+        owner_delegate_->GetWebWidgetForWidget();
+    if (delegate_widget)
+      return delegate_widget;
+  }
   return webwidget_internal_;
 }
 
@@ -3038,6 +3150,89 @@
          layer_tree_view_->IsSurfaceSynchronizationEnabled();
 }
 
+void RenderWidget::SetHandlingInputEventForTesting(bool handling_input_event) {
+  input_handler_->set_handling_input_event(handling_input_event);
+}
+
+void RenderWidget::SetDeviceScaleFactorForTesting(float factor) {
+  device_scale_factor_for_testing_ = factor;
+
+  VisualProperties visual_properties;
+  visual_properties.screen_info = screen_info_;
+  visual_properties.screen_info.device_scale_factor = factor;
+  visual_properties.new_size = size();
+  visual_properties.visible_viewport_size = visible_viewport_size_;
+  visual_properties.compositor_viewport_pixel_size =
+      gfx::ScaleToCeiledSize(size(), factor);
+  visual_properties.browser_controls_shrink_blink_size = false;
+  visual_properties.top_controls_height = 0.f;
+  visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+  visual_properties.display_mode = display_mode_;
+  visual_properties.local_surface_id = local_surface_id_from_parent_;
+  // We are changing the device scale factor from the renderer, so allocate a
+  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  if (layer_tree_view_)
+    layer_tree_view_->RequestNewLocalSurfaceId();
+
+  OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::SetDeviceColorSpaceForTesting(
+    const gfx::ColorSpace& color_space) {
+  VisualProperties visual_properties;
+  visual_properties.screen_info = screen_info_;
+  visual_properties.screen_info.color_space = color_space;
+  visual_properties.new_size = size();
+  visual_properties.visible_viewport_size = visible_viewport_size_;
+  visual_properties.compositor_viewport_pixel_size =
+      compositor_viewport_pixel_size_;
+  visual_properties.browser_controls_shrink_blink_size = false;
+  visual_properties.top_controls_height = 0.f;
+  visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+  visual_properties.display_mode = display_mode_;
+  visual_properties.local_surface_id = local_surface_id_from_parent_;
+  // We are changing the device color space from the renderer, so allocate a
+  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  if (layer_tree_view_)
+    layer_tree_view_->RequestNewLocalSurfaceId();
+  OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::SetWindowRectSynchronouslyForTesting(
+    const gfx::Rect& new_window_rect) {
+  SetWindowRectSynchronously(new_window_rect);
+}
+
+void RenderWidget::EnableAutoResizeForTesting(const gfx::Size& min_size,
+                                              const gfx::Size& max_size) {
+  VisualProperties visual_properties;
+  visual_properties.auto_resize_enabled = true;
+  visual_properties.min_size_for_auto_resize = min_size;
+  visual_properties.max_size_for_auto_resize = max_size;
+  visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>(
+      viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
+  OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderWidget::DisableAutoResizeForTesting(const gfx::Size& new_size) {
+  if (!auto_resize_mode_)
+    return;
+
+  VisualProperties visual_properties;
+  visual_properties.auto_resize_enabled = false;
+  visual_properties.screen_info = screen_info_;
+  visual_properties.new_size = new_size;
+  visual_properties.compositor_viewport_pixel_size =
+      compositor_viewport_pixel_size_;
+  visual_properties.browser_controls_shrink_blink_size =
+      browser_controls_shrink_blink_size_;
+  visual_properties.top_controls_height = top_controls_height_;
+  visual_properties.visible_viewport_size = visible_viewport_size_;
+  visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+  visual_properties.display_mode = display_mode_;
+  OnSynchronizeVisualProperties(visual_properties);
+}
+
 void RenderWidget::UpdateURLForCompositorUkm() {
   DCHECK(layer_tree_view_);
   blink::WebFrameWidget* frame_widget = GetFrameWidget();
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index e2c9b6f..fecd455 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -94,6 +94,7 @@
 }
 
 namespace gfx {
+class ColorSpace;
 class Range;
 }
 
@@ -106,6 +107,7 @@
 class CompositorDependencies;
 class ExternalPopupMenu;
 class FrameSwapMessageQueue;
+class IdleUserDetector;
 class ImeEventGuard;
 class LayerTreeView;
 class MainThreadEventQueue;
@@ -179,16 +181,14 @@
   static RenderWidget* FromRoutingID(int32_t routing_id);
 
   // Closes a RenderWidget that was created by |CreateForFrame|.
-  // TODO(avi): De-virtualize this once RenderViewImpl has-a RenderWidget.
-  // https://crbug.com/545684
-  virtual void CloseForFrame();
+  void CloseForFrame();
 
   int32_t routing_id() const { return routing_id_; }
 
   CompositorDependencies* compositor_deps() const { return compositor_deps_; }
 
   // This can return nullptr while the RenderWidget is closing.
-  virtual blink::WebWidget* GetWebWidget() const;
+  blink::WebWidget* GetWebWidget() const;
 
   // Returns the current instance of WebInputMethodController which is to be
   // used for IME related tasks. This instance corresponds to the one from
@@ -218,7 +218,6 @@
     DCHECK(!owner_delegate_);
     owner_delegate_ = owner_delegate;
   }
-
   RenderWidgetOwnerDelegate* owner_delegate() const { return owner_delegate_; }
 
   // Sets whether this RenderWidget has been swapped out to be displayed by
@@ -226,7 +225,6 @@
   // sent (only ACKs) and the process is free to exit when there are no other
   // active RenderWidgets.
   void SetSwappedOut(bool is_swapped_out);
-
   bool is_swapped_out() const { return is_swapped_out_; }
 
   // Manage edit commands to be used for the next keyboard event.
@@ -342,7 +340,7 @@
 
   // Override point to obtain that the current input method state and caret
   // position.
-  virtual ui::TextInputType GetTextInputType();
+  ui::TextInputType GetTextInputType();
 
   // Internal helper that generates the LayerTreeSettings to be given to the
   // compositor in StartCompositor().
@@ -374,8 +372,6 @@
     return *input_handler_;
   }
 
-  void SetHandlingInputEventForTesting(bool handling_input_event);
-
   // Deliveres |message| together with compositor state change updates. The
   // exact behavior depends on |policy|.
   // This mechanism is not a drop-in replacement for IPC: messages sent this way
@@ -401,7 +397,7 @@
   // the new value will be sent to the browser process.
   void UpdateSelectionBounds();
 
-  virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
+  void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
 
   void OnShowHostContextMenu(ContextMenuParams* params);
 
@@ -413,6 +409,12 @@
   // the browser even if the composition info is not changed.
   void UpdateCompositionInfo(bool immediate_request);
 
+  // Override point to obtain that the current composition character bounds.
+  // In the case of surrogate pairs, the character is treated as two characters:
+  // the bounds for first character is actual one, and the bounds for second
+  // character is zero width rectangle.
+  void GetCompositionCharacterBounds(std::vector<gfx::Rect>* character_bounds);
+
   // Called when the Widget has changed size as a result of an auto-resize.
   void DidAutoResize(const gfx::Size& new_size);
 
@@ -436,7 +438,6 @@
   // Helper to convert |point| using ConvertWindowToViewport().
   gfx::PointF ConvertWindowPointToViewport(const gfx::PointF& point);
   gfx::Point ConvertWindowPointToViewport(const gfx::Point& point);
-
   uint32_t GetContentSourceId();
   void DidNavigate();
 
@@ -471,7 +472,7 @@
   scoped_refptr<MainThreadEventQueue> GetInputEventQueue();
 
   void OnSetActive(bool active);
-  virtual void OnSetFocus(bool enable);
+  void OnSetFocus(bool enable);
   void OnSetBackgroundOpaque(bool opaque);
   void OnMouseCaptureLost();
   void OnCursorVisibilityChange(bool is_visible);
@@ -488,6 +489,10 @@
                        int relative_cursor_pos);
   void OnImeFinishComposingText(bool keep_selection);
 
+  // This does the actual focus change, but is called in more situations than
+  // just as an IPC message.
+  void SetFocus(bool enable);
+
   // Called by the browser process to update text input state.
   void OnRequestTextInputStateUpdate();
 
@@ -512,6 +517,14 @@
 
   bool IsSurfaceSynchronizationEnabled() const;
 
+  void SetHandlingInputEventForTesting(bool handling_input_event);
+  void SetDeviceScaleFactorForTesting(float factor);
+  void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
+  void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
+  void EnableAutoResizeForTesting(const gfx::Size& min_size,
+                                  const gfx::Size& max_size);
+  void DisableAutoResizeForTesting(const gfx::Size& new_size);
+
   base::WeakPtr<RenderWidget> AsWeakPtr();
 
  protected:
@@ -537,6 +550,7 @@
                scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                mojom::WidgetRequest widget_request = nullptr);
 
+  // Avoid making RenderWidget other than as a refptr.
   ~RenderWidget() override;
 
   static blink::WebFrameWidget* CreateWebFrameWidget(
@@ -551,6 +565,10 @@
   // should be null if show() won't be triggered for this widget.
   void Init(ShowCallback show_callback, blink::WebWidget* web_widget);
 
+  // Idle user detector is optionally set up and destroyed during
+  // initialization/teardown.
+  void SetUpIdleUserDetector();
+
   // Allows the process to exit once the unload handler has finished, if there
   // are no other active RenderWidgets.
   void WasSwappedOut();
@@ -559,7 +577,7 @@
   void NotifyOnClose();
 
   gfx::Size GetSizeForWebWidget() const;
-  virtual void ResizeWebWidget();
+  void ResizeWebWidget();
 
   // Close the underlying WebWidget and stop the compositor.
   virtual void Close();
@@ -572,8 +590,6 @@
   // Update the web view's device scale factor.
   void UpdateWebViewWithDeviceScaleFactor();
 
-  // Used to force the size of a window when running layout tests.
-  void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
   void SetExternalPopupOriginAdjustmentsForEmulation(
       ExternalPopupMenu* popup,
@@ -591,16 +607,16 @@
   virtual void OnSynchronizeVisualProperties(const VisualProperties& params);
   void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
   void OnDisableDeviceEmulation();
-  virtual void OnWasHidden();
-  virtual void OnWasShown(bool needs_repainting,
-                          base::TimeTicks show_request_timestamp);
+  void OnWasHidden();
+  void OnWasShown(bool needs_repainting,
+                  base::TimeTicks show_request_timestamp);
   void OnCreateVideoAck(int32_t video_id);
   void OnUpdateVideoAck(int32_t video_id);
   void OnRequestSetBoundsAck();
   void OnForceRedraw(int snapshot_id);
   // Request from browser to show context menu.
-  virtual void OnShowContextMenu(ui::MenuSourceType source_type,
-                                 const gfx::Point& location);
+  void OnShowContextMenu(ui::MenuSourceType source_type,
+                         const gfx::Point& location);
 
   void OnSetTextDirection(blink::WebTextDirection direction);
   void OnGetFPS();
@@ -634,14 +650,13 @@
                          const gfx::PointF& screen_point,
                          blink::WebDragOperation drag_operation);
   void OnDragSourceSystemDragEnded();
-
   void OnOrientationChange();
 
-  // Override points to notify derived classes that a paint has happened.
-  // DidInitiatePaint happens when that has completed, and subsequent rendering
-  // won't affect the painted content.
+  // Notify subclasses that we initiated the paint operation.
   virtual void DidInitiatePaint() {}
 
+  // Gets the current URL or a placeholder constant for creating 3d contexts and
+  // attributing them back to a URL.
   virtual GURL GetURLForGraphicsContext3D();
 
   // Sets the "hidden" state of this widget.  All accesses to is_hidden_ should
@@ -665,16 +680,9 @@
       scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
       int source_frame_number);
 
-  // Override point to obtain that the current composition character bounds.
-  // In the case of surrogate pairs, the character is treated as two characters:
-  // the bounds for first character is actual one, and the bounds for second
-  // character is zero width rectangle.
-  virtual void GetCompositionCharacterBounds(
-      std::vector<gfx::Rect>* character_bounds);
-
   // Returns the range of the text that is being composed or the selection if
   // the composition does not exist.
-  virtual void GetCompositionRange(gfx::Range* range);
+  void GetCompositionRange(gfx::Range* range);
 
   // Returns true if the composition range or composition character bounds
   // should be sent to the browser process.
@@ -684,7 +692,7 @@
 
   // Override point to obtain that the current input method state about
   // composition text.
-  virtual bool CanComposeInline();
+  bool CanComposeInline();
 
   // Set the pending window rect.
   // Because the real render_widget is hosted in another process, there is
@@ -736,6 +744,8 @@
   // messages.
   WebCursor current_cursor_;
 
+  base::Optional<float> device_scale_factor_for_testing_;
+
   // The size of the RenderWidget in DIPs. This may differ from
   // |compositor_viewport_pixel_size_| in the following (and possibly other)
   // cases: * On Android, for top and bottom controls * On OOPIF, due to
@@ -906,6 +916,9 @@
       const gfx::Size& new_compositor_viewport_pixel_size,
       const ScreenInfo& new_screen_info);
 
+  // Used to force the size of a window when running layout tests.
+  void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
+
   void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
 
   // A variant of Send but is fatal if it fails. The browser may
@@ -980,6 +993,14 @@
   bool first_update_visual_state_after_hidden_;
   base::TimeTicks was_shown_time_;
 
+  // Whether or not Blink's viewport size should be shrunk by the height of the
+  // URL-bar.
+  bool browser_controls_shrink_blink_size_ = false;
+  // The height of the browser top controls.
+  float top_controls_height_ = 0.f;
+  // The height of the browser bottom controls.
+  float bottom_controls_height_ = 0.f;
+
   // This is initialized to zero and is incremented on each non-same-page
   // navigation commit by RenderFrameImpl. At that time it is sent to the
   // compositor so that it can tag compositor frames, and RenderFrameImpl is
@@ -996,8 +1017,10 @@
   scoped_refptr<MainThreadEventQueue> input_event_queue_;
 
   mojo::Binding<mojom::Widget> widget_binding_;
-
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  // IdleUserDetector is setup optionally on RenderWidget by its creator, so may
+  // be null.
+  std::unique_ptr<IdleUserDetector> idle_user_detector_;
 
   gfx::Rect compositor_visible_rect_;
 
diff --git a/content/renderer/render_widget_owner_delegate.h b/content/renderer/render_widget_owner_delegate.h
index 8438e9ac..2365a39 100644
--- a/content/renderer/render_widget_owner_delegate.h
+++ b/content/renderer/render_widget_owner_delegate.h
@@ -21,15 +21,98 @@
 //  are disentangled; see https://crbug.com/583347 and https://crbug.com/478281.
 class CONTENT_EXPORT RenderWidgetOwnerDelegate {
  public:
-  // As in RenderWidgetInputHandlerDelegate.
-  virtual bool RenderWidgetWillHandleMouseEvent(
+  // Returns the WebWidget if the delegate has one. Otherwise it returns null,
+  // and RenderWidget will fall back to its own WebWidget.
+  virtual blink::WebWidget* GetWebWidgetForWidget() const = 0;
+
+  // As in RenderWidgetInputHandlerDelegate. Return true if the event was
+  // handled.
+  virtual bool RenderWidgetWillHandleMouseEventForWidget(
       const blink::WebMouseEvent& event) = 0;
 
   // See comment in RenderWidgetHost::SetActive().
-  virtual void SetActive(bool active) = 0;
+  virtual void SetActiveForWidget(bool active) = 0;
 
   // See comment in RenderWidgetHostImpl::SetBackgroundOpaque().
-  virtual void SetBackgroundOpaque(bool opaque) = 0;
+  virtual void SetBackgroundOpaqueForWidget(bool opaque) = 0;
+
+  // Returns whether multiple windows are allowed for the widget. If true, then
+  // Show() may be called more than once.
+  virtual bool SupportsMultipleWindowsForWidget() = 0;
+
+  // Called after RenderWidget services WebWidgetClient::DidHandleGestureEvent()
+  // if the event was not cancelled.
+  virtual void DidHandleGestureEventForWidget(
+      const blink::WebGestureEvent& event) = 0;
+
+  // ==================================
+  // These methods called during closing of a RenderWidget.
+  //
+  // Called when RenderWidget is closed that was "created for a frame".
+  virtual void OverrideCloseForWidget() = 0;
+  // Called after closing the RenderWidget and destroying the WebView.
+  virtual void DidCloseWidget() = 0;
+  // ==================================
+
+  // ==================================
+  // These methods called during handling of a SynchronizeVisualProperties
+  // message to handle updating state on the delegate.
+  //
+  // Called during handling a SynchronizeVisualProperties message, with the new
+  // size that will be applied to the RenderWidget. The size in the RenderWidget
+  // has not yet changed when this method is called, as it is changed later.
+  virtual void ApplyNewSizeForWidget(const gfx::Size& old_size,
+                                     const gfx::Size& new_size) = 0;
+  // Called during handling a SynchronizeVisualProperties message, with the new
+  // display mode that will be applied to the RenderWidget. The display mode in
+  // the RenderWidget is already changed when this method is called.
+  virtual void ApplyNewDisplayModeForWidget(
+      const blink::WebDisplayMode& new_display_mode) = 0;
+  // Called during handling a SynchronizeVisualProperties message, if auto
+  // resize is enabled, with the new auto size limits.
+  virtual void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
+                                              const gfx::Size& max_size) = 0;
+  // Called during handling a SynchronizeVisualProperties message, if auto
+  // resize was enabled but is being disabled.
+  virtual void DisableAutoResizeForWidget() = 0;
+  // Called during handling a SynchronizeVisualProperties message, if the
+  // message informed that the focused node should be scrolled into view.
+  virtual void ScrollFocusedNodeIntoViewForWidget() = 0;
+  // ==================================
+
+  // Called when RenderWidget receives a SetFocus event.
+  virtual void DidReceiveSetFocusEventForWidget() = 0;
+
+  // Called after RenderWidget changes focus.
+  virtual void DidChangeFocusForWidget() = 0;
+
+  // Called to get the current URL if it exists or a hardcoded fallback.
+  virtual GURL GetURLForGraphicsContext3DForWidget() = 0;
+
+  // Called when the RenderWidget handles
+  // LayerTreeViewDelegate::DidCommitCompositorFrame().
+  virtual void DidCommitCompositorFrameForWidget() = 0;
+
+  // Called when the RenderWidget handles
+  // LayerTreeViewDelegate::DidCompletePageScaleAnimation().
+  virtual void DidCompletePageScaleAnimationForWidget() = 0;
+
+  // Called to resize the WebWidget, so the delegate may change how resize
+  // happens.
+  virtual void ResizeWebWidgetForWidget(
+      const gfx::Size& size,
+      float top_controls_height,
+      float bottom_controls_height,
+      bool browser_controls_shrink_blink_size) = 0;
+
+  // Called to schedule an animation on the WebWidgetClient.
+  virtual void RequestScheduleAnimationForWidget() = 0;
+
+  // Called when RenderWidget services RenderWidgetScreenMetricsEmulatorDelegate
+  // SetScreenMetricsEmulationParameters().
+  virtual void SetScreenMetricsEmulationParametersForWidget(
+      bool enabled,
+      const blink::WebDeviceEmulationParams& params) = 0;
 
  protected:
   virtual ~RenderWidgetOwnerDelegate() {}
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index f91cc4b..ede9e6ca 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -33,6 +33,7 @@
 #include "content/child/thread_safe_sender.h"
 #include "content/common/frame_messages.h"
 #include "content/common/gpu_stream_constants.h"
+#include "content/common/indexed_db/indexed_db.mojom.h"
 #include "content/common/render_message_filter.mojom.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -74,8 +75,6 @@
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ipc/ipc_sync_message_filter.h"
 #include "media/audio/audio_output_device.h"
 #include "media/blink/webcontentdecryptionmodule_impl.h"
 #include "media/filters/stream_parser_factory.h"
@@ -258,12 +257,8 @@
                      ->GetServiceManagerConnection()
                      ->GetConnector()
                      ->Clone();
-    sync_message_filter_ = RenderThreadImpl::current()->sync_message_filter();
     thread_safe_sender_ = RenderThreadImpl::current()->thread_safe_sender();
     blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
-    web_idb_factory_.reset(new WebIDBFactoryImpl(
-        sync_message_filter_,
-        RenderThreadImpl::current()->GetIOTaskRunner().get()));
 #if defined(OS_LINUX)
     font_loader_ = sk_make_sp<font_service::FontLoader>(connector_.get());
     SkFontConfigInterface::SetGlobal(font_loader_);
@@ -293,6 +288,16 @@
 
   GetInterfaceProvider()->GetInterface(
       mojo::MakeRequest(&web_database_host_info_));
+
+  // RenderThread may not exist in some tests.
+  if (RenderThreadImpl::current()) {
+    indexed_db::mojom::FactoryPtrInfo web_idb_factory_host_info;
+    GetInterfaceProvider()->GetInterface(
+        mojo::MakeRequest(&web_idb_factory_host_info));
+    web_idb_factory_.reset(new WebIDBFactoryImpl(
+        std::move(web_idb_factory_host_info),
+        RenderThreadImpl::current()->GetIOTaskRunner()));
+  }
 }
 
 RendererBlinkPlatformImpl::~RendererBlinkPlatformImpl() {
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 98afd27..54f59bc 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -34,10 +34,6 @@
 #include "third_party/skia/include/core/SkRefCnt.h"           // nogncheck
 #endif
 
-namespace IPC {
-class SyncMessageFilter;
-}
-
 namespace blink {
 namespace scheduler {
 class WebThreadScheduler;
@@ -274,7 +270,6 @@
   std::unique_ptr<blink::WebBlobRegistry> blob_registry_;
 
   scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
-  scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
   scoped_refptr<ThreadSafeSender> thread_safe_sender_;
 
   std::unique_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
diff --git a/content/test/data/frame_tree/page_with_janky_frame.html b/content/test/data/frame_tree/page_with_janky_frame.html
deleted file mode 100644
index 25c8737b..0000000
--- a/content/test/data/frame_tree/page_with_janky_frame.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<style>
-.container {
-  touch-action: pan-y;
-}
-iframe {
-  position:absolute;
-  top: 50px;
-  left: 50px;
-  width: 100px;
-  height: 100px;
-}
-</style>
-<html>
-<body>
-<div class="container">
-  <iframe src="/cross-site/baz.com/page_with_touch_start_janking_main_thread.html"></iframe>
-</div>
-This page contains a positioned cross-origin iframe.
-</body>
-</html>
diff --git a/content/test/data/page_with_touch_start_janking_main_thread.html b/content/test/data/page_with_touch_start_janking_main_thread.html
deleted file mode 100644
index 7480d1fd..0000000
--- a/content/test/data/page_with_touch_start_janking_main_thread.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-<style>
-#janktest{
-  width: 1000px;
-  height: 10000px;
-}
-</style>
-<body onload='setup()'>
- <div id="janktest"></div>
-</body>
-<script>
-function setup() {
-  janktest.ontouchstart = function() {
-    var end = performance.now() + 1200;
-    while (performance.now() < end) ;
-  };
-}
-</script>
-</html>
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index b8dbec2c..75199c7 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -464,13 +464,18 @@
 
 void ForceResizeRenderView(RenderView* render_view,
                            const WebSize& new_size) {
-  RenderViewImpl* render_view_impl = static_cast<RenderViewImpl*>(render_view);
-  render_view_impl->ForceResizeForTesting(new_size);
+  auto* render_view_impl = static_cast<RenderViewImpl*>(render_view);
+  gfx::Rect window_rect(render_view_impl->RootWindowRect().x,
+                        render_view_impl->RootWindowRect().y, new_size.width,
+                        new_size.height);
+  RenderWidget* render_widget = render_view_impl->GetWidget();
+  render_widget->SetWindowRectSynchronouslyForTesting(window_rect);
 }
 
 void SetDeviceScaleFactor(RenderView* render_view, float factor) {
-  static_cast<RenderViewImpl*>(render_view)->
-      SetDeviceScaleFactorForTesting(factor);
+  RenderWidget* render_widget =
+      static_cast<RenderViewImpl*>(render_view)->GetWidget();
+  render_widget->SetDeviceScaleFactorForTesting(factor);
 }
 
 float GetWindowToViewportScale(RenderView* render_view) {
@@ -507,8 +512,9 @@
 
 void SetDeviceColorSpace(RenderView* render_view,
                          const gfx::ColorSpace& color_space) {
-  static_cast<RenderViewImpl*>(render_view)
-      ->SetDeviceColorSpaceForTesting(color_space);
+  RenderWidget* render_widget =
+      static_cast<RenderViewImpl*>(render_view)->GetWidget();
+  render_widget->SetDeviceColorSpaceForTesting(color_space);
 }
 
 void SetTestBluetoothScanDuration(BluetoothTestScanDurationSetting setting) {
@@ -534,13 +540,15 @@
 void EnableAutoResizeMode(RenderView* render_view,
                           const WebSize& min_size,
                           const WebSize& max_size) {
-  static_cast<RenderViewImpl*>(render_view)->
-      EnableAutoResizeForTesting(min_size, max_size);
+  RenderWidget* render_widget =
+      static_cast<RenderViewImpl*>(render_view)->GetWidget();
+  render_widget->EnableAutoResizeForTesting(min_size, max_size);
 }
 
 void DisableAutoResizeMode(RenderView* render_view, const WebSize& new_size) {
-  static_cast<RenderViewImpl*>(render_view)->
-      DisableAutoResizeForTesting(new_size);
+  RenderWidget* render_widget =
+      static_cast<RenderViewImpl*>(render_view)->GetWidget();
+  render_widget->DisableAutoResizeForTesting(new_size);
 }
 
 void SchedulerRunIdleTasks(base::OnceClosure callback) {
diff --git a/content/test/mock_platform_notification_service.cc b/content/test/mock_platform_notification_service.cc
index 28dc265..b345a74 100644
--- a/content/test/mock_platform_notification_service.cc
+++ b/content/test/mock_platform_notification_service.cc
@@ -100,6 +100,10 @@
   return ++next_persistent_notification_id_;
 }
 
+void MockPlatformNotificationService::RecordNotificationUkmEvent(
+    BrowserContext* browser_context,
+    const NotificationDatabaseData& data) {}
+
 void MockPlatformNotificationService::SimulateClick(
     const std::string& title,
     const base::Optional<int>& action_index,
diff --git a/content/test/mock_platform_notification_service.h b/content/test/mock_platform_notification_service.h
index baf24f9..8741d95e 100644
--- a/content/test/mock_platform_notification_service.h
+++ b/content/test/mock_platform_notification_service.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
+#include "content/public/browser/notification_database_data.h"
 #include "content/public/browser/platform_notification_service.h"
 #include "url/gurl.h"
 
@@ -63,6 +64,9 @@
       const DisplayedNotificationsCallback& callback) override;
   int64_t ReadNextPersistentNotificationId(
       BrowserContext* browser_context) override;
+  void RecordNotificationUkmEvent(
+      BrowserContext* browser_context,
+      const NotificationDatabaseData& data) override;
 
  private:
   // Structure to represent the information of a persistent notification.
diff --git a/extensions/browser/content_verifier/content_hash.cc b/extensions/browser/content_verifier/content_hash.cc
index 18aa94f..4cc291e 100644
--- a/extensions/browser/content_verifier/content_hash.cc
+++ b/extensions/browser/content_verifier/content_hash.cc
@@ -47,10 +47,11 @@
     bool delete_invalid_file) {
   base::AssertBlockingAllowed();
   DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
-  auto verified_contents = std::make_unique<VerifiedContents>(key.verifier_key);
   base::FilePath verified_contents_path =
       file_util::GetVerifiedContentsPath(key.extension_root);
-  if (!verified_contents->InitFrom(verified_contents_path)) {
+  std::unique_ptr<VerifiedContents> verified_contents =
+      VerifiedContents::Create(key.verifier_key, verified_contents_path);
+  if (!verified_contents) {
     if (delete_invalid_file &&
         !base::DeleteFile(verified_contents_path, false)) {
       LOG(WARNING) << "Failed to delete " << verified_contents_path.value();
diff --git a/extensions/browser/verified_contents.cc b/extensions/browser/verified_contents.cc
index 654a4dd..1d84d3a 100644
--- a/extensions/browser/verified_contents.cc
+++ b/extensions/browser/verified_contents.cc
@@ -10,6 +10,7 @@
 #include "base/base64url.h"
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "base/timer/elapsed_timer.h"
@@ -142,39 +143,44 @@
 //     }
 //   ]
 // }
-bool VerifiedContents::InitFrom(const base::FilePath& path) {
+// static.
+std::unique_ptr<VerifiedContents> VerifiedContents::Create(
+    base::span<const uint8_t> public_key,
+    const base::FilePath& path) {
   ScopedUMARecorder uma_recorder;
+  // Note: VerifiedContents constructor is private.
+  auto verified_contents = base::WrapUnique(new VerifiedContents(public_key));
   std::string payload;
-  if (!GetPayload(path, &payload))
-    return false;
+  if (!verified_contents->GetPayload(path, &payload))
+    return nullptr;
 
   std::unique_ptr<base::Value> value(base::JSONReader::Read(payload));
   if (!value.get() || !value->is_dict())
-    return false;
+    return nullptr;
   DictionaryValue* dictionary = static_cast<DictionaryValue*>(value.get());
 
   std::string item_id;
   if (!dictionary->GetString(kItemIdKey, &item_id) ||
       !crx_file::id_util::IdIsValid(item_id)) {
-    return false;
+    return nullptr;
   }
-  extension_id_ = item_id;
+  verified_contents->extension_id_ = item_id;
 
   std::string version_string;
   if (!dictionary->GetString(kItemVersionKey, &version_string))
-    return false;
-  version_ = base::Version(version_string);
-  if (!version_.IsValid())
-    return false;
+    return nullptr;
+  verified_contents->version_ = base::Version(version_string);
+  if (!verified_contents->version_.IsValid())
+    return nullptr;
 
-  ListValue* hashes_list = NULL;
+  ListValue* hashes_list = nullptr;
   if (!dictionary->GetList(kContentHashesKey, &hashes_list))
-    return false;
+    return nullptr;
 
   for (size_t i = 0; i < hashes_list->GetSize(); i++) {
-    DictionaryValue* hashes = NULL;
+    DictionaryValue* hashes = nullptr;
     if (!hashes_list->GetDictionary(i, &hashes))
-      return false;
+      return nullptr;
     std::string format;
     if (!hashes->GetString(kFormatKey, &format) || format != kTreeHash)
       continue;
@@ -183,23 +189,23 @@
     int hash_block_size = 0;
     if (!hashes->GetInteger(kBlockSizeKey, &block_size) ||
         !hashes->GetInteger(kHashBlockSizeKey, &hash_block_size)) {
-      return false;
+      return nullptr;
     }
-    block_size_ = block_size;
+    verified_contents->block_size_ = block_size;
 
     // We don't support using a different block_size and hash_block_size at
     // the moment.
-    if (block_size_ != hash_block_size)
-      return false;
+    if (verified_contents->block_size_ != hash_block_size)
+      return nullptr;
 
-    ListValue* files = NULL;
+    ListValue* files = nullptr;
     if (!hashes->GetList(kFilesKey, &files))
-      return false;
+      return nullptr;
 
-    for (size_t j = 0; j < files->GetSize(); j++) {
-      DictionaryValue* data = NULL;
+    for (size_t j = 0; j < files->GetSize(); ++j) {
+      DictionaryValue* data = nullptr;
       if (!files->GetDictionary(j, &data))
-        return false;
+        return nullptr;
       std::string file_path_string;
       std::string encoded_root_hash;
       std::string root_hash;
@@ -209,13 +215,13 @@
           !base::Base64UrlDecode(encoded_root_hash,
                                  base::Base64UrlDecodePolicy::IGNORE_PADDING,
                                  &root_hash)) {
-        return false;
+        return nullptr;
       }
       base::FilePath file_path =
           base::FilePath::FromUTF8Unsafe(file_path_string);
       base::FilePath::StringType lowercase_file_path =
           base::ToLowerASCII(file_path.value());
-      RootHashes::iterator i = root_hashes_.insert(
+      RootHashes::iterator i = verified_contents->root_hashes_.insert(
           std::make_pair(lowercase_file_path, std::string()));
       i->second.swap(root_hash);
 
@@ -225,14 +231,15 @@
       // HasTreeHashRoot() and TreeHashRootEquals().
       base::FilePath::StringType trimmed_path;
       if (TrimDotSpaceSuffix(lowercase_file_path, &trimmed_path))
-        root_hashes_.insert(std::make_pair(trimmed_path, i->second));
+        verified_contents->root_hashes_.insert(
+            std::make_pair(trimmed_path, i->second));
 #endif  // defined(OS_WIN)
     }
 
     break;
   }
   uma_recorder.RecordSuccess();
-  return true;
+  return verified_contents;
 }
 
 bool VerifiedContents::HasTreeHashRoot(
diff --git a/extensions/browser/verified_contents.h b/extensions/browser/verified_contents.h
index 0688c5d..cf24d3c 100644
--- a/extensions/browser/verified_contents.h
+++ b/extensions/browser/verified_contents.h
@@ -24,13 +24,16 @@
 // corruption of extension files on local disk.
 class VerifiedContents {
  public:
-  // Note: the public_key must remain valid for the lifetime of this object.
-  explicit VerifiedContents(base::span<const uint8_t> public_key);
   ~VerifiedContents();
 
-  // Returns true if we successfully parsed the verified_contents.json file at
-  // |path| and validated the enclosed signature. The
-  bool InitFrom(const base::FilePath& path);
+  // Returns verified contents after successfully parsing verified_contents.json
+  // file at |path| and validating the enclosed signature. Returns nullptr on
+  // failure.
+  // Note: |public_key| must remain valid for the lifetime of the returned
+  // object.
+  static std::unique_ptr<VerifiedContents> Create(
+      base::span<const uint8_t> public_key,
+      const base::FilePath& path);
 
   int block_size() const { return block_size_; }
   const std::string& extension_id() const { return extension_id_; }
@@ -46,6 +49,9 @@
   bool valid_signature() { return valid_signature_; }
 
  private:
+  // Note: the public_key must remain valid for the lifetime of this object.
+  explicit VerifiedContents(base::span<const uint8_t> public_key);
+
   // Returns the base64url-decoded "payload" field from the json at |path|, if
   // the signature was valid.
   bool GetPayload(const base::FilePath& path, std::string* payload);
diff --git a/extensions/browser/verified_contents_unittest.cc b/extensions/browser/verified_contents_unittest.cc
index 88e305e..53b733f4 100644
--- a/extensions/browser/verified_contents_unittest.cc
+++ b/extensions/browser/verified_contents_unittest.cc
@@ -71,13 +71,10 @@
   if (!GetPublicKey(path.AppendASCII(kPublicKeyPem), &public_key))
     return nullptr;
 
-  auto contents = std::make_unique<VerifiedContents>(
-      base::as_bytes(base::make_span(public_key)));
   base::FilePath verified_contents_path =
       path.AppendASCII(verified_contents_filename);
-  if (!contents->InitFrom(verified_contents_path))
-    return nullptr;
-  return contents;
+  return VerifiedContents::Create(base::as_bytes(base::make_span(public_key)),
+                                  verified_contents_path);
 }
 
 }  // namespace
diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS
index 61d8e6e..aa743ad 100644
--- a/extensions/renderer/DEPS
+++ b/extensions/renderer/DEPS
@@ -40,4 +40,7 @@
     # For net::IsLocalhost.
     "+net/base/url_util.h",
   ],
+  "extension_throttle_unittest.cc": [
+    "+net/url_request/redirect_info.h",
+  ],
 }
diff --git a/extensions/renderer/extension_throttle_manager.cc b/extensions/renderer/extension_throttle_manager.cc
index 38316d47..f03661eb 100644
--- a/extensions/renderer/extension_throttle_manager.cc
+++ b/extensions/renderer/extension_throttle_manager.cc
@@ -101,13 +101,12 @@
     int request_load_flags,
     const net::RedirectInfo& redirect_info) {
   {
+    // An entry GC when requests are outstanding can purge entries so check
+    // before use.
     base::AutoLock auto_lock(lock_);
-    const std::string url_id = GetIdFromUrl(request_url);
-    ExtensionThrottleEntry* entry = url_entries_[url_id].get();
-    DCHECK(entry);
-    // TODO(crbug.com/866798) Temporarily checking for null ptr.
-    if (entry)
-      entry->UpdateWithResponse(redirect_info.status_code);
+    auto it = url_entries_.find(GetIdFromUrl(request_url));
+    if (it != url_entries_.end())
+      it->second->UpdateWithResponse(redirect_info.status_code);
   }
   return ShouldRejectRequest(redirect_info.new_url, request_load_flags);
 }
@@ -116,13 +115,12 @@
     const GURL& response_url,
     const network::ResourceResponseHead& response_head) {
   if (response_head.network_accessed) {
+    // An entry GC when requests are outstanding can purge entries so check
+    // before use.
     base::AutoLock auto_lock(lock_);
-    const std::string url_id = GetIdFromUrl(response_url);
-    ExtensionThrottleEntry* entry = url_entries_[url_id].get();
-    DCHECK(entry);
-    // TODO(crbug.com/866798) Temporarily checking for null ptr.
-    if (entry)
-      entry->UpdateWithResponse(response_head.headers->response_code());
+    auto it = url_entries_.find(GetIdFromUrl(response_url));
+    if (it != url_entries_.end())
+      it->second->UpdateWithResponse(response_head.headers->response_code());
   }
 }
 
diff --git a/extensions/renderer/extension_throttle_unittest.cc b/extensions/renderer/extension_throttle_unittest.cc
index 4aa3b97..8673032 100644
--- a/extensions/renderer/extension_throttle_unittest.cc
+++ b/extensions/renderer/extension_throttle_unittest.cc
@@ -12,6 +12,8 @@
 #include "extensions/renderer/extension_throttle_manager.h"
 #include "extensions/renderer/extension_throttle_test_support.h"
 #include "net/base/load_flags.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/resource_response.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::TimeDelta;
@@ -405,4 +407,20 @@
   }
 }
 
+TEST(ExtensionThrottleManagerTest, UseAfterNetworkChange) {
+  MockExtensionThrottleManager manager;
+  const GURL test_url("http://www.example.com/");
+  EXPECT_FALSE(manager.ShouldRejectRequest(test_url, net::LOAD_NORMAL));
+  manager.SetOnline(/*is_online=*/false);
+  manager.SetOnline(/*is_online=*/true);
+  net::RedirectInfo redirect_info;
+  redirect_info.new_url = GURL("http://www.newsite.com");
+  EXPECT_FALSE(
+      manager.ShouldRejectRedirect(test_url, net::LOAD_NORMAL, redirect_info));
+  manager.SetOnline(/*is_online=*/false);
+  manager.SetOnline(/*is_online=*/true);
+  network::ResourceResponseHead response_head;
+  manager.WillProcessResponse(redirect_info.new_url, response_head);
+}
+
 }  // namespace extensions
diff --git a/extensions/strings/extensions_strings_ar.xtb b/extensions/strings/extensions_strings_ar.xtb
index 0b54150b..0a7de818 100644
--- a/extensions/strings/extensions_strings_ar.xtb
+++ b/extensions/strings/extensions_strings_ar.xtb
@@ -56,6 +56,7 @@
 <translation id="7003844668372540529">المنتج غير معروف <ph name="PRODUCT_ID" /> من <ph name="VENDOR_NAME" /></translation>
 <translation id="7068383018033524534">ملف البيان غير صالح</translation>
 <translation id="7217838517480956708">يطلب مشرف هذا الجهاز تثبيت <ph name="EXTENSION_NAME" />. لا يمكن إزالتها أو تعديلها.</translation>
+<translation id="7939686037314084444">تعذّر تحميل الإضافة بشكلٍ صحيح. وقد لا تتمكن الإضافة من اعتراض طلبات الشبكة.</translation>
 <translation id="7972881773422714442">الخيارات: <ph name="EXTENSIONOPTIONS_TAG_NAME" /></translation>
 <translation id="8035920974645200807">الكاميرا الأمامية للمستخدم</translation>
 <translation id="8047248493720652249">تعذّرت هذه الإضافة في تسمية التنزيل "<ph name="ATTEMPTED_FILENAME" />" نظرًا لأن هناك إضافة أخرى (<ph name="EXTENSION_NAME" />) قد حددت اسم ملف آخر "<ph name="ACTUAL_FILENAME" />".</translation>
diff --git a/extensions/strings/extensions_strings_bn.xtb b/extensions/strings/extensions_strings_bn.xtb
index 0081ca9..f082ba5 100644
--- a/extensions/strings/extensions_strings_bn.xtb
+++ b/extensions/strings/extensions_strings_bn.xtb
@@ -56,6 +56,7 @@
 <translation id="7003844668372540529"><ph name="VENDOR_NAME" /> এর থেকে অজানা পণ্য <ph name="PRODUCT_ID" /></translation>
 <translation id="7068383018033524534">ম্যানিফেস্ট ফাইলটি ভুল</translation>
 <translation id="7217838517480956708">এই মেশিনের প্রশাসকের <ph name="EXTENSION_NAME" /> ইনস্টল করার প্রয়োজন৷ এটি সরানো অথবা সংশোধন করা যাবে না৷</translation>
+<translation id="7939686037314084444">এই এক্সটেনশনটি সঠিকভাবে লোড করা যায়নি। এটি নেটওয়ার্ক অনুরোধগুলি হয়ত আটকাতে পারেনি।</translation>
 <translation id="7972881773422714442">বিকল্পগুলি: <ph name="EXTENSIONOPTIONS_TAG_NAME" /></translation>
 <translation id="8035920974645200807">ব্যবহারকারীর দিকে মুখ করা</translation>
 <translation id="8047248493720652249">এই এক্সটেনশানটি ডাউনলোড "<ph name="ATTEMPTED_FILENAME" />" এর নাম দিতে ব্যর্থ হয়েছে কারণ অন্য এক্সটেনশান (<ph name="EXTENSION_NAME" />) একটি ভিন্ন ফাইল নাম "<ph name="ACTUAL_FILENAME" />" নির্ধারণ করেছে৷</translation>
diff --git a/extensions/strings/extensions_strings_ru.xtb b/extensions/strings/extensions_strings_ru.xtb
index e520885..e88af98 100644
--- a/extensions/strings/extensions_strings_ru.xtb
+++ b/extensions/strings/extensions_strings_ru.xtb
@@ -56,6 +56,7 @@
 <translation id="7003844668372540529">Неизвестный продукт <ph name="PRODUCT_ID" /> от <ph name="VENDOR_NAME" /></translation>
 <translation id="7068383018033524534">Недопустимый файл манифеста</translation>
 <translation id="7217838517480956708">Удаление и изменение расширения <ph name="EXTENSION_NAME" /> на этом компьютере запрещено администратором.</translation>
+<translation id="7939686037314084444">Не удалось корректно загрузить расширение. Перехват запросов сети может быть нарушен.</translation>
 <translation id="7972881773422714442">Options: <ph name="EXTENSIONOPTIONS_TAG_NAME" /></translation>
 <translation id="8035920974645200807">Фронтальная</translation>
 <translation id="8047248493720652249">Данному расширению не удалось присвоить скачанному файлу имя "<ph name="ATTEMPTED_FILENAME" />", поскольку другое расширение (<ph name="EXTENSION_NAME" />) уже присвоило ему другое имя: "<ph name="ACTUAL_FILENAME" />".</translation>
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 5e597d7..1b98c564 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1024,7 +1024,9 @@
                                        GLbitfield flags);
 
   // Callback for async SwapBuffers.
-  void FinishAsyncSwapBuffers(uint64_t swap_id, gfx::SwapResult result);
+  void FinishAsyncSwapBuffers(uint64_t swap_id,
+                              gfx::SwapResult result,
+                              std::unique_ptr<gfx::GpuFence>);
   void FinishSwapBuffers(gfx::SwapResult result);
 
   void DoCommitOverlayPlanes(uint64_t swap_id, GLbitfield flags);
@@ -16008,9 +16010,14 @@
   ExitCommandProcessingEarly();
 }
 
-void GLES2DecoderImpl::FinishAsyncSwapBuffers(uint64_t swap_id,
-                                              gfx::SwapResult result) {
+void GLES2DecoderImpl::FinishAsyncSwapBuffers(
+    uint64_t swap_id,
+    gfx::SwapResult result,
+    std::unique_ptr<gfx::GpuFence> gpu_fence) {
   TRACE_EVENT_ASYNC_END0("gpu", "AsyncSwapBuffers", swap_id);
+  // Handling of the out-fence should have already happened before reaching
+  // this function, so we don't expect to get a valid fence here.
+  DCHECK(!gpu_fence);
 
   FinishSwapBuffers(result);
 }
@@ -16044,8 +16051,8 @@
   if (supports_async_swap_) {
     client_->OnSwapBuffers(swap_id, flags);
     surface_->CommitOverlayPlanesAsync(
-        base::Bind(&GLES2DecoderImpl::FinishSwapBuffers,
-                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&GLES2DecoderImpl::FinishAsyncSwapBuffers,
+                   weak_ptr_factory_.GetWeakPtr(), swap_id),
         base::DoNothing());
   } else {
     client_->OnSwapBuffers(swap_id, flags);
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index bf9a384..db45afcc 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -1830,18 +1830,18 @@
       if (!level_infos[level_index].estimated_size)
         continue;
 
+      std::string level_dump_name = base::StringPrintf(
+          "%s/face_%d/level_%d", dump_name.c_str(), face_index, level_index);
+
       // If a level has a GLImage, ask the GLImage to dump itself.
       // If a level does not have a GLImage bound to it, then dump the
       // texture allocation also as the storage is not provided by the
       // GLImage in that case.
       if (level_infos[level_index].image) {
-        level_infos[level_index].image->OnMemoryDump(
-            pmd, client_tracing_id,
-            base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(),
-                               face_index, level_index));
+        level_infos[level_index].image->OnMemoryDump(pmd, client_tracing_id,
+                                                     level_dump_name);
       } else {
-        MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(base::StringPrintf(
-            "%s/face_%d/level_%d", dump_name.c_str(), face_index, level_index));
+        MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(level_dump_name);
         dump->AddScalar(
             MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes,
             static_cast<uint64_t>(level_infos[level_index].estimated_size));
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index d9d588a..c9721b8 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2963,6 +2963,18 @@
       "features": [
         "gl_clear_broken"
       ]
+    },
+    {
+      "id": 272,
+      "cr_bugs": [858879],
+      "description": "A deleted query id for GL_TIMESTAMP cannot be reused for other query targets",
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": "Qualcomm.*",
+      "features": [
+        "disable_timestamp_queries"
+      ]
     }
   ]
 }
diff --git a/gpu/ipc/gl_in_process_context.cc b/gpu/ipc/gl_in_process_context.cc
index 2316013..2c583527 100644
--- a/gpu/ipc/gl_in_process_context.cc
+++ b/gpu/ipc/gl_in_process_context.cc
@@ -34,22 +34,7 @@
 
 GLInProcessContext::GLInProcessContext() = default;
 
-GLInProcessContext::~GLInProcessContext() {
-  if (gles2_implementation_) {
-    // First flush the context to ensure that any pending frees of resources
-    // are completed. Otherwise, if this context is part of a share group,
-    // those resources might leak. Also, any remaining side effects of commands
-    // issued on this context might not be visible to other contexts in the
-    // share group.
-    gles2_implementation_->Flush();
-
-    gles2_implementation_.reset();
-  }
-
-  transfer_buffer_.reset();
-  gles2_helper_.reset();
-  command_buffer_.reset();
-}
+GLInProcessContext::~GLInProcessContext() = default;
 
 const Capabilities& GLInProcessContext::GetCapabilities() const {
   return command_buffer_->GetCapabilities();
diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h
index b8694c9..905dd4f8 100644
--- a/gpu/ipc/gl_in_process_context.h
+++ b/gpu/ipc/gl_in_process_context.h
@@ -66,10 +66,11 @@
       const InProcessCommandBuffer::UpdateVSyncParametersCallback& callback);
 
  private:
+  // The destruction order is important, don't reorder these member variables.
+  std::unique_ptr<InProcessCommandBuffer> command_buffer_;
   std::unique_ptr<gles2::GLES2CmdHelper> gles2_helper_;
   std::unique_ptr<TransferBuffer> transfer_buffer_;
   std::unique_ptr<gles2::GLES2Implementation> gles2_implementation_;
-  std::unique_ptr<InProcessCommandBuffer> command_buffer_;
 
   DISALLOW_COPY_AND_ASSIGN(GLInProcessContext);
 };
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
index 98d3d82..85f28721 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
@@ -167,10 +167,12 @@
     LOG(ERROR) << "Failed to create IOSurface mach port.";
   }
 
-  gfx::GenericSharedMemoryId image_id(++next_anonymous_image_id_);
   scoped_refptr<gl::GLImageIOSurface> image(
       gl::GLImageIOSurface::Create(size, internalformat));
-  if (!image->Initialize(io_surface.get(), image_id, format)) {
+  // Use an invalid GMB id so that we can differentiate between anonymous and
+  // shared GMBs by using gfx::GenericSharedMemoryId::is_valid().
+  if (!image->Initialize(io_surface.get(), gfx::GenericSharedMemoryId(),
+                         format)) {
     DLOG(ERROR) << "Failed to initialize anonymous GLImage.";
     return scoped_refptr<gl::GLImage>();
   }
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
index 96f27f00..62e3ed21 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
@@ -72,9 +72,6 @@
   IOSurfaceMap io_surfaces_;
   base::Lock io_surfaces_lock_;
 
-  // Assign unique ids to anonymous images to differentiate in memory dumps.
-  int next_anonymous_image_id_ = 1;
-
   DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryIOSurface);
 };
 
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.cc b/gpu/ipc/service/pass_through_image_transport_surface.cc
index 8cbe603..8827552 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.cc
+++ b/gpu/ipc/service/pass_through_image_transport_surface.cc
@@ -220,10 +220,17 @@
 void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
     GLSurface::SwapCompletionCallback callback,
     gfx::SwapResponse response,
-    gfx::SwapResult result) {
+    gfx::SwapResult result,
+    std::unique_ptr<gfx::GpuFence> gpu_fence) {
+  // TODO(afrantzis): It's probably not ideal to introduce a wait here.
+  // However, since this is a temporary step to maintain existing behavior
+  // until we are ready to expose the gpu_fence further, and fences are only
+  // enabled with a flag, this should be fine for now.
+  if (gpu_fence)
+    gpu_fence->Wait();
   response.result = result;
   FinishSwapBuffers(std::move(response));
-  callback.Run(result);
+  callback.Run(result, nullptr);
 }
 
 void PassThroughImageTransportSurface::BufferPresented(
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.h b/gpu/ipc/service/pass_through_image_transport_surface.h
index b177e41..279bfa39 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.h
+++ b/gpu/ipc/service/pass_through_image_transport_surface.h
@@ -64,7 +64,8 @@
   void FinishSwapBuffers(gfx::SwapResponse response);
   void FinishSwapBuffersAsync(GLSurface::SwapCompletionCallback callback,
                               gfx::SwapResponse response,
-                              gfx::SwapResult result);
+                              gfx::SwapResult result,
+                              std::unique_ptr<gfx::GpuFence> gpu_fence);
 
   void BufferPresented(const GLSurface::PresentationCallback& callback,
                        const gfx::PresentationFeedback& feedback);
diff --git a/headless/test/data/protocol/helpers/virtual-time-controller.js b/headless/test/data/protocol/helpers/virtual-time-controller.js
index 45482489..92cfa27 100644
--- a/headless/test/data/protocol/helpers/virtual-time-controller.js
+++ b/headless/test/data/protocol/helpers/virtual-time-controller.js
@@ -74,7 +74,15 @@
   }
 
   /**
-   * Revokes any granted virtual time, resulting in no more animatino frames
+   * Retrieves current frame time to be used in beginFrame calls.
+   * @return {number} Frame time in milliseconds.
+   */
+  currentFrameTime() {
+    return this.virtualTimeBase_ + this.totalElapsedTime_;
+  }
+
+  /**
+   * Revokes any granted virtual time, resulting in no more animation frames
    * being issued and final OnExpired call being made.
    */
   stopVirtualTimeGracefully() {
diff --git a/headless/test/data/protocol/sanity/renderer-canvas-expected.txt b/headless/test/data/protocol/sanity/renderer-canvas-expected.txt
new file mode 100644
index 0000000..3742fdf
--- /dev/null
+++ b/headless/test/data/protocol/sanity/renderer-canvas-expected.txt
@@ -0,0 +1,5 @@
+Tests renderer: canvas.
+requested url: http://example.com/
+Screenshot size: 800 x 600
+rgba @(0,0): 255,255,255,255
+rgba @(25,25): 255,0,0,255
\ No newline at end of file
diff --git a/headless/test/data/protocol/sanity/renderer-canvas.js b/headless/test/data/protocol/sanity/renderer-canvas.js
new file mode 100644
index 0000000..3f6d5145
--- /dev/null
+++ b/headless/test/data/protocol/sanity/renderer-canvas.js
@@ -0,0 +1,82 @@
+// 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.
+
+(async function(testRunner) {
+  let {page, session, dp} = await testRunner.startBlank(
+      'Tests renderer: canvas.');
+
+  // Open the test page in a new tab with BeginFrameControl enabled.
+  await testTargetPage(await session.createTargetInNewContext(
+      800, 600, 'about:blank', true));
+
+  async function testTargetPage(session) {
+    dp = session.protocol;
+    await dp.Runtime.enable();
+    await dp.HeadlessExperimental.enable();
+
+    let RendererTestHelper =
+        await testRunner.loadScript('../helpers/renderer-test-helper.js');
+    let {httpInterceptor, frameNavigationHelper, virtualTimeController} =
+        await (new RendererTestHelper(testRunner, dp, page)).init();
+
+    httpInterceptor.addResponse(
+        `http://example.com/`,
+        `<html>
+          <body>
+            <canvas id="test_canvas" width="100" height="100"
+                    style="position:absolute;left:0px;top:0px">
+              Oops!  Canvas not supported!
+            </canvas>
+            <script>
+              var context = document.getElementById("test_canvas").
+                            getContext("2d");
+              context.fillStyle = "rgb(255,0,0)";
+              context.fillRect(25, 25, 50, 50);
+            </script>
+          </body>
+        </html>`);
+
+    await virtualTimeController.grantInitialTime(500, 1000,
+      null,
+      async () => {
+        const frameTimeTicks = virtualTimeController.currentFrameTime();
+        const screenshotData =
+            (await dp.HeadlessExperimental.beginFrame(
+                {frameTimeTicks, screenshot: {format: 'png'}}))
+            .result.screenshotData;
+        await logScreenShotData(screenshotData);
+        testRunner.completeTest();
+      }
+    );
+
+    function logScreenShotData(pngBase64) {
+      const image = new Image();
+
+      let callback;
+      let promise = new Promise(fulfill => callback = fulfill);
+      image.onload = function() {
+        testRunner.log(`Screenshot size: `
+            + `${image.naturalWidth} x ${image.naturalHeight}`);
+        const canvas = document.createElement('canvas');
+        canvas.width = image.naturalWidth;
+        canvas.height = image.naturalHeight;
+        const ctx = canvas.getContext('2d');
+        ctx.drawImage(image, 0, 0);
+        // Expected rgba @(0,0): 255,255,255,255
+        const rgba = ctx.getImageData(0, 0, 1, 1).data;
+        testRunner.log(`rgba @(0,0): ${rgba}`);
+        // Expected rgba @(25,25): 255,0,0,255
+        const rgba2 = ctx.getImageData(25, 25, 1, 1).data;
+        testRunner.log(`rgba @(25,25): ${rgba2}`);
+        callback();
+      }
+
+      image.src = `data:image/png;base64,${pngBase64}`;
+
+      return promise;
+    }
+
+    await frameNavigationHelper.navigate('http://example.com/');
+  }
+})
diff --git a/headless/test/data/protocol/sanity/renderer-css-url-filter-expected.txt b/headless/test/data/protocol/sanity/renderer-css-url-filter-expected.txt
new file mode 100644
index 0000000..b8e97a0
--- /dev/null
+++ b/headless/test/data/protocol/sanity/renderer-css-url-filter-expected.txt
@@ -0,0 +1,30 @@
+Tests renderer: canvas.
+requested url: http://www.example.com/
+requested url: http://www.example.com/circle.svg
+requested url: http://www.example.com/blur.svg
+Screenshot size: 100 x 100
+rgba @(0,0): 163,163,163,255
+rgba @(1,1): 222,225,231,255
+rgba @(2,2): 221,232,251,255
+rgba @(3,3): 206,222,249,255
+rgba @(4,4): 255,255,255,255
+rgba @(5,5): 255,255,255,255
+rgba @(6,6): 201,218,245,255
+rgba @(7,7): 198,216,244,255
+rgba @(8,8): 197,214,243,255
+rgba @(9,9): 191,210,236,255
+rgba @(10,10): 152,194,170,255
+rgba @(11,11): 174,215,161,255
+rgba @(12,12): 255,255,255,255
+rgba @(13,13): 135,191,136,255
+rgba @(14,14): 141,190,140,255
+rgba @(15,15): 138,139,139,255
+rgba @(16,16): 255,255,255,255
+rgba @(17,17): 255,255,255,255
+rgba @(18,18): 255,255,255,255
+rgba @(19,19): 255,255,255,255
+rgba @(20,20): 255,255,255,255
+rgba @(21,21): 255,255,255,255
+rgba @(22,22): 255,255,255,255
+rgba @(23,23): 255,255,255,255
+rgba @(24,24): 255,255,255,255
\ No newline at end of file
diff --git a/headless/test/data/protocol/sanity/renderer-css-url-filter.js b/headless/test/data/protocol/sanity/renderer-css-url-filter.js
new file mode 100644
index 0000000..72a1a49
--- /dev/null
+++ b/headless/test/data/protocol/sanity/renderer-css-url-filter.js
@@ -0,0 +1,99 @@
+// 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.
+
+(async function(testRunner) {
+  let {page, session, dp} = await testRunner.startBlank(
+      'Tests renderer: canvas.');
+
+  // Open the test page in a new tab with BeginFrameControl enabled.
+  await testTargetPage(await session.createTargetInNewContext(
+      100, 100, 'about:blank', true));
+
+  // Ensures that "filter: url(...)" does not get into an infinite style update
+  // loop.
+  async function testTargetPage(session) {
+    dp = session.protocol;
+    await dp.Runtime.enable();
+    await dp.HeadlessExperimental.enable();
+
+    let RendererTestHelper =
+        await testRunner.loadScript('../helpers/renderer-test-helper.js');
+    let {httpInterceptor, frameNavigationHelper, virtualTimeController} =
+        await (new RendererTestHelper(testRunner, dp, page)).init();
+
+    // The image from circle.svg will be drawn with the blur from blur.svg.
+    httpInterceptor.addResponse(
+        `http://www.example.com/`,
+        `<!DOCTYPE html>
+        <style>
+          body { margin: 0; }
+          img {
+            -webkit-filter: url(blur.svg#blur);
+            filter: url(blur.svg#blur);
+          }
+        </style>
+        <img src="circle.svg">`);
+
+    // Just a normal image.
+    httpInterceptor.addResponse(
+        `http://www.example.com/circle.svg`,
+        `<svg width="100" height="100" version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+          xmlns:xlink="http://www.w3.org/1999/xlink">
+          <circle cx="50" cy="50" r="50" fill="green" />
+        </svg>`);
+
+    // A blur filter stored inside an svg file.
+    httpInterceptor.addResponse(
+        `http://www.example.com/blur.svg`,
+        `<svg width="100" height="100" version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+            xmlns:xlink="http://www.w3.org/1999/xlink">
+          <filter id="blur">
+            <feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
+          </filter>
+        </svg>`);
+
+    await virtualTimeController.grantInitialTime(500, 1000,
+      null,
+      async () => {
+        const frameTimeTicks = virtualTimeController.currentFrameTime();
+        const screenshotData =
+            (await dp.HeadlessExperimental.beginFrame(
+                {frameTimeTicks, screenshot: {format: 'png'}}))
+            .result.screenshotData;
+        await logScreenShotData(screenshotData);
+        testRunner.completeTest();
+      }
+    );
+
+    function logScreenShotData(pngBase64) {
+      const image = new Image();
+
+      let callback;
+      let promise = new Promise(fulfill => callback = fulfill);
+      image.onload = function() {
+        testRunner.log(`Screenshot size: `
+            + `${image.naturalWidth} x ${image.naturalHeight}`);
+        const canvas = document.createElement('canvas');
+        canvas.width = image.naturalWidth;
+        canvas.height = image.naturalHeight;
+        const ctx = canvas.getContext('2d');
+        ctx.drawImage(image, 0, 0);
+        for (let n = 0; n < 25; ++n) {
+          const rgba = ctx.getImageData(n, n, 1, 1).data;
+          testRunner.log(`rgba @(${n},${n}): ${rgba}`);
+        }
+
+        callback();
+      }
+
+      image.src = `data:image/png;base64,${pngBase64}`;
+
+      return promise;
+    }
+
+    await frameNavigationHelper.navigate('http://www.example.com/');
+  }
+})
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc
index f6b38e92..b609778 100644
--- a/headless/test/headless_protocol_browsertest.cc
+++ b/headless/test/headless_protocol_browsertest.cc
@@ -341,5 +341,8 @@
 HEADLESS_PROTOCOL_COMPOSITOR_TEST(
     RendererClientRedirectChainNoJs,
     "sanity/renderer-client-redirect-chain-no-js.js");
+HEADLESS_PROTOCOL_COMPOSITOR_TEST(RendererCssUrlFilter,
+                                  "sanity/renderer-css-url-filter.js");
+HEADLESS_PROTOCOL_COMPOSITOR_TEST(RendererCanvas, "sanity/renderer-canvas.js");
 
 }  // namespace headless
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index da96b98..3d0bf44 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -1937,8 +1937,22 @@
           ->SetSnapshotCoalescingEnabled(false);
     }));
 
-    SnapshotTabHelper::FromWebState(currentTab.webState)
-        ->UpdateSnapshot(/*with_overlays=*/true, /*visible_frame_only=*/true);
+    // Do not take a snapshot if the web state is loading, since it will be
+    // stale.
+    if (currentTab.webState->IsLoading()) {
+      SnapshotTabHelper::FromWebState(currentTab.webState)->RemoveSnapshot();
+    } else {
+      UIImage* snapshot = SnapshotTabHelper::FromWebState(currentTab.webState)
+                              ->UpdateSnapshot(/*with_overlays=*/true,
+                                               /*visible_frame_only=*/true);
+      // TODO(crbug.com/711455) : Snapshot generation can fail for certain
+      // websites that have video somewhere on the page. If the snapshot
+      // generation fails, the stale snapshot should be removed so as not to
+      // display an old snapshot.
+      if (snapshot == SnapshotTabHelper::GetDefaultSnapshotImage()) {
+        SnapshotTabHelper::FromWebState(currentTab.webState)->RemoveSnapshot();
+      }
+    }
   }
 
   if (!_tabSwitcher) {
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_de.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_de.xtb
index 29bccf0..997c3da 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_de.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_de.xtb
@@ -33,7 +33,7 @@
 <translation id="5945387852661427312">Sie melden sich mit einem von <ph name="DOMAIN" /> verwalteten Konto an und geben dem Administrator der Domain Kontrolle über Ihre Chromium-Daten. Die Daten werden diesem Konto dauerhaft zugeordnet. Wenn Sie sich von Chromium abmelden, werden Ihre Daten auf dem Gerät gelöscht, bleiben jedoch in Ihrem Google-Konto erhalten.</translation>
 <translation id="6068866989048414399">Chromium-Nutzungsbedingungen</translation>
 <translation id="6268381023930128611">Von Chromium abmelden?</translation>
-<translation id="641451971369018375">Mit Google kommunizieren, um das Surferlebnis und Chromium zu verbessern</translation>
+<translation id="641451971369018375">Funktionen nutzen, die helfen, Chrome für Sie noch besser zu machen</translation>
 <translation id="6424492062988593837">Chromium ist jetzt noch besser! Es ist eine neue Version verfügbar.</translation>
 <translation id="6604711459180487467">Profitieren Sie von einer besseren Nutzererfahrung in Chromium auf Grundlage Ihres Standorts.</translation>
 <translation id="6626296268883197964">Durch die Verwendung dieser App stimmen Sie den <ph name="BEGIN_LINK_TOS" />Nutzungsbedingungen<ph name="END_LINK_TOS" /> und <ph name="BEGIN_LINK_PRIVACY" />Datenschutzhinweisen<ph name="END_LINK_PRIVACY" /> von Chromium zu.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb
index 9dce227..012c131 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_id.xtb
@@ -15,7 +15,7 @@
 <translation id="2178608107313874732">Chromium saat ini tidak dapat menggunakan kamera</translation>
 <translation id="2195025571279539885">Ingin Chromium menawarkan untuk menerjemahkan halaman berbahasa <ph name="LANGUAGE_NAME" /> dari situs ini saat Anda mengunjunginya lagi?</translation>
 <translation id="2647554856022461007">Chromium dapat mengunakan layanan web agar pengalaman mengakses internet lebih menyenangkan. Anda dapat memilih untuk menonaktifkan layanan ini. <ph name="BEGIN_LINK" />Pelajari lebih lanjut<ph name="END_LINK" /></translation>
-<translation id="2687023731466035790">Dapatkan perangkat smart Google di Chromium</translation>
+<translation id="2687023731466035790">Dapatkan kecanggihan Google di Chromium</translation>
 <translation id="2730884209570016437">Chromium tidak dapat menggunakan kamera karena sedang digunakan aplikasi lain</translation>
 <translation id="3256316712990552818">Disalin ke Chromium</translation>
 <translation id="3413120535237193088">Agar bookmark tersedia di semua perangkat Anda, masuk ke Chromium.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-CN.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-CN.xtb
index a28083f9..f8e4264a 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_zh-CN.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_zh-CN.xtb
@@ -4,7 +4,7 @@
 <translation id="102360288709523007">将使用情况统计信息和崩溃报告发送给 Google,帮助我们完善 Chromium。</translation>
 <translation id="1185134272377778587">关于 Chromium</translation>
 <translation id="1289966288285062467">Chromium 隐私权声明</translation>
-<translation id="1341317949260424055">通过将系统信息和使用情况数据发送给 Google 来改进 Chromium 并提高其安全性</translation>
+<translation id="1341317949260424055">将系统信息和使用情况数据发送给 Google,帮助改进 Chromium 并提高其安全性</translation>
 <translation id="1472013873724362412">无法在 Chromium 上登录您的帐号。请与您的网域管理员联系,或使用普通的 Google 帐号登录。</translation>
 <translation id="1736662517232558588">已清除 Chromium 数据</translation>
 <translation id="1838412507805038478">Chromium 已证实:此网站的证书是由 <ph name="ISSUER" /> 签发的。</translation>
@@ -49,7 +49,7 @@
 <translation id="8175055321229419309">提示:<ph name="BEGIN_LINK" />将 Chromium 移到 Dock 中<ph name="END_LINK" /></translation>
 <translation id="8252885722420466166">Chromium 可根据您的位置信息为您提供更好的 Google 产品使用体验。</translation>
 <translation id="8353224596138547809">您希望 Chromium 保存您在此网站上使用的密码吗?</translation>
-<translation id="8508544542427105412">您随时可以自定义<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />。Google 可能会根据您所访问网站中的内容、浏览器互动行为和活动对 Chromium 以及 Google 服务(例如翻译、搜索和广告)进行个性化设置。</translation>
+<translation id="8508544542427105412">您随时可以自定义<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />。Google 可能会根据您访问的网站上的内容、您在浏览器中的互动行为和活动,为您提供个性化的 Chromium 体验和其他 Google 服务体验(例如翻译、搜索和广告)。</translation>
 <translation id="8586442755830160949">版权所有<ph name="YEAR" /> The Chromium Authors。保留所有权利。</translation>
 <translation id="8809780021347235332">要保存图片,请点按“设置”以允许 Chromium 使用您的照片</translation>
 <translation id="9022552996538154597">登录 Chromium</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_de.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_de.xtb
index 484961f4..f9983cb 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_de.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_de.xtb
@@ -1,7 +1,7 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="de">
-<translation id="114721135501989771">Chrome intelligent nutzen mit Google</translation>
+<translation id="114721135501989771">Chrome cleverer nutzen – dank Google</translation>
 <translation id="1326317727527857210">Melden Sie sich in Chrome an, um Tabs von Ihren anderen Geräten abzurufen.</translation>
 <translation id="1759842336958782510">Chrome</translation>
 <translation id="1816764564654397850">Chrome-Datenschutzhinweise</translation>
@@ -10,11 +10,11 @@
 <translation id="2334084861041072223">Copyright <ph name="YEAR" /> Google Inc. Alle Rechte vorbehalten.</translation>
 <translation id="2342981853652716282">Melden Sie sich in Chrome an, um Daten wie Lesezeichen und Passwörter auf allen Ihren Geräten zu nutzen.</translation>
 <translation id="2347208864470321755">Wenn diese Funktion aktiviert ist, bietet Chrome an, Seiten in anderen Sprachen mithilfe von Google Übersetzer zu übersetzen. <ph name="BEGIN_LINK" />Weitere Informationen<ph name="END_LINK" /></translation>
-<translation id="2436117022029368436">Mit Google kommunizieren, um das Surferlebnis und Chrome zu verbessern</translation>
+<translation id="2436117022029368436">Funktionen nutzen, die helfen, Chrome für Sie noch besser zu machen</translation>
 <translation id="2441696206556358796">Speichern Sie Bilder, indem Sie auf "Einstellungen" tippen und zulassen, dass Ihre Fotos in Chrome verwendet werden.</translation>
 <translation id="2576431527583832481">Chrome ist jetzt noch besser! Es ist eine neue Version verfügbar.</translation>
 <translation id="257708665678654955">Soll Google Chrome beim nächsten Mal eine Übersetzung von Seiten dieser Website anbieten, die auf <ph name="LANGUAGE_NAME" /> sind?</translation>
-<translation id="2943166482989655199">Verbessern Sie Chrome und die Sicherheit, indem Sie System- und Nutzungsdaten an Google senden</translation>
+<translation id="2943166482989655199">System- und Nutzungsdaten an Google senden, um Chrome noch besser und sicherer zu machen</translation>
 <translation id="3148434565183091099">Melden Sie sich in Chrome an, um Ihre Lesezeichen auf allen Ihren Geräten zu haben.</translation>
 <translation id="3148688391461398285">Profitieren Sie von einer besseren Nutzererfahrung in Chrome auf Grundlage Ihres Standorts.</translation>
 <translation id="3167189358072330585">Dieses Konto funktioniert in Google Chrome nicht. Wenden Sie sich an Ihren Domainadministrator oder melden Sie sich mit einem Google-Standardkonto an.</translation>
@@ -29,7 +29,7 @@
 <translation id="4099578267706723511">Nutzungsstatistiken und Absturzberichte zur Verbesserung von Chrome an Google senden</translation>
 <translation id="415767770115540173">Profitieren Sie von einer verbesserten Google-Nutzererfahrung in Chrome auf der Grundlage Ihres Standorts.</translation>
 <translation id="424864128008805179">Von Chrome abmelden?</translation>
-<translation id="447252321002412580">Ich möchte dabei helfen, die Funktionen und die Leistung von Chrome zu verbessern</translation>
+<translation id="447252321002412580">Helfen, die Funktionen und die Leistung von Chrome zu verbessern</translation>
 <translation id="4523886039239821078">Einige Add-ons führen zum Ausfall von Chrome. Bitte deinstallieren Sie:</translation>
 <translation id="4615174829807303908">Sie melden sich von einem Konto ab, das von <ph name="SIGNOUT_MANAGED_DOMAIN" /> verwaltet wird. Dadurch werden Ihre Chrome-Daten von diesem Gerät gelöscht, bleiben jedoch in Ihrem Google-Konto erhalten.</translation>
 <translation id="5389212809648216794">Google Chrome kann nicht auf die Kamera zugreifen, da diese gerade von einer anderen App verwendet wird</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_es-419.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_es-419.xtb
index 67472b2..5fd5bd91 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_es-419.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_es-419.xtb
@@ -1,7 +1,7 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="es-419">
-<translation id="114721135501989771">Obtener las funciones inteligentes de Google en Chrome</translation>
+<translation id="114721135501989771">Obtén las mejores funciones de Google en Chrome</translation>
 <translation id="1326317727527857210">Accede a Chrome para obtener las pestañas de tus otros dispositivos.</translation>
 <translation id="1759842336958782510">Chrome</translation>
 <translation id="1816764564654397850">Aviso de privacidad de Google Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb
index f92f9808..d8e68c65f 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_id.xtb
@@ -1,7 +1,7 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="id">
-<translation id="114721135501989771">Dapatkan perangkat smart Google di Chrome</translation>
+<translation id="114721135501989771">Dapatkan kecanggihan Google di Chrome</translation>
 <translation id="1326317727527857210">Untuk mendapatkan tab dari perangkat lainnya, masuk ke Chrome.</translation>
 <translation id="1759842336958782510">Chrome</translation>
 <translation id="1816764564654397850">Pemberitahuan Privasi Google Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb
index a667b9a..79332564 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_pt-BR.xtb
@@ -1,7 +1,7 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="pt-BR">
-<translation id="114721135501989771">Use a tecnologia do Google no Chrome</translation>
+<translation id="114721135501989771">A tecnologia Google no Chrome</translation>
 <translation id="1326317727527857210">Para ver as guias dos seus outros dispositivos, faça login no Chrome.</translation>
 <translation id="1759842336958782510">Chrome</translation>
 <translation id="1816764564654397850">Aviso de Privacidade do Google Chrome</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
index afd7e59..eff67f5e 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
@@ -10,7 +10,7 @@
 <translation id="2334084861041072223">© Google Inc, <ph name="YEAR" />. Все права защищены.</translation>
 <translation id="2342981853652716282">Войдите в Chrome, чтобы синхронизировать закладки, пароли и другую информацию на всех ваших устройствах.</translation>
 <translation id="2347208864470321755">Когда эта функция включена, Chrome будет предлагать перевести страницы с помощью Переводчика Google. <ph name="BEGIN_LINK" />Подробнее…<ph name="END_LINK" /></translation>
-<translation id="2436117022029368436">Обмен информацией с Google для улучшения работы Chrome</translation>
+<translation id="2436117022029368436">Отправка данных в Google для улучшения работы Chrome</translation>
 <translation id="2441696206556358796">Чтобы открыть Chrome доступ к фотографиям, нажмите "Настройки".</translation>
 <translation id="2576431527583832481">Chrome становится лучше! Доступна новая версия.</translation>
 <translation id="257708665678654955">Хотите, чтобы Google Chrome всегда предлагал перевести этот сайт, когда обнаружит на его страницах <ph name="LANGUAGE_NAME" />?</translation>
@@ -29,7 +29,7 @@
 <translation id="4099578267706723511">Отправлять в Google статистику использования и отчеты о сбоях</translation>
 <translation id="415767770115540173">Разрешите браузеру определять ваше местоположение и пользуйтесь дополнительными возможностями Chrome.</translation>
 <translation id="424864128008805179">Выйти из Chrome?</translation>
-<translation id="447252321002412580">Помогите улучшить Chrome и его функции</translation>
+<translation id="447252321002412580">Помогать повышать производительность Chrome и улучшать функции</translation>
 <translation id="4523886039239821078">Некоторые дополнения вызывают сбой Chrome. Необходимо удалить:</translation>
 <translation id="4615174829807303908">Вы выходите из аккаунта, которым управляет администратор домена <ph name="SIGNOUT_MANAGED_DOMAIN" />. Все данные Chrome, хранящиеся на этом устройстве, будут удалены, но останутся в вашем аккаунте Google.</translation>
 <translation id="5389212809648216794">Google Chrome не может получить доступ к камере, поскольку она используется другим приложением.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-CN.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-CN.xtb
index 0b5adf51..af92a4c 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-CN.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_zh-CN.xtb
@@ -14,7 +14,7 @@
 <translation id="2441696206556358796">要保存图片,请点按“设置”,并允许 Chrome 使用您的照片</translation>
 <translation id="2576431527583832481">Chrome 浏览器刚刚经过了改进!新版本已推出。</translation>
 <translation id="257708665678654955">下次访问这个网站时,您希望 Google Chrome 翻译其中的<ph name="LANGUAGE_NAME" />网页吗?</translation>
-<translation id="2943166482989655199">通过将系统信息和使用情况数据发送给 Google,协助改进 Chrome 并提高其安全性</translation>
+<translation id="2943166482989655199">将系统信息和使用情况数据发送给 Google,帮助改进 Chrome 并提高其安全性</translation>
 <translation id="3148434565183091099">要将您的书签同步到您所有的设备上,请登录 Chrome。</translation>
 <translation id="3148688391461398285">要在Chrome中获得更好的使用体验,需要用到您的位置信息。</translation>
 <translation id="3167189358072330585">无法在 Google Chrome 上登录您的帐号。请与您的网域管理员联系,或使用普通的 Google 帐号登录。</translation>
@@ -33,7 +33,7 @@
 <translation id="4523886039239821078">部分插件导致 Chrome 崩溃,请卸载这些插件:</translation>
 <translation id="4615174829807303908">您正要退出由 <ph name="SIGNOUT_MANAGED_DOMAIN" /> 管理的帐号。退出后,您的 Chrome 数据将从这台设备上删除,但仍会保留在您的 Google 帐号中。</translation>
 <translation id="5389212809648216794">由于另一个应用正在使用您的相机,因此 Google Chrome 无法使用</translation>
-<translation id="5489543008378040943">您随时可以自定义<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />。Google 可能会根据您所访问网站中的内容、浏览器互动行为和活动对 Chrome 以及 Google 服务(例如翻译、搜索和广告)进行个性化设置。</translation>
+<translation id="5489543008378040943">您随时可以自定义<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />。Google 可能会根据您访问的网站上的内容、在浏览器中的互动行为和活动,为您提供个性化的 Chrome 体验和其他 Google 服务体验(例如翻译、搜索和广告)。</translation>
 <translation id="5639704535586432836">打开“设置”&gt;“隐私”&gt;“相机”&gt;“Google Chrome”,然后开启相机。</translation>
 <translation id="5642200033778930880">Google Chrome 无法在分割视图模式下使用您的相机</translation>
 <translation id="5703130498371792817">您对 Chrome 使用体验感到满意吗?欢迎<ph name="BEGIN_LINK" />为此应用评分<ph name="END_LINK" /></translation>
@@ -54,5 +54,5 @@
 <translation id="840168496893712993">部分插件导致 Chrome 崩溃,请尝试卸载这些插件。</translation>
 <translation id="8459495907675268833">所选数据已从 Chrome 和同步的设备中移除。不过,您的 Google 帐号在 history.google.com 上可能有其他形式的浏览记录(例如,在其他 Google 服务中的搜索记录和活动记录)。</translation>
 <translation id="8540666473246803645">Google Chrome</translation>
-<translation id="8606668294522778825">Google Chrome可能会使用网络服务来改善您的浏览体验。不过,您可以选择停用这些服务。<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
+<translation id="8606668294522778825">Google Chrome 可能会使用网络服务来改善您的浏览体验。不过,您可以选择停用这些服务。<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
 </translationbundle>
\ No newline at end of file
diff --git a/ios/chrome/app/strings/resources/ios_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
index ad77ede..e534f78 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ar.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
@@ -76,6 +76,7 @@
 <translation id="2120297377148151361">النشاط والتفاعلات</translation>
 <translation id="213900355088104901">للتصفّح بخصوصية تامّة، افتح علامة تبويب للتصفُّح المتخفي</translation>
 <translation id="2149973817440762519">تعديل الإشارة</translation>
+<translation id="2207590065820824892"><ph name="UNREAD_COUNT" /> من مقالات قائمة القراءة غير المقروءة.</translation>
 <translation id="2230173723195178503">تم تحميل الصفحة المطلوبة</translation>
 <translation id="2256128224215992540">اقتراحات البحث والمواقع</translation>
 <translation id="2267753748892043616">إضافة حساب</translation>
@@ -219,6 +220,7 @@
 
 تم تشفير بياناتك باستخدام عبارة مرور المزامنة. أدخلها لبدء المزامنة.</translation>
 <translation id="473775607612524610">تحديث</translation>
+<translation id="4807020197310989387">مقالة قائمة قراءة واحدة غير مقروءة.</translation>
 <translation id="481968316161811770">ملفات تعريف الارتباط، وبيانات موقع الويب</translation>
 <translation id="4854345657858711387">تعيين رمز المرور</translation>
 <translation id="4860895144060829044">اتصال</translation>
@@ -394,6 +396,7 @@
 <translation id="7830720446622801252">الخدمات غير المُخصّصة</translation>
 <translation id="7856733331829174190">تعذّر التنزيل.</translation>
 <translation id="7859704718976024901">سجل التصفح</translation>
+<translation id="7918293828610777738">قائمة القراءة متاحة بلا اتصال بالإنترنت. لإضافة صفحة إلى قائمة القراءة، انقر على  <ph name="SHARE_OPENING_ICON" />  ثم <ph name="READ_LATER_TEXT" />.</translation>
 <translation id="7938254975914653459">FaceTime</translation>
 <translation id="7939128259257418052">جارٍ تصدير كلمات المرور...</translation>
 <translation id="7947953824732555851">قبول وتسجيل الدخول</translation>
@@ -411,6 +414,7 @@
 <translation id="8080028325999236607">إغلاق جميع علامات التبويب</translation>
 <translation id="8114753159095730575">أصبح بالإمكان تنزيل الملف. يمكنك مراجعة الخيارات في أسفل الشاشة.</translation>
 <translation id="8160722851663543621">يُرسِل عمليات البحث من شريط العناوين ومربّع البحث وبعض ملفات تعريف الارتباط إلى محرك البحث التلقائي.</translation>
+<translation id="8178325540017397816">ستتم إزالة العناصر التي اخترتها.</translation>
 <translation id="8205564605687841303">إلغاء</translation>
 <translation id="8225985093977202398">الصور والملفات المُخزنة مؤقتًا</translation>
 <translation id="8261506727792406068">حذف</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_bn.xtb b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
index f1dd086..d6d88fa7f 100644
--- a/ios/chrome/app/strings/resources/ios_strings_bn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
@@ -73,6 +73,7 @@
 <translation id="2116625576999540962"><ph name="NUMBER_OF_SELECTED_BOOKMARKS" />টি আইটেম সরানো হয়েছে</translation>
 <translation id="213900355088104901">গোপনে ব্রাউজ করার জন্য ছদ্মবেশী ট্যাব খুলুন</translation>
 <translation id="2149973817440762519">বুকমার্ক সম্পাদনা করুন</translation>
+<translation id="2207590065820824892">পড়ার তালিকাতে <ph name="UNREAD_COUNT" />টি না পড়া নিবন্ধ।</translation>
 <translation id="2230173723195178503">ওয়েবপৃষ্ঠা লোড হয়েছে</translation>
 <translation id="2256128224215992540">সার্চ এবং সাইটের প্রস্তাবনা</translation>
 <translation id="2267753748892043616">অ্যাকাউন্ট যোগ করুন</translation>
@@ -214,6 +215,7 @@
 
 আপনার সিঙ্ক পাসফ্রেজের মাধ্যমে আপনার ডেটা এনক্রিপটেড হয়েছে। সিঙ্ক শুরু করতে এটি লিখুন।</translation>
 <translation id="473775607612524610">আপডেট</translation>
+<translation id="4807020197310989387">পড়ার তালিকাতে ১টি না পড়া নিবন্ধ।</translation>
 <translation id="481968316161811770">কুকিজ, সাইট ডেটা</translation>
 <translation id="4854345657858711387">একটি পাসকোড সেট করুন</translation>
 <translation id="4860895144060829044">কল করুন</translation>
@@ -385,6 +387,7 @@
 <translation id="780301667611848630">না থাক</translation>
 <translation id="7856733331829174190">ডাউনলোড করা যায়নি</translation>
 <translation id="7859704718976024901">ব্রাউজিং ইতিহাস</translation>
+<translation id="7918293828610777738">আপনার পড়ার তালিকাটি অফলাইনে উপলভ্য। আপনার পড়ার তালিকায় কোনও পৃষ্ঠা যোগ করতে <ph name="SHARE_OPENING_ICON" />  তারপর <ph name="READ_LATER_TEXT" /> ট্যাপ করুন।</translation>
 <translation id="7938254975914653459">ফেসটাইম</translation>
 <translation id="7939128259257418052">পাসওয়ার্ড এক্সপোর্ট করুন...</translation>
 <translation id="7947953824732555851">স্বীকার করুন ও প্রবেশ করুন</translation>
@@ -401,6 +404,7 @@
 <translation id="8076014560081431679">সংরক্ষিত সাইটের সেটিংস মোছা হবে না এবং আপনার ব্রাউজিং অভ্যাস প্রতিফলিত হতে পারে। <ph name="BEGIN_LINK" />আরও জানুন<ph name="END_LINK" /></translation>
 <translation id="8080028325999236607">সমস্ত ট্যাব বন্ধ করুন</translation>
 <translation id="8114753159095730575">ফাইল ডাউনলোড করা যাবে। স্ক্রিনের নিচের দিকে বিকল্পগুলি উপলভ্য।</translation>
+<translation id="8178325540017397816">আপনার বেছে নেওয়া আইটেমগুলি সরানো হবে</translation>
 <translation id="8205564605687841303">বাতিল করুন</translation>
 <translation id="8225985093977202398">সঞ্চিত ছবি এবং ফাইলগুলি</translation>
 <translation id="8261506727792406068">মুছুন</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_de.xtb b/ios/chrome/app/strings/resources/ios_strings_de.xtb
index 2dab6ed..1b137c7 100644
--- a/ios/chrome/app/strings/resources/ios_strings_de.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_de.xtb
@@ -20,7 +20,7 @@
 <translation id="1219674500290482172">Internetverbindung kann nicht hergestellt werden.</translation>
 <translation id="1254117744268754948">Ordner wählen</translation>
 <translation id="1265739287306757398">Weitere Informationen</translation>
-<translation id="127138278192656016">Synchronisierung und alle Dienste verwenden</translation>
+<translation id="127138278192656016">Synchronisierung und alle Dienste nutzen</translation>
 <translation id="1272079795634619415">Stopp</translation>
 <translation id="1323735185997015385">Löschen</translation>
 <translation id="132683371494960526">Tippen Sie hier doppelt, um den übergeordneten Ordner zu ändern.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_id.xtb b/ios/chrome/app/strings/resources/ios_strings_id.xtb
index 49e8e56..029ec81f 100644
--- a/ios/chrome/app/strings/resources/ios_strings_id.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_id.xtb
@@ -20,7 +20,7 @@
 <translation id="1219674500290482172">Tidak dapat tersambung ke internet.</translation>
 <translation id="1254117744268754948">Pilih Folder</translation>
 <translation id="1265739287306757398">Pelajari Caranya</translation>
-<translation id="127138278192656016">Menggunakan sinkronisasi dan semua layanan</translation>
+<translation id="127138278192656016">Gunakan sinkronisasi dan semua layanan</translation>
 <translation id="1272079795634619415">Berhenti</translation>
 <translation id="1323735185997015385">Hapus</translation>
 <translation id="132683371494960526">Ketuk dua kali untuk mengubah folder induk.</translation>
@@ -120,7 +120,7 @@
 <translation id="2898963176829412617">Folder Baru…</translation>
 <translation id="2903493209154104877">Alamat</translation>
 <translation id="2909437209446960244">Tab Terbaru</translation>
-<translation id="2916171785467530738">Melengkapi Otomatis Penelusuran dan URL</translation>
+<translation id="2916171785467530738">Lengkapi Otomatis Penelusuran dan URL</translation>
 <translation id="291754862089661335">Letakkan kode QR atau kode batang dalam bingkai ini</translation>
 <translation id="2921219216347069551">Gagal Berbagi Halaman</translation>
 <translation id="2923448633003185837">Tempel dan Buka</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ru.xtb b/ios/chrome/app/strings/resources/ios_strings_ru.xtb
index 4a9c975..4809824 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ru.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ru.xtb
@@ -10,7 +10,7 @@
 <translation id="1112015203684611006">Ошибка печати</translation>
 <translation id="1125564390852150847">Создать вкладку</translation>
 <translation id="1145536944570833626">Удалить сохраненные данные.</translation>
-<translation id="1157102636231978136">Данные о работе в браузере и о ваших действиях, синхронизированные с аккаунтом Google</translation>
+<translation id="1157102636231978136">Данные о работе в браузере и ваших действиях, связанных с аккаунтом Google</translation>
 <translation id="1165039591588034296">Ошибка</translation>
 <translation id="1172898394251786223">Следующее поле</translation>
 <translation id="1176932207622159128">Не удалось сохранить</translation>
@@ -76,6 +76,7 @@
 <translation id="2120297377148151361">Действия в браузере</translation>
 <translation id="213900355088104901">Чтобы просматривать сайты анонимно, откройте вкладку в режиме инкогнито</translation>
 <translation id="2149973817440762519">Закладка</translation>
+<translation id="2207590065820824892">Число непрочитанных статей в Списке для чтения: <ph name="UNREAD_COUNT" />.</translation>
 <translation id="2230173723195178503">Веб-страница загружена</translation>
 <translation id="2256128224215992540">Подсказки запросов и сайтов</translation>
 <translation id="2267753748892043616">Добавить аккаунт</translation>
@@ -219,12 +220,13 @@
 
 Данные зашифрованы с помощью кодовой фразы. Введите ее, чтобы начать синхронизацию.</translation>
 <translation id="473775607612524610">Обновление</translation>
+<translation id="4807020197310989387">В Списке для чтения 1 непрочитанная статья.</translation>
 <translation id="481968316161811770">Cookie, данные сайтов</translation>
 <translation id="4854345657858711387">Установите код доступа</translation>
 <translation id="4860895144060829044">Позвонить</translation>
 <translation id="4875622588773761625">Обновить пароль для этого сайта в сервисе "<ph name="PASSWORD_MANAGER_BRAND" />"?</translation>
 <translation id="4881695831933465202">Открыть</translation>
-<translation id="4882831918239250449">Выберите параметры истории просмотров для персонализации Поиска, рекламы и т. д.</translation>
+<translation id="4882831918239250449">Использование данных о посещенных страницах для персонализации Поиска, рекламы и т. д.</translation>
 <translation id="4904877109095351937">Отметить как прочитанное</translation>
 <translation id="4930268273022498155">Удалить сохраненные данные. Чтобы снова получить к ним доступ, переключитесь на аккаунт <ph name="USER_EMAIL1" />.</translation>
 <translation id="4941089862236492464">Не удалось опубликовать запись.</translation>
@@ -394,12 +396,13 @@
 <translation id="7830720446622801252">Неперсонализированные сервисы</translation>
 <translation id="7856733331829174190">Не удалось скачать файл</translation>
 <translation id="7859704718976024901">История просмотра веб-страниц</translation>
+<translation id="7918293828610777738">Список для чтения доступен без подключения к Интернету. Чтобы добавить в него страницу, нажмите <ph name="SHARE_OPENING_ICON" />, а потом <ph name="READ_LATER_TEXT" />.</translation>
 <translation id="7938254975914653459">FaceTime</translation>
 <translation id="7939128259257418052">Экспорт паролей...</translation>
 <translation id="7947953824732555851">Принять и войти</translation>
 <translation id="7961015016161918242">Нет</translation>
 <translation id="7971521879845308059">Блок. вспл. окна</translation>
-<translation id="7981313251711023384">Разрешить предварительную настройку страниц для повышения скорости работы и поиска</translation>
+<translation id="7981313251711023384">Разрешить предзагрузку страниц для повышения скорости работы браузера и поиска</translation>
 <translation id="7982789257301363584">Сеть</translation>
 <translation id="8019783059653722575">Это нужно, чтобы сохранять и загружать фотографии</translation>
 <translation id="802154636333426148">Ошибка скачивания</translation>
@@ -411,6 +414,7 @@
 <translation id="8080028325999236607">Закрыть все вкладки</translation>
 <translation id="8114753159095730575">Файл доступен для скачивания. Параметры указаны в нижней части экрана.</translation>
 <translation id="8160722851663543621">Отправлять поисковые запросы из адресной строки и окна поиска, а также файлы cookie в поисковую систему по умолчанию</translation>
+<translation id="8178325540017397816">Удаление выбранных данных</translation>
 <translation id="8205564605687841303">Отмена</translation>
 <translation id="8225985093977202398">Файлы, сохраненные в кеше</translation>
 <translation id="8261506727792406068">Удалить</translation>
@@ -421,7 +425,7 @@
 <translation id="842017693807136194">Выполнен вход через</translation>
 <translation id="8428045167754449968">Город</translation>
 <translation id="8428213095426709021">Настройки</translation>
-<translation id="8438566539970814960">Улучшить поиск и просмотр страниц</translation>
+<translation id="8438566539970814960">Помогать улучшить просмотр страниц и поиск</translation>
 <translation id="8458397775385147834">Удалено закладок: 1</translation>
 <translation id="8487700953926739672">Доступно в автономном режиме</translation>
 <translation id="8503813439785031346">Имя пользователя</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-CN.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-CN.xtb
index 4956888..ec65a91f 100644
--- a/ios/chrome/app/strings/resources/ios_strings_zh-CN.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_zh-CN.xtb
@@ -350,7 +350,7 @@
 <translation id="6979158407327259162">Google 云端硬盘</translation>
 <translation id="7004499039102548441">最近打开的标签页</translation>
 <translation id="7006788746334555276">内容设置</translation>
-<translation id="7017968314960951695">根据您所访问的网站上的内容以及您的浏览器活动和互动行为,提供个性化的使用体验</translation>
+<translation id="7017968314960951695">根据您访问的网站上的内容以及您在浏览器中的活动和互动行为,提供个性化的使用体验</translation>
 <translation id="7029809446516969842">密码</translation>
 <translation id="7031882061095297553">同步到</translation>
 <translation id="7053983685419859001">禁止</translation>
diff --git a/ios/chrome/browser/autofill/manual_fill/accessory_provider.mm b/ios/chrome/browser/autofill/manual_fill/accessory_provider.mm
index c145fa4..02cce4e3 100644
--- a/ios/chrome/browser/autofill/manual_fill/accessory_provider.mm
+++ b/ios/chrome/browser/autofill/manual_fill/accessory_provider.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/autofill/manual_fill_accessory_provider.h"
+#import "ios/chrome/browser/autofill/manual_fill/accessory_provider.h"
 
 #include "base/feature_list.h"
 #import "base/mac/foundation_util.h"
@@ -16,7 +16,7 @@
 @interface ManualFillAccessoryProvider ()
 
 // The default accesory view to return in the update block.
-@property(nonatomic, readonly) KeyboardAccessoryView* accessoryView;
+@property(nonatomic, readonly) ManualFillKeyboardAccessoryView* accessoryView;
 
 // Callback to update the accessory view.
 @property(nonatomic, copy)
@@ -59,9 +59,10 @@
 
 #pragma mark - Getters
 
-- (KeyboardAccessoryView*)accessoryView {
+- (ManualFillKeyboardAccessoryView*)accessoryView {
   if (!_accessoryView) {
-    _accessoryView = [[KeyboardAccessoryView alloc] initWithDelegate:nil];
+    _accessoryView =
+        [[ManualFillKeyboardAccessoryView alloc] initWithDelegate:nil];
   }
   return _accessoryView;
 }
diff --git a/ios/chrome/browser/snapshots/snapshot_generator.mm b/ios/chrome/browser/snapshots/snapshot_generator.mm
index 992ecb2..5b3a513 100644
--- a/ios/chrome/browser/snapshots/snapshot_generator.mm
+++ b/ios/chrome/browser/snapshots/snapshot_generator.mm
@@ -154,10 +154,9 @@
 - (void)retrieveSnapshot:(void (^)(UIImage*))callback {
   DCHECK(callback);
 
-  __weak SnapshotGenerator* weakSelf = self;
   void (^wrappedCallback)(UIImage*) = ^(UIImage* image) {
     if (!image) {
-      image = [weakSelf updateSnapshotWithOverlays:YES visibleFrameOnly:YES];
+      image = [SnapshotGenerator defaultSnapshotImage];
     }
     callback(image);
   };
@@ -197,10 +196,10 @@
                       visibleFrameOnly:(BOOL)visibleFrameOnly {
   UIImage* snapshot = [self generateSnapshotWithOverlays:shouldAddOverlay
                                         visibleFrameOnly:visibleFrameOnly];
-
   // Return default snapshot without caching it if the generation failed.
-  if (!snapshot)
+  if (!snapshot) {
     return [[self class] defaultSnapshotImage];
+  }
 
   [self.snapshotCache setImage:snapshot withSessionID:_snapshotSessionId];
   return snapshot;
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
index 0abe3a0..8017bd2 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
@@ -216,29 +216,6 @@
   EXPECT_EQ(delegate_.snapshotTakenCount, 0u);
 }
 
-// Tests that RetrieveColorSnapshot generates the image if there is no
-// image in the cache.
-TEST_F(SnapshotTabHelperTest, RetrieveColorSnapshotGenerate) {
-  AddDefaultWebStateView();
-
-  base::RunLoop run_loop;
-  base::RunLoop* run_loop_ptr = &run_loop;
-
-  __block UIImage* snapshot = nil;
-  SnapshotTabHelper::FromWebState(&web_state_)
-      ->RetrieveColorSnapshot(^(UIImage* image) {
-        snapshot = image;
-        run_loop_ptr->Quit();
-      });
-
-  run_loop.Run();
-
-  ASSERT_TRUE(snapshot);
-  EXPECT_TRUE(CGSizeEqualToSize(snapshot.size, kWebStateViewSize));
-  EXPECT_TRUE(IsDominantColorForImage(snapshot, [UIColor redColor]));
-  EXPECT_EQ(delegate_.snapshotTakenCount, 1u);
-}
-
 // Tests that RetrieveGreySnapshot uses the image from the cache if
 // there is one present, and that it is greyscale.
 TEST_F(SnapshotTabHelperTest, RetrieveGreySnapshotCachedSnapshot) {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 2152b24..b6308bf9b 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -876,6 +876,7 @@
           self.spinnerView = nil;
         }];
     [strongSelf loadBookmarkViews];
+    [strongSelf.sharedState.tableView reloadData];
   }];
 }
 
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
index 5902673..b54acc2 100644
--- a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -494,6 +494,8 @@
   cell.theme = self.theme;
   cell.itemIdentifier = item.identifier;
   cell.title = item.title;
+  cell.snapshot = nil;
+  cell.icon = nil;
   NSString* itemIdentifier = item.identifier;
   [self.imageDataSource faviconForIdentifier:itemIdentifier
                                   completion:^(UIImage* icon) {
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
index 0245cd1f..8ee3c84 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -212,7 +212,6 @@
 
 - (void)webStateDidChangeTitle:(web::WebState*)webState {
   // Assumption: the ID of the webState didn't change as a result of this load.
-  SnapshotTabHelper::FromWebState(webState)->RemoveSnapshot();
   TabIdTabHelper* tabHelper = TabIdTabHelper::FromWebState(webState);
   NSString* itemID = tabHelper->tab_id();
   [self.consumer replaceItemID:itemID withItem:CreateItem(webState)];
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_accessory_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_accessory_item.mm
index 96558b3..61949ba 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_accessory_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_accessory_item.mm
@@ -12,11 +12,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// The width and height of the ImageView.
-const float kImageWidth = 28.0f;
-}
-
 @implementation TableViewAccessoryItem
 
 @synthesize image = _image;
@@ -68,6 +63,8 @@
     // The favicon image is smaller than its UIImageView's bounds, so center
     // it.
     _imageView.contentMode = UIViewContentModeCenter;
+    [_imageView setContentHuggingPriority:UILayoutPriorityRequired
+                                  forAxis:UILayoutConstraintAxisHorizontal];
 
     // Set font size using dynamic type.
     _titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
@@ -80,7 +77,7 @@
         setContentHuggingPriority:UILayoutPriorityDefaultHigh
                           forAxis:UILayoutConstraintAxisHorizontal];
 
-    // Horizontal stack view holds favicon, title, and disclosureView.
+    // Horizontal stack view holds imageView, title, and disclosureView.
     UIStackView* horizontalStack =
         [[UIStackView alloc] initWithArrangedSubviews:@[
           _imageView, _titleLabel, disclosureImageView
@@ -94,8 +91,6 @@
     [self.contentView addSubview:horizontalStack];
 
     [NSLayoutConstraint activateConstraints:@[
-      // The favicon view has fixed width.
-      [_imageView.widthAnchor constraintEqualToConstant:kImageWidth],
       // Horizontal Stack constraints.
       [horizontalStack.leadingAnchor
           constraintEqualToAnchor:self.contentView.leadingAnchor
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
index fde3071e..7b303afa 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
@@ -102,20 +102,31 @@
     // Add subviews to View Hierarchy.
     [self.contentView addSubview:horizontalStack];
 
+    // Lower the padding constraints priority. UITableView might try to set
+    // the header view height/width to 0 breaking the constraints. See
+    // https://crbug.com/854117 for more information.
+    NSLayoutConstraint* topAnchorConstraint = [horizontalStack.topAnchor
+        constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor
+                                    constant:kTableViewVerticalSpacing];
+    topAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* bottomAnchorConstraint = [horizontalStack.bottomAnchor
+        constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
+                                 constant:-kTableViewVerticalSpacing];
+    bottomAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* leadingAnchorConstraint = [horizontalStack.leadingAnchor
+        constraintEqualToAnchor:self.contentView.leadingAnchor
+                       constant:kTableViewHorizontalSpacing];
+    leadingAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* trailingAnchorConstraint =
+        [horizontalStack.trailingAnchor
+            constraintEqualToAnchor:self.contentView.trailingAnchor
+                           constant:-kTableViewHorizontalSpacing];
+    trailingAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+
     // Set and activate constraints.
     [NSLayoutConstraint activateConstraints:@[
-      [horizontalStack.leadingAnchor
-          constraintEqualToAnchor:self.contentView.leadingAnchor
-                         constant:kTableViewHorizontalSpacing],
-      [horizontalStack.trailingAnchor
-          constraintEqualToAnchor:self.contentView.trailingAnchor
-                         constant:-kTableViewHorizontalSpacing],
-      [horizontalStack.topAnchor
-          constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor
-                                      constant:kTableViewVerticalSpacing],
-      [horizontalStack.bottomAnchor
-          constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
-                                   constant:-kTableViewVerticalSpacing],
+      topAnchorConstraint, bottomAnchorConstraint, leadingAnchorConstraint,
+      trailingAnchorConstraint,
       [horizontalStack.centerYAnchor
           constraintEqualToAnchor:self.contentView.centerYAnchor]
     ]];
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
index 2a80514..ea3b39c 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
@@ -130,20 +130,31 @@
     // Add subviews to View Hierarchy.
     [self.contentView addSubview:horizontalStack];
 
+    // Lower the padding constraints priority. UITableView might try to set
+    // the header view height/width to 0 breaking the constraints. See
+    // https://crbug.com/854117 for more information.
+    NSLayoutConstraint* topAnchorConstraint = [horizontalStack.topAnchor
+        constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor
+                                    constant:kTableViewVerticalSpacing];
+    topAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* bottomAnchorConstraint = [horizontalStack.bottomAnchor
+        constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
+                                 constant:-kTableViewVerticalSpacing];
+    bottomAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* leadingAnchorConstraint = [horizontalStack.leadingAnchor
+        constraintEqualToAnchor:self.contentView.leadingAnchor
+                       constant:kTableViewHorizontalSpacing];
+    leadingAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSLayoutConstraint* trailingAnchorConstraint =
+        [horizontalStack.trailingAnchor
+            constraintEqualToAnchor:self.contentView.trailingAnchor
+                           constant:-kTableViewHorizontalSpacing];
+    trailingAnchorConstraint.priority = UILayoutPriorityDefaultHigh;
+
     // Set and activate constraints.
     [NSLayoutConstraint activateConstraints:@[
-      [horizontalStack.leadingAnchor
-          constraintEqualToAnchor:self.contentView.leadingAnchor
-                         constant:kTableViewHorizontalSpacing],
-      [horizontalStack.trailingAnchor
-          constraintEqualToAnchor:self.contentView.trailingAnchor
-                         constant:-kTableViewHorizontalSpacing],
-      [horizontalStack.topAnchor
-          constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor
-                                      constant:kTableViewVerticalSpacing],
-      [horizontalStack.bottomAnchor
-          constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
-                                   constant:-kTableViewVerticalSpacing],
+      topAnchorConstraint, bottomAnchorConstraint, leadingAnchorConstraint,
+      trailingAnchorConstraint,
       [horizontalStack.centerYAnchor
           constraintEqualToAnchor:self.contentView.centerYAnchor]
     ]];
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
index 0249def9..b216b5856 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
@@ -76,6 +76,9 @@
     [containerView addSubview:verticalStack];
     [self.contentView addSubview:containerView];
 
+    // If performBatchUpdates is used with this header there might be a need to
+    // change the padding constraints priority. See https://crbug.com/854117 for
+    // more information.
     // Set and activate constraints.
     [NSLayoutConstraint activateConstraints:@[
       // Container Constraints.
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index c19b3e9..6e75e72 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: 943615c5feec4fcb51efe6aaad3c2226aa3e283f
+Revision: 98397e899bd994fb1b42f1dc15ef8a6c7357ae2f
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm
index 266fcbb..84a7142 100644
--- a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm
+++ b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm
@@ -499,6 +499,7 @@
   MOCK_METHOD1(DidStopLoading, void(WebState*));
   MOCK_METHOD2(PageLoaded, void(WebState*, PageLoadCompletionStatus));
   MOCK_METHOD1(DidChangeBackForwardState, void(WebState*));
+  MOCK_METHOD1(TitleWasSet, void(WebState*));
   void WebStateDestroyed(WebState* web_state) override { NOTREACHED(); }
 
  private:
@@ -609,6 +610,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -642,6 +644,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -710,6 +713,7 @@
   EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
       .WillOnce(Return(true));
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -734,6 +738,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyReloadFinishedContext(web_state(), url, &context, &nav_id,
                                             true /* is_web_page */));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -768,6 +773,7 @@
   EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
       .WillOnce(Return(true));
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -788,6 +794,7 @@
       .WillOnce(Return(true));
   // TODO(crbug.com/798836): verify the correct User-Agent header is sent.
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -824,6 +831,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -902,6 +910,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -956,6 +965,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1011,6 +1021,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewNativePageFinishedContext(web_state(), url, &context,
                                                    &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1026,6 +1037,7 @@
   // No ShouldAllowRequest/ShouldAllowResponse callbacks for native content
   // navigations.
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1051,6 +1063,78 @@
                                               /*check_for_repost=*/false);
 }
 
+// Tests WasTitleSet callback triggered when navigating back to native content
+// from web content.
+TEST_P(NavigationAndLoadCallbacksTest, GoBackToNativeContent) {
+  // Load a native content URL.
+  GURL url(url::SchemeHostPort(kTestNativeContentScheme, "ui", 0).Serialize());
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _));
+  // No ShouldAllowRequest/ShouldAllowResponse callbacks for native content
+  // navigations.
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+  [provider_ setController:content_ forURL:url];
+  ASSERT_TRUE(LoadUrl(url));
+
+  // Load a web navigation.
+  const GURL web_url = test_server_->GetURL("/echo");
+
+  // Perform new page navigation.
+  NavigationContext* context = nullptr;
+  int32_t nav_id = 0;
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+  WebStatePolicyDecider::RequestInfo expected_request_info(
+      ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT, web_url,
+      /*target_main_frame=*/true, /*has_user_gesture=*/false);
+  EXPECT_CALL(*decider_,
+              ShouldAllowRequest(_, RequestInfoMatch(expected_request_info)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _))
+      .WillOnce(VerifyPageStartedContext(
+          web_state(), web_url, ui::PageTransition::PAGE_TRANSITION_TYPED,
+          &context, &nav_id));
+  EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
+      .WillOnce(Return(true));
+  if (GetWebClient()->IsSlimNavigationManagerEnabled()) {
+    EXPECT_CALL(observer_, DidChangeBackForwardState(web_state()));
+  }
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
+      .WillOnce(VerifyNewPageFinishedContext(
+          web_state(), web_url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+  ASSERT_TRUE(LoadUrl(web_url));
+
+  // Going back to native content should trigger TitleWasSet.
+  if (GetWebClient()->IsSlimNavigationManagerEnabled()) {
+    EXPECT_CALL(observer_, DidChangeBackForwardState(web_state())).Times(2);
+    // TODO(crbug.com/867095): fix this extra callback triggered by placeholder
+    // URL load.
+    EXPECT_CALL(observer_,
+                PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+  }
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _));
+  // No ShouldAllowRequest/ShouldAllowResponse callbacks for native content
+  // navigations.
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  // This call is required to make sure WebStateObservers update their cached
+  // version of current title.
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+  ASSERT_TRUE(ExecuteBlockAndWaitForLoad(url, ^{
+    navigation_manager()->GoBack();
+  }));
+}
+
 // Tests successful navigation to a new page with post HTTP method.
 TEST_P(NavigationAndLoadCallbacksTest, UserInitiatedPostNavigation) {
   // Prior to iOS 11, POST navigation is implemented as an XMLHttpRequest in
@@ -1086,6 +1170,7 @@
     EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
         .WillOnce(VerifyNewPageFinishedContext(
             web_state(), url, kExpectedMimeType, &context, &nav_id));
+    EXPECT_CALL(observer_, TitleWasSet(web_state())).Times(2);
     EXPECT_CALL(observer_, DidStopLoading(web_state()));
     EXPECT_CALL(observer_,
                 PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1117,6 +1202,7 @@
       .WillOnce(VerifyPostFinishedContext(
           web_state(), url, /*has_user_gesture=*/true, &context, &nav_id,
           /*renderer_initiated=*/false));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1146,6 +1232,7 @@
   EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
       .WillOnce(Return(true));
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1176,6 +1263,7 @@
       .WillOnce(VerifyPostFinishedContext(
           web_state(), action, /*has_user_gesture=*/false, &context, &nav_id,
           /*renderer_initiated=*/true));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1201,6 +1289,7 @@
   EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
       .WillOnce(Return(true));
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1223,6 +1312,7 @@
     EXPECT_CALL(observer_, DidChangeBackForwardState(web_state()));
   }
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1264,6 +1354,7 @@
       .WillOnce(VerifyPostFinishedContext(
           web_state(), action, /*has_user_gesture=*/true, &context, &nav_id,
           reload_is_renderer_initiated));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1299,6 +1390,7 @@
   EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
       .WillOnce(Return(true));
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1321,6 +1413,7 @@
     EXPECT_CALL(observer_, DidChangeBackForwardState(web_state()));
   }
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1353,6 +1446,7 @@
         .WillOnce(Return(true));
   }
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1384,6 +1478,7 @@
       .WillOnce(VerifyPostFinishedContext(
           web_state(), action, /*has_user_gesture=*/true, &context, &nav_id,
           /*renderer_initiated=*/false));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1425,6 +1520,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(
           web_state(), redirect_url, kExpectedMimeType, &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
@@ -1488,6 +1584,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(web_state(), url, /*mime_type=*/"",
                                              &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::FAILURE));
@@ -1588,6 +1685,7 @@
   EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
       .WillOnce(VerifyNewPageFinishedContext(web_state(), url, /*mime_type=*/"",
                                              &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
 
   test::LoadUrl(web_state(), url);
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 2abad79..caae320 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1290,9 +1290,6 @@
     return;
 
   base::string16 newTitle = base::SysNSStringToUTF16(title);
-  if (item->GetTitle() == newTitle)
-    return;
-
   item->SetTitle(newTitle);
   // TODO(crbug.com/546218): See if this can be removed; it's not clear that
   // other platforms send this (tab sync triggers need to be compared against
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 6e6b232..848c7e36 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -1089,10 +1089,18 @@
   scoped_observer.Add(web_state());
   ASSERT_EQ(0, observer.title_change_count());
 
-  // Expect TitleWasSet callback after the page is loaded.
+  int initial_title_change_count = 0;
+  if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
+    // WKBasedNavigationManager produces an extra call to TitleWasSet because it
+    // loads New Tab Page in web view.
+    initial_title_change_count += 1;
+  }
+
+  // Expect TitleWasSet callback after the page is loaded and due to WKWebView
+  // title change KVO.
   LoadHtml(@"<title>Title1</title>");
   EXPECT_EQ("Title1", base::UTF16ToUTF8(web_state()->GetTitle()));
-  EXPECT_EQ(1, observer.title_change_count());
+  EXPECT_EQ(initial_title_change_count + 2, observer.title_change_count());
 
   // Expect at least one more TitleWasSet callback after changing title via
   // JavaScript. On iOS 10 WKWebView fires 3 callbacks after JS excucution
@@ -1101,7 +1109,7 @@
   // Fix expecteation when WKWebView stops sending extra KVO calls.
   ExecuteJavaScript(@"window.document.title = 'Title2';");
   EXPECT_EQ("Title2", base::UTF16ToUTF8(web_state()->GetTitle()));
-  EXPECT_GE(observer.title_change_count(), 2);
+  EXPECT_GE(observer.title_change_count(), initial_title_change_count + 3);
 };
 
 // Tests that fragment change navigations use title from the previous page.
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index c29e0506..24abaff1 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -32,7 +32,6 @@
 #include "media/filters/ffmpeg_demuxer.h"
 #include "media/filters/file_data_source.h"
 #include "media/formats/mp4/avc.h"
-#include "media/formats/mp4/bitstream_converter.h"
 #include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -1200,8 +1199,8 @@
     subsamples = buffer->decrypt_config()->subsamples();
 
   bool is_valid =
-      mp4::AVC::AnalyzeAnnexB(buffer->data(), buffer->data_size(), subsamples)
-          .is_conformant.value_or(false);
+      mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size(),
+                              subsamples);
   EXPECT_TRUE(is_valid);
 
   if (!is_valid) {
diff --git a/media/formats/mp4/avc.cc b/media/formats/mp4/avc.cc
index 235795f7..509335b 100644
--- a/media/formats/mp4/avc.cc
+++ b/media/formats/mp4/avc.cc
@@ -171,21 +171,15 @@
   return true;
 }
 
-// static
-BitstreamConverter::AnalysisResult AVC::AnalyzeAnnexB(
-    const uint8_t* buffer,
-    size_t size,
-    const std::vector<SubsampleEntry>& subsamples) {
+// Verifies AnnexB NALU order according to ISO/IEC 14496-10 Section 7.4.1.2.3
+bool AVC::IsValidAnnexB(const uint8_t* buffer,
+                        size_t size,
+                        const std::vector<SubsampleEntry>& subsamples) {
   DVLOG(3) << __func__;
   DCHECK(buffer);
 
-  BitstreamConverter::AnalysisResult result;
-  result.is_conformant = false;  // Will change if needed before return.
-
-  if (size == 0) {
-    result.is_conformant = true;
-    return result;
-  }
+  if (size == 0)
+    return true;
 
   H264Parser parser;
   parser.SetEncryptedStream(buffer, size, subsamples);
@@ -211,7 +205,7 @@
           case H264NALU::kAUD:
             if (order_state > kAUDAllowed) {
               DVLOG(1) << "Unexpected AUD in order_state " << order_state;
-              return result;
+              return false;
             }
             order_state = kBeforeFirstVCL;
             break;
@@ -227,7 +221,7 @@
             if (order_state > kBeforeFirstVCL) {
               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
                        << " in order_state " << order_state;
-              return result;
+              return false;
             }
             order_state = kBeforeFirstVCL;
             break;
@@ -235,7 +229,7 @@
           case H264NALU::kSPSExt:
             if (last_nalu_type != H264NALU::kSPS) {
               DVLOG(1) << "SPS extension does not follow an SPS.";
-              return result;
+              return false;
             }
             break;
 
@@ -246,26 +240,22 @@
           case H264NALU::kIDRSlice:
             if (order_state > kAfterFirstVCL) {
               DVLOG(1) << "Unexpected VCL in order_state " << order_state;
-              return result;
+              return false;
             }
-
-            if (!result.is_keyframe.has_value())
-              result.is_keyframe = nalu.nal_unit_type == H264NALU::kIDRSlice;
-
             order_state = kAfterFirstVCL;
             break;
 
           case H264NALU::kCodedSliceAux:
             if (order_state != kAfterFirstVCL) {
               DVLOG(1) << "Unexpected extension in order_state " << order_state;
-              return result;
+              return false;
             }
             break;
 
           case H264NALU::kEOSeq:
             if (order_state != kAfterFirstVCL) {
               DVLOG(1) << "Unexpected EOSeq in order_state " << order_state;
-              return result;
+              return false;
             }
             order_state = kEOStreamAllowed;
             break;
@@ -273,7 +263,7 @@
           case H264NALU::kEOStream:
             if (order_state < kAfterFirstVCL) {
               DVLOG(1) << "Unexpected EOStream in order_state " << order_state;
-              return result;
+              return false;
             }
             order_state = kNoMoreDataAllowed;
             break;
@@ -284,7 +274,7 @@
                   order_state < kEOStreamAllowed)) {
               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
                        << " in order_state " << order_state;
-              return result;
+              return false;
             }
             break;
 
@@ -294,30 +284,25 @@
                 order_state != kAfterFirstVCL) {
               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
                        << " in order_state " << order_state;
-              return result;
+              return false;
             }
         }
         last_nalu_type = nalu.nal_unit_type;
         break;
 
       case H264Parser::kInvalidStream:
-        return result;
+        return false;
 
       case H264Parser::kUnsupportedStream:
         NOTREACHED() << "AdvanceToNextNALU() returned kUnsupportedStream!";
-        return result;
+        return false;
 
       case H264Parser::kEOStream:
         done = true;
     }
   }
 
-  if (order_state < kAfterFirstVCL)
-    return result;
-
-  result.is_conformant = true;
-  DCHECK(result.is_keyframe.has_value());
-  return result;
+  return order_state >= kAfterFirstVCL;
 }
 
 AVCBitstreamConverter::AVCBitstreamConverter(
@@ -353,16 +338,14 @@
   return true;
 }
 
-BitstreamConverter::AnalysisResult AVCBitstreamConverter::Analyze(
+bool AVCBitstreamConverter::IsValid(
     std::vector<uint8_t>* frame_buf,
     std::vector<SubsampleEntry>* subsamples) const {
 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING)
-  if (disable_validation_) {
-    BitstreamConverter::AnalysisResult result;
-    return result;
-  }
+  if (disable_validation_)
+    return true;
 #endif  // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING)
-  return AVC::AnalyzeAnnexB(frame_buf->data(), frame_buf->size(), *subsamples);
+  return AVC::IsValidAnnexB(frame_buf->data(), frame_buf->size(), *subsamples);
 }
 
 }  // namespace mp4
diff --git a/media/formats/mp4/avc.h b/media/formats/mp4/avc.h
index 444d219..655aa2f 100644
--- a/media/formats/mp4/avc.h
+++ b/media/formats/mp4/avc.h
@@ -44,17 +44,14 @@
       const AVCDecoderConfigurationRecord& avc_config,
       std::vector<uint8_t>* buffer);
 
-  // Analyzes the contents of |buffer| for conformance to Section 7.4.1.2.3 of
-  // ISO/IEC 14496-10. Also analyzes |buffer| and reports if it looks like a
-  // keyframe, if such can be determined. Determination of keyframe-ness is done
-  // only if |buffer| is conformant or if lack of conformance is detected after
-  // detecting keyframe-ness.
+  // Verifies that the contents of |buffer| conform to
+  // Section 7.4.1.2.3 of ISO/IEC 14496-10.
   // |subsamples| contains the information about what parts of the buffer are
   // encrypted and which parts are clear.
-  static BitstreamConverter::AnalysisResult AnalyzeAnnexB(
-      const uint8_t* buffer,
-      size_t size,
-      const std::vector<SubsampleEntry>& subsamples);
+  // Returns true if |buffer| contains conformant Annex B data
+  static bool IsValidAnnexB(const uint8_t* buffer,
+                            size_t size,
+                            const std::vector<SubsampleEntry>& subsamples);
 
   // Given a |buffer| and |subsamples| information and |pts| pointer into the
   // |buffer| finds the index of the subsample |ptr| is pointing into.
@@ -84,9 +81,8 @@
                     bool is_keyframe,
                     std::vector<SubsampleEntry>* subsamples) const override;
 
-  AnalysisResult Analyze(
-      std::vector<uint8_t>* frame_buf,
-      std::vector<SubsampleEntry>* subsamples) const override;
+  bool IsValid(std::vector<uint8_t>* frame_buf,
+               std::vector<SubsampleEntry>* subsamples) const override;
 
  private:
   ~AVCBitstreamConverter() override;
diff --git a/media/formats/mp4/avc_unittest.cc b/media/formats/mp4/avc_unittest.cc
index 944ca1b..0bca2a02 100644
--- a/media/formats/mp4/avc_unittest.cc
+++ b/media/formats/mp4/avc_unittest.cc
@@ -6,16 +6,12 @@
 #include <stdint.h>
 #include <string.h>
 
-#include <ostream>
-
 #include "base/macros.h"
-#include "base/optional.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "media/base/decrypt_config.h"
 #include "media/base/stream_parser_buffer.h"
 #include "media/formats/mp4/avc.h"
-#include "media/formats/mp4/bitstream_converter.h"
 #include "media/formats/mp4/box_definitions.h"
 #include "media/video/h264_parser.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,15 +36,6 @@
   if (name == "I")
     return H264NALU::kIDRSlice;
 
-  if (name == "SDA")
-    return H264NALU::kSliceDataA;
-
-  if (name == "SDB")
-    return H264NALU::kSliceDataB;
-
-  if (name == "SDC")
-    return H264NALU::kSliceDataC;
-
   if (name == "SEI")
     return H264NALU::kSEIMessage;
 
@@ -145,9 +132,9 @@
 // The output buffer will contain a valid-looking Annex B (it's valid-looking in
 // the sense that it has start codes and correct NALU types, but the actual NALU
 // payload is junk).
-static void StringToAnnexB(const std::string& str,
-                           std::vector<uint8_t>* buffer,
-                           std::vector<SubsampleEntry>* subsamples) {
+void StringToAnnexB(const std::string& str,
+                    std::vector<uint8_t>* buffer,
+                    std::vector<SubsampleEntry>* subsamples) {
   DCHECK(!str.empty());
 
   std::vector<std::string> subsample_specs = base::SplitString(
@@ -189,30 +176,8 @@
   }
 }
 
-// Helper to compare two results of AVC::Analyze().
-static bool AnalysesMatch(const BitstreamConverter::AnalysisResult& r1,
-                          const BitstreamConverter::AnalysisResult& r2) {
-  return r1.is_conformant == r2.is_conformant &&
-         r1.is_keyframe == r2.is_keyframe;
-}
-
-// Helper output operator, for debugging/testability.
-std::ostream& operator<<(std::ostream& os,
-                         const BitstreamConverter::AnalysisResult& r) {
-  os << "{ is_conformant: "
-     << (r.is_conformant.has_value()
-             ? (r.is_conformant.value() ? "true" : "false")
-             : "nullopt/unknown")
-     << ", is_keyframe: "
-     << (r.is_keyframe.has_value() ? (r.is_keyframe.value() ? "true" : "false")
-                                   : "nullopt/unknown")
-     << " }";
-  return os;
-}
-
-static std::string AnnexBToString(
-    const std::vector<uint8_t>& buffer,
-    const std::vector<SubsampleEntry>& subsamples) {
+std::string AnnexBToString(const std::vector<uint8_t>& buffer,
+                           const std::vector<SubsampleEntry>& subsamples) {
   std::stringstream ss;
 
   H264Parser parser;
@@ -265,14 +230,7 @@
   std::vector<SubsampleEntry> subsamples;
   MakeInputForLength(GetParam(), &buf);
   EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, &subsamples));
-
-  BitstreamConverter::AnalysisResult expected;
-  expected.is_conformant = true;
-  expected.is_keyframe = false;
-  EXPECT_PRED2(AnalysesMatch,
-               AVC::AnalyzeAnnexB(buf.data(), buf.size(), subsamples),
-               expected);
-
+  EXPECT_TRUE(AVC::IsValidAnnexB(buf.data(), buf.size(), subsamples));
   EXPECT_EQ(buf.size(), sizeof(kExpected));
   EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected)));
   EXPECT_EQ("P,SDC", AnnexBToString(buf, subsamples));
@@ -392,107 +350,63 @@
   std::vector<uint8_t> buf;
   std::vector<SubsampleEntry> subsamples;
   StringToAnnexB(str, &buf, &subsamples);
-
-  BitstreamConverter::AnalysisResult expected;
-  expected.is_conformant = true;
-  expected.is_keyframe = true;
-  EXPECT_PRED2(AnalysesMatch,
-               AVC::AnalyzeAnnexB(buf.data(), buf.size(), subsamples),
-               expected);
+  EXPECT_TRUE(AVC::IsValidAnnexB(buf.data(), buf.size(), subsamples));
 
   EXPECT_EQ(str, AnnexBToString(buf, subsamples));
 }
 
 TEST_F(AVCConversionTest, ValidAnnexBConstructs) {
-  struct {
-    const char* case_string;
-    const bool is_keyframe;
-  } test_cases[] = {
-      {"I", true},
-      {"I I I I", true},
-      {"AUD I", true},
-      {"AUD SPS PPS I", true},
-      {"I EOSeq", true},
-      {"I EOSeq EOStr", true},
-      {"I EOStr", true},
-      {"P", false},
-      {"P P P P", false},
-      {"AUD SPS PPS P", false},
-      {"SEI SEI I", true},
-      {"SEI SEI R14 I", true},
-      {"SPS SPSExt SPS PPS I P", true},
-      {"R14 SEI I", true},
-      {"AUD,I", true},
-      {"AUD,SEI I", true},
-      {"AUD,SEI,SPS,PPS,I", true},
-
-      // In reality, these might not always be conformant/valid, but assuming
-      // they are, they're not keyframes because a non-IDR slice preceded the
-      // IDR slice, if any.
-      {"SDA SDB SDC", false},
-      {"P I", false},
-      {"SDA I", false},
-      {"SDB I", false},
-      {"SDC I", false},
+  const char* test_cases[] = {
+    "I",
+    "I I I I",
+    "AUD I",
+    "AUD SPS PPS I",
+    "I EOSeq",
+    "I EOSeq EOStr",
+    "I EOStr",
+    "P",
+    "P P P P",
+    "AUD SPS PPS P",
+    "SEI SEI I",
+    "SEI SEI R14 I",
+    "SPS SPSExt SPS PPS I P",
+    "R14 SEI I",
+    "AUD,I",
+    "AUD,SEI I",
+    "AUD,SEI,SPS,PPS,I"
   };
 
   for (size_t i = 0; i < arraysize(test_cases); ++i) {
     std::vector<uint8_t> buf;
     std::vector<SubsampleEntry> subsamples;
-    StringToAnnexB(test_cases[i].case_string, &buf, NULL);
-
-    BitstreamConverter::AnalysisResult expected;
-    expected.is_conformant = true;
-    expected.is_keyframe = test_cases[i].is_keyframe;
-    EXPECT_PRED2(AnalysesMatch,
-                 AVC::AnalyzeAnnexB(buf.data(), buf.size(), subsamples),
-                 expected)
-        << "'" << test_cases[i].case_string << "' failed";
+    StringToAnnexB(test_cases[i], &buf, NULL);
+    EXPECT_TRUE(AVC::IsValidAnnexB(buf.data(), buf.size(), subsamples))
+        << "'" << test_cases[i] << "' failed";
   }
 }
 
 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) {
-  struct {
-    const char* case_string;
-    const base::Optional<bool> is_keyframe;
-  } test_cases[] = {
-      // For these cases, lack of conformance is determined before detecting any
-      // IDR or non-IDR slices, so the non-conformant frames' keyframe analysis
-      // reports base::nullopt (which means undetermined analysis result).
-      {"AUD", base::nullopt},            // No VCL present.
-      {"AUD,SEI", base::nullopt},        // No VCL present.
-      {"SPS PPS", base::nullopt},        // No VCL present.
-      {"SPS PPS AUD I", base::nullopt},  // Parameter sets must come after AUD.
-      {"SPSExt SPS P", base::nullopt},   // SPS must come before SPSExt.
-      {"SPS PPS SPSExt P", base::nullopt},  // SPSExt must follow an SPS.
-      {"EOSeq", base::nullopt},             // EOSeq must come after a VCL.
-      {"EOStr", base::nullopt},             // EOStr must come after a VCL.
-
-      // For these cases, IDR slice is first VCL and is detected before
-      // conformance failure, so the non-conformant frame is reported as a
-      // keyframe.
-      {"I EOStr EOSeq", true},  // EOSeq must come before EOStr.
-      {"I R14", true},          // Reserved14-18 must come before first VCL.
-      {"I SEI", true},          // SEI must come before first VCL.
-
-      // For this case, P slice is first VCL and is detected before conformance
-      // failure, so the non-conformant frame is reported as a non-keyframe.
-      {"P SPS P",
-       false},  // SPS after first VCL would indicate a new access unit.
+  static const char* test_cases[] = {
+    "AUD",  // No VCL present.
+    "AUD,SEI", // No VCL present.
+    "SPS PPS",  // No VCL present.
+    "SPS PPS AUD I",  // Parameter sets must come after AUD.
+    "SPSExt SPS P",  // SPS must come before SPSExt.
+    "SPS PPS SPSExt P",  // SPSExt must follow an SPS.
+    "EOSeq",  // EOSeq must come after a VCL.
+    "EOStr",  // EOStr must come after a VCL.
+    "I EOStr EOSeq",  // EOSeq must come before EOStr.
+    "I R14",  // Reserved14-18 must come before first VCL.
+    "I SEI",  // SEI must come before first VCL.
+    "P SPS P", // SPS after first VCL would indicate a new access unit.
   };
 
-  BitstreamConverter::AnalysisResult expected;
-  expected.is_conformant = false;
-
   for (size_t i = 0; i < arraysize(test_cases); ++i) {
     std::vector<uint8_t> buf;
     std::vector<SubsampleEntry> subsamples;
-    StringToAnnexB(test_cases[i].case_string, &buf, NULL);
-    expected.is_keyframe = test_cases[i].is_keyframe;
-    EXPECT_PRED2(AnalysesMatch,
-                 AVC::AnalyzeAnnexB(buf.data(), buf.size(), subsamples),
-                 expected)
-        << "'" << test_cases[i].case_string << "' failed";
+    StringToAnnexB(test_cases[i], &buf, NULL);
+    EXPECT_FALSE(AVC::IsValidAnnexB(buf.data(), buf.size(), subsamples))
+        << "'" << test_cases[i] << "' failed";
   }
 }
 
@@ -528,10 +442,6 @@
   avc_config.pps_list[0].push_back(0x56);
   avc_config.pps_list[0].push_back(0x78);
 
-  BitstreamConverter::AnalysisResult expected;
-  expected.is_conformant = true;
-  expected.is_keyframe = true;
-
   for (size_t i = 0; i < arraysize(test_cases); ++i) {
     std::vector<uint8_t> buf;
     std::vector<SubsampleEntry> subsamples;
@@ -540,9 +450,7 @@
 
     EXPECT_TRUE(AVC::InsertParamSetsAnnexB(avc_config, &buf, &subsamples))
         << "'" << test_cases[i].input << "' insert failed.";
-    EXPECT_PRED2(AnalysesMatch,
-                 AVC::AnalyzeAnnexB(buf.data(), buf.size(), subsamples),
-                 expected)
+    EXPECT_TRUE(AVC::IsValidAnnexB(buf.data(), buf.size(), subsamples))
         << "'" << test_cases[i].input << "' created invalid AnnexB.";
     EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples))
         << "'" << test_cases[i].input << "' generated unexpected output.";
diff --git a/media/formats/mp4/bitstream_converter.cc b/media/formats/mp4/bitstream_converter.cc
index 812f682..e6cd01a 100644
--- a/media/formats/mp4/bitstream_converter.cc
+++ b/media/formats/mp4/bitstream_converter.cc
@@ -7,13 +7,6 @@
 namespace media {
 namespace mp4 {
 
-BitstreamConverter::AnalysisResult::AnalysisResult(){};
-
-BitstreamConverter::AnalysisResult::AnalysisResult(const AnalysisResult& other)
-    : is_conformant(other.is_conformant), is_keyframe(other.is_keyframe) {}
-
-BitstreamConverter::AnalysisResult::~AnalysisResult() = default;
-
 BitstreamConverter::~BitstreamConverter() = default;
 
 }  // namespace mp4
diff --git a/media/formats/mp4/bitstream_converter.h b/media/formats/mp4/bitstream_converter.h
index a3c1d1de..3f95d172 100644
--- a/media/formats/mp4/bitstream_converter.h
+++ b/media/formats/mp4/bitstream_converter.h
@@ -10,8 +10,6 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/optional.h"
-#include "media/base/media_export.h"
 
 namespace media {
 
@@ -22,21 +20,9 @@
 // BitstreamConverter provides a unified interface for performing some common
 // bitstream conversions (e.g. H.264 MP4 bitstream to Annex B, and elementary
 // AAC stream to ADTS).
-class MEDIA_EXPORT BitstreamConverter
+class BitstreamConverter
     : public base::RefCountedThreadSafe<BitstreamConverter> {
  public:
-  // Describes the result of Analyze(). Not all analyses are implemented or
-  // enabled across mp4::BitstreamConverter implementations, hence the use of
-  // base::Optional<>.
-  struct AnalysisResult {
-    AnalysisResult();
-    AnalysisResult(const AnalysisResult&);
-    ~AnalysisResult();
-
-    base::Optional<bool> is_conformant;
-    base::Optional<bool> is_keyframe;
-  };
-
   // Converts a single frame/buffer |frame_buf| into the output format.
   // Returns true iff the conversion was successful.
   // |frame_buf| is an input/output parameter, it contains input frame data and
@@ -51,12 +37,11 @@
                             bool is_keyframe,
                             std::vector<SubsampleEntry>* subsamples) const = 0;
 
-  // Inspects an already converted frame for conformance. If conformant,
-  // inspects further to see if the converted frame appears to be a keyframe.
-  // Note, the checks may not be exhaustive (or implemented at all).
-  virtual AnalysisResult Analyze(
-      std::vector<uint8_t>* frame_buf,
-      std::vector<SubsampleEntry>* subsamples) const = 0;
+  // Checks a converted frame for conformance.
+  // Note: may return true even if the frame is not conformant; the checks may
+  // not be exhaustive (or implemented at all).
+  virtual bool IsValid(std::vector<uint8_t>* frame_buf,
+                       std::vector<SubsampleEntry>* subsamples) const = 0;
 
  protected:
   friend class base::RefCountedThreadSafe<BitstreamConverter>;
diff --git a/media/formats/mp4/hevc.cc b/media/formats/mp4/hevc.cc
index 8e8c8ea..ecf813d 100644
--- a/media/formats/mp4/hevc.cc
+++ b/media/formats/mp4/hevc.cc
@@ -137,13 +137,11 @@
 static const uint8_t kAnnexBStartCode[] = {0, 0, 0, 1};
 static const int kAnnexBStartCodeSize = 4;
 
-// static
 bool HEVC::InsertParamSetsAnnexB(
     const HEVCDecoderConfigurationRecord& hevc_config,
     std::vector<uint8_t>* buffer,
     std::vector<SubsampleEntry>* subsamples) {
-  DCHECK(HEVC::AnalyzeAnnexB(buffer->data(), buffer->size(), *subsamples)
-             .is_conformant.value_or(true));
+  DCHECK(HEVC::IsValidAnnexB(buffer->data(), buffer->size(), *subsamples));
 
   std::unique_ptr<H265Parser> parser(new H265Parser());
   const uint8_t* start = buffer->data();
@@ -181,12 +179,10 @@
   buffer->insert(config_insert_point,
                  param_sets.begin(), param_sets.end());
 
-  DCHECK(HEVC::AnalyzeAnnexB(buffer->data(), buffer->size(), *subsamples)
-             .is_conformant.value_or(true));
+  DCHECK(HEVC::IsValidAnnexB(buffer->data(), buffer->size(), *subsamples));
   return true;
 }
 
-// static
 bool HEVC::ConvertConfigToAnnexB(
     const HEVCDecoderConfigurationRecord& hevc_config,
     std::vector<uint8_t>* buffer) {
@@ -208,23 +204,17 @@
   return true;
 }
 
-// static
-BitstreamConverter::AnalysisResult HEVC::AnalyzeAnnexB(
-    const uint8_t* buffer,
-    size_t size,
-    const std::vector<SubsampleEntry>& subsamples) {
+// Verifies AnnexB NALU order according to section 7.4.2.4.4 of ISO/IEC 23008-2.
+bool HEVC::IsValidAnnexB(const uint8_t* buffer,
+                         size_t size,
+                         const std::vector<SubsampleEntry>& subsamples) {
   DCHECK(buffer);
 
-  BitstreamConverter::AnalysisResult result;
+  if (size == 0)
+    return true;
 
-  if (size == 0) {
-    result.is_conformant = true;
-    return result;
-  }
-
-  // TODO(servolk): Implement this, see https://crbug.com/527595. For now, we
-  // report that neither conformance nor keyframe analyses were performed.
-  return result;
+  // TODO(servolk): Implement this, see crbug.com/527595
+  return true;
 }
 
 HEVCBitstreamConverter::HEVCBitstreamConverter(
@@ -253,10 +243,10 @@
   return true;
 }
 
-BitstreamConverter::AnalysisResult HEVCBitstreamConverter::Analyze(
+bool HEVCBitstreamConverter::IsValid(
     std::vector<uint8_t>* frame_buf,
     std::vector<SubsampleEntry>* subsamples) const {
-  return HEVC::AnalyzeAnnexB(frame_buf->data(), frame_buf->size(), *subsamples);
+  return HEVC::IsValidAnnexB(frame_buf->data(), frame_buf->size(), *subsamples);
 }
 
 }  // namespace mp4
diff --git a/media/formats/mp4/hevc.h b/media/formats/mp4/hevc.h
index 87ec4ff..f3576f9 100644
--- a/media/formats/mp4/hevc.h
+++ b/media/formats/mp4/hevc.h
@@ -78,15 +78,14 @@
       std::vector<uint8_t>* buffer,
       std::vector<SubsampleEntry>* subsamples);
 
-  // Analyzes the contents of |buffer| for conformance to
-  // Section 7.4.2.4.4 of ISO/IEC 23008-2, and if conformant, further inspects
-  // |buffer| to report whether or not it looks like a keyframe.
+  // Verifies that the contents of |buffer| conform to
+  // Section 7.4.2.4.4 of ISO/IEC 23008-2.
   // |subsamples| contains the information about what parts of the buffer are
   // encrypted and which parts are clear.
-  static BitstreamConverter::AnalysisResult AnalyzeAnnexB(
-      const uint8_t* buffer,
-      size_t size,
-      const std::vector<SubsampleEntry>& subsamples);
+  // Returns true if |buffer| contains conformant Annex B data
+  static bool IsValidAnnexB(const uint8_t* buffer,
+                            size_t size,
+                            const std::vector<SubsampleEntry>& subsamples);
 };
 
 class HEVCBitstreamConverter : public BitstreamConverter {
@@ -99,9 +98,8 @@
                     bool is_keyframe,
                     std::vector<SubsampleEntry>* subsamples) const override;
 
-  AnalysisResult Analyze(
-      std::vector<uint8_t>* frame_buf,
-      std::vector<SubsampleEntry>* subsamples) const override;
+  bool IsValid(std::vector<uint8_t>* frame_buf,
+               std::vector<SubsampleEntry>* subsamples) const override;
 
  private:
   ~HEVCBitstreamConverter() override;
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc
index 3517906..dc7645a 100644
--- a/media/formats/mp4/mp4_stream_parser.cc
+++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -41,7 +41,6 @@
 
 const int kMaxEmptySampleLogs = 20;
 const int kMaxInvalidConversionLogs = 20;
-const int kMaxVideoKeyframeMismatchLogs = 10;
 
 // Caller should be prepared to handle return of Unencrypted() in case of
 // unsupported scheme.
@@ -91,8 +90,8 @@
       has_sbr_(has_sbr),
       has_flac_(has_flac),
       num_empty_samples_skipped_(0),
-      num_invalid_conversions_(0),
-      num_video_keyframe_mismatches_(0) {}
+      num_invalid_conversions_(0) {
+}
 
 MP4StreamParser::~MP4StreamParser() = default;
 
@@ -803,31 +802,12 @@
             << "Failed to prepare video sample for decode";
         return ParseResult::kError;
       }
-      BitstreamConverter::AnalysisResult analysis =
-          runs_->video_description().frame_bitstream_converter->Analyze(
-              &frame_buf, &subsamples);
-      // If conformance analysis was not actually performed, assume the frame is
-      // conformant.  If it was performed and found to be non-conformant, log
-      // it.
-      if (!analysis.is_conformant.value_or(true)) {
+      if (!runs_->video_description().frame_bitstream_converter->IsValid(
+              &frame_buf, &subsamples)) {
         LIMITED_MEDIA_LOG(DEBUG, media_log_, num_invalid_conversions_,
                           kMaxInvalidConversionLogs)
             << "Prepared video sample is not conformant";
       }
-
-      // Use |analysis.is_keyframe|, if it was actually determined, for logging
-      // if the analysis mismatches the container's keyframe metadata for
-      // |frame_buf|.
-      if (analysis.is_keyframe.has_value() &&
-          runs_->is_keyframe() != analysis.is_keyframe.value()) {
-        LIMITED_MEDIA_LOG(DEBUG, media_log_, num_video_keyframe_mismatches_,
-                          kMaxVideoKeyframeMismatchLogs)
-            << "ISO-BMFF container metadata for video frame indicates that the "
-               "frame is "
-            << (runs_->is_keyframe() ? "" : "not ")
-            << "a keyframe, but the video frame contents indicate the "
-               "opposite.";
-      }
     }
   }
 
diff --git a/media/formats/mp4/mp4_stream_parser.h b/media/formats/mp4/mp4_stream_parser.h
index 909bf55..45ee6f9 100644
--- a/media/formats/mp4/mp4_stream_parser.h
+++ b/media/formats/mp4/mp4_stream_parser.h
@@ -148,9 +148,6 @@
   // Tracks the number of MEDIA_LOGS for invalid bitstream conversion.
   int num_invalid_conversions_;
 
-  // Tracks the number of MEDIA_LOGS for video keyframe MP4<->frame mismatch.
-  int num_video_keyframe_mismatches_;
-
   DISALLOW_COPY_AND_ASSIGN(MP4StreamParser);
 };
 
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc
index ccb0800..5ce3fd8 100644
--- a/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -50,11 +50,7 @@
 }
 
 MATCHER_P(ErrorLog, error_string, "") {
-  return CONTAINS_STRING(arg, error_string) && CONTAINS_STRING(arg, "error");
-}
-
-MATCHER_P(DebugLog, debug_string, "") {
-  return CONTAINS_STRING(arg, debug_string) && CONTAINS_STRING(arg, "debug");
+  return CONTAINS_STRING(arg, error_string);
 }
 
 class MP4StreamParserTest : public testing::Test {
@@ -291,51 +287,6 @@
       512);
 }
 
-TEST_F(MP4StreamParserTest, AVC_KeyAndNonKeyframeness_Match_Container) {
-  // Both AVC video frames' keyframe-ness metadata matches the MP4:
-  // Frame 0: AVC IDR, trun.first_sample_flags: sync sample that doesn't
-  //          depend on others.
-  // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: not sync sample, depends
-  //          on others.
-  // This is the base case; see also the "Mismatches" cases, below.
-  auto params = GetDefaultInitParametersExpectations();
-  params.detected_audio_track_count = 0;
-  InitializeParserWithInitParametersExpectations(params);
-  ParseMP4File("bear-640x360-v-2frames_frag.mp4", 512);
-}
-
-TEST_F(MP4StreamParserTest, AVC_Keyframeness_Mismatches_Container) {
-  // The first AVC video frame's keyframe-ness metadata matches the MP4:
-  // Frame 0: AVC IDR, trun.first_sample_flags: NOT sync sample, DEPENDS on
-  //          others.
-  // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: not sync sample, depends
-  //          on others.
-  auto params = GetDefaultInitParametersExpectations();
-  params.detected_audio_track_count = 0;
-  InitializeParserWithInitParametersExpectations(params);
-  EXPECT_MEDIA_LOG(DebugLog(
-      "ISO-BMFF container metadata for video frame indicates that the frame is "
-      "not a keyframe, but the video frame contents indicate the opposite."));
-  ParseMP4File("bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4",
-               512);
-}
-
-TEST_F(MP4StreamParserTest, AVC_NonKeyframeness_Mismatches_Container) {
-  // The second AVC video frame's keyframe-ness metadata matches the MP4:
-  // Frame 0: AVC IDR, trun.first_sample_flags: sync sample that doesn't
-  //          depend on others.
-  // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: SYNC sample, DOES NOT
-  //          depend on others.
-  auto params = GetDefaultInitParametersExpectations();
-  params.detected_audio_track_count = 0;
-  InitializeParserWithInitParametersExpectations(params);
-  EXPECT_MEDIA_LOG(DebugLog(
-      "ISO-BMFF container metadata for video frame indicates that the frame is "
-      "a keyframe, but the video frame contents indicate the opposite."));
-  ParseMP4File("bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4",
-               512);
-}
-
 TEST_F(MP4StreamParserTest, MPEG2_AAC_LC) {
   InSequence s;
   std::set<int> audio_object_types;
diff --git a/media/test/data/README b/media/test/data/README
index 4347682..2568798 100644
--- a/media/test/data/README
+++ b/media/test/data/README
@@ -74,20 +74,6 @@
 vorbis-packet-2  - timestamp: 0ms, duration: 0ms
 vorbis-packet-3  - timestamp: 2902ms, duration: 0ms
 
-// MSE MP4 keyframe-metadata versus encoded AVC keyframe-ness test media:
-bear-640x360-v-2frames_frag.mp4 - Just first 2 video frames of bear-640x360-v_frag.mp4, created with:
-  ffmpeg -i bear-640x360-v_frag.mp4 -vcodec copy -movflags frag_keyframe+empty_moov+default_base_moof \
-    -vframes 2 bear-640x360-v-2frames_frag.mp4
-  It's 1 keyframe + 1 non-keyframe, with container's frame keyframe-ness correct.
-bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4
-  This is bear-640x360-v-2frames_frag.mp4, with manually updated trun.first_sample_flags:
-    s/0x02000000/0x01010000 (first frame is non-sync-sample, depends on another
-    frame, mismatches compressed h264 first frame's keyframe-ness).
-bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4
-  This is bear-640x360-v-2frames_frag.mp4, with manually updated tfhd.default_sample_flags:
-    s/0x01010000/0x02000000 (second frame is sync-sample, doesn't depend on other
-    frames, mismatches compressed h264 second frame's nonkeyframe-ness).
-
 // 10-bit test file(s)
 bear-320x180-hi10p.mp4
 bear-320x240-vp9_profile2.webm - VP9 encoded video with profile 2 (10-bit, 4:2:0). Codec string: vp09.02.10.10.01.02.02.02.00.
diff --git a/media/test/data/bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4 b/media/test/data/bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4
deleted file mode 100644
index dac67566..0000000
--- a/media/test/data/bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4
+++ /dev/null
Binary files differ
diff --git a/media/test/data/bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4 b/media/test/data/bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4
deleted file mode 100644
index 3dddd57..0000000
--- a/media/test/data/bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4
+++ /dev/null
Binary files differ
diff --git a/media/test/data/bear-640x360-v-2frames_frag.mp4 b/media/test/data/bear-640x360-v-2frames_frag.mp4
deleted file mode 100644
index 3d21750..0000000
--- a/media/test/data/bear-640x360-v-2frames_frag.mp4
+++ /dev/null
Binary files differ
diff --git a/mojo/public/cpp/system/README.md b/mojo/public/cpp/system/README.md
index 0e6d72df..d1f6889 100644
--- a/mojo/public/cpp/system/README.md
+++ b/mojo/public/cpp/system/README.md
@@ -95,8 +95,8 @@
 
 ``` cpp
 mojo::DataPipe pipe;
-mojo::ScopedDataPipeProducerHandle producer = std::move(pipe.producer);
-mojo::ScopedDataPipeConsumerHandle consumer = std::move(pipe.consumer);
+mojo::ScopedDataPipeProducerHandle producer = std::move(pipe.producer_handle);
+mojo::ScopedDataPipeConsumerHandle consumer = std::move(pipe.consumer_handle);
 
 // Or alternatively:
 mojo::ScopedDataPipeProducerHandle producer;
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 1fbe018..cbf36fe 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -54573,6 +54573,9 @@
     { "name": "skypeassets.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
     { "name": "teams.microsoft.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
     { "name": "trouter.io", "policy": "custom", "mode": "force-https", "include_subdomains": true },
+    { "name": "www.zdnet.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
+    { "name": "downloads.zdnet.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
+    { "name": "www.techrepublic.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
     // IP Address
     { "name": "1.0.0.1", "policy": "custom", "mode": "force-https", "include_subdomains": false },
     // No subdomains
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 07d47adf..6cedcc8b 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -1501,6 +1501,12 @@
       size_t num_streams = GetNumActiveStreams();
       if (num_streams > 0)
         histogram->AddCount(error, num_streams);
+    } else {
+      if (error == quic::QUIC_HANDSHAKE_TIMEOUT) {
+        UMA_HISTOGRAM_BOOLEAN(
+            "Net.QuicSession.HandshakeTimeout.PathDegradingDetected",
+             connection()->IsPathDegrading());
+      }
     }
     base::UmaHistogramSparse("Net.QuicSession.ConnectionCloseErrorCodeClient",
                              error);
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn
index 6fca9dc..e0a4627 100644
--- a/remoting/host/linux/BUILD.gn
+++ b/remoting/host/linux/BUILD.gn
@@ -103,22 +103,24 @@
   }
 }
 
-source_set("x11") {
-  sources = [
-    "unicode_to_keysym.cc",
-    "unicode_to_keysym.h",
-    "x11_character_injector.cc",
-    "x11_character_injector.h",
-    "x11_keyboard_impl.cc",
-    "x11_keyboard_impl.h",
-    "x11_util.cc",
-    "x11_util.h",
-    "x_server_clipboard.cc",
-    "x_server_clipboard.h",
-  ]
-  deps = [
-    "//third_party/webrtc/modules/desktop_capture",
-  ]
+if (use_x11) {
+  source_set("x11") {
+    sources = [
+      "unicode_to_keysym.cc",
+      "unicode_to_keysym.h",
+      "x11_character_injector.cc",
+      "x11_character_injector.h",
+      "x11_keyboard_impl.cc",
+      "x11_keyboard_impl.h",
+      "x11_util.cc",
+      "x11_util.h",
+      "x_server_clipboard.cc",
+      "x_server_clipboard.h",
+    ]
+    deps = [
+      "//third_party/webrtc/modules/desktop_capture",
+    ]
+  }
 }
 
 executable("remoting_native_messaging_host") {
@@ -160,7 +162,10 @@
   ]
 
   if (!use_x11) {
-    sources -= [ "unicode_to_keysym_unittest.cc" ]
+    sources -= [
+      "unicode_to_keysym_unittest.cc",
+      "x_server_clipboard_unittest.cc",
+    ]
   }
 
   configs += [ "//remoting/build/config:version" ]
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index 41c04bbc..ab603947 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -40,7 +40,9 @@
 };
 
 // Wrapper to manage libcap2's cap_t type.
-typedef std::unique_ptr<typeof(*((cap_t)0)), CapFreeDeleter> ScopedCap;
+typedef std::unique_ptr<std::remove_reference<decltype(*((cap_t)0))>::type,
+                        CapFreeDeleter>
+    ScopedCap;
 
 bool WorkingDirectoryIsRoot() {
   char current_dir[PATH_MAX];
diff --git a/sandbox/linux/suid/process_util_linux.c b/sandbox/linux/suid/process_util_linux.c
index d28d576..0008331 100644
--- a/sandbox/linux/suid/process_util_linux.c
+++ b/sandbox/linux/suid/process_util_linux.c
@@ -8,7 +8,9 @@
 // Needed for O_DIRECTORY, must be defined before fcntl.h is included
 // (and it can be included earlier than the explicit #include below
 // in some versions of glibc).
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include "sandbox/linux/suid/process_util.h"
 
diff --git a/sandbox/linux/suid/sandbox.c b/sandbox/linux/suid/sandbox.c
index 66f68ef..854819b 100644
--- a/sandbox/linux/suid/sandbox.c
+++ b/sandbox/linux/suid/sandbox.c
@@ -6,7 +6,9 @@
 
 #include "sandbox/linux/suid/common/sandbox.h"
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include <asm/unistd.h>
 #include <errno.h>
 #include <fcntl.h>
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h
index cb467ed..7d1662a0 100644
--- a/services/metrics/public/cpp/ukm_recorder.h
+++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -18,6 +18,7 @@
 
 class IOSChromePasswordManagerClient;
 class MediaEngagementSession;
+class PlatformNotificationServiceImpl;
 class PluginInfoHostImpl;
 
 namespace autofill {
@@ -27,11 +28,11 @@
 namespace blink {
 class Document;
 class NavigatorVR;
-}
+}  // namespace blink
 
 namespace cc {
 class UkmManager;
-}
+}  // namespace cc
 
 namespace content {
 class CrossSiteDocumentResourceHandler;
@@ -41,7 +42,7 @@
 
 namespace download {
 class DownloadUkmHelper;
-}
+}  // namespace download
 
 namespace password_manager {
 class PasswordManagerMetricsRecorder;
@@ -49,11 +50,11 @@
 
 namespace payments {
 class JourneyLogger;
-}
+}  // namespace payments
 
 namespace metrics {
 class UkmRecorderInterface;
-}
+}  // namespace metrics
 
 namespace media {
 class MediaMetricsProvider;
@@ -63,7 +64,7 @@
 
 namespace translate {
 class TranslateRankerImpl;
-}
+}  // namespace translate
 
 namespace ukm {
 
@@ -73,7 +74,7 @@
 namespace internal {
 class SourceUrlRecorderWebContentsObserver;
 class SourceUrlRecorderWebStateObserver;
-}
+}  // namespace internal
 
 // This feature controls whether UkmService should be created.
 METRICS_EXPORT extern const base::Feature kUkmFeature;
@@ -104,6 +105,7 @@
   friend DelegatingUkmRecorder;
   friend IOSChromePasswordManagerClient;
   friend MediaEngagementSession;
+  friend PlatformNotificationServiceImpl;
   friend PluginInfoHostImpl;
   friend TestRecordingHelper;
   friend autofill::TestAutofillClient;
diff --git a/skia/OWNERS b/skia/OWNERS
index 86f39bb..122fa73 100644
--- a/skia/OWNERS
+++ b/skia/OWNERS
@@ -4,7 +4,6 @@
 bungeman@google.com
 djsollen@google.com
 fmalita@chromium.org
-junov@chromium.org
 jvanverth@google.com
 mtklein@chromium.org
 reed@google.com
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index f532c1c..8b72aef9 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -365,7 +365,7 @@
           "--browser=android-chromium",
           "--upload-results",
           "--run-ref-build",
-          "--test-shard-map-filename=pixel2_7_shard_map.json"
+          "--test-shard-map-filename=android_pixel2_shard_map.json"
         ],
         "isolate_name": "performance_test_suite",
         "merge": {
@@ -415,7 +415,7 @@
           "--browser=android-webview",
           "--upload-results",
           "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk",
-          "--test-shard-map-filename=pixel2_webview_7_shard_map.json"
+          "--test-shard-map-filename=android_pixel2_webview_shard_map.json"
         ],
         "isolate_name": "performance_webview_test_suite",
         "merge": {
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter
index c4293c7..b322cb8c 100644
--- a/testing/buildbot/filters/mash.browser_tests.filter
+++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -40,8 +40,6 @@
 BrowserNonClientFrameViewAshTest.FrameMinSizeIsUpdated*
 
 # Direct access to ash window frames, tablet mode, overview mode, etc.
--ExtensionUninstallDialogViewBrowserTest.BookmarkAppWindowAshCrash
--HostedAppNonClientFrameViewAshTest.*
 -HomeLauncherBrowserNonClientFrameViewAshTest.*
 
 BrowserNonClientFrameViewAshTest.NonClientHitTest*
@@ -51,9 +49,9 @@
 -ImmersiveModeBrowserViewTest.TestCaptionButtonsReceiveEventsInAppImmersiveMode*
 -ImmersiveModeBrowserViewTest.TestCaptionButtonsReceiveEventsInBrowserImmersiveMode*
 -ImmersiveModeControllerAshHostedAppBrowserTest.*
--FileDisplay/FilesAppBrowserTest.Test/fileDisplayDownloads_TabletMode
--FileDisplay/FilesAppBrowserTest.Test/fileDisplayDrive_TabletMode
--QuickView/FilesAppBrowserTest.Test/openQuickView_TabletMode
+
+# Null immersive_fullscreen_controller_.
+-ChromeNativeAppWindowViewsAuraAshBrowserTest.*
 
 # ash::Shell access from ChromeViewsDelegate::CreateDefaultNonClientFrameView()
 # e.g. from chromeos::CaptivePortalWindowProxy::Show().
@@ -81,9 +79,6 @@
 # Need screenshot support. http://crbug.com/706246
 -ChromeScreenshotGrabberBrowserTest.*
 
-# Null immersive_fullscreen_controller_.
--ChromeNativeAppWindowViewsAuraAshBrowserTest.*
-
 # Flaky. SessionRestoreStatsCollector::Observe failure. crbug.com/785298
 # session_restore_stats_collector.cc(210) Check failed: 0u < loading_tab_count_ (0 vs. 0)
 -ContinueWhereILeftOffTest.*
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py
index a491fcd..e7d67082 100755
--- a/testing/scripts/run_performance_tests.py
+++ b/testing/scripts/run_performance_tests.py
@@ -119,10 +119,10 @@
   if stories:
     if 'begin' in stories.keys():
       per_benchmark_args.append(
-          ('--experimental-story-shard-begin-index=%d' % stories['begin']))
+          ('--story-shard-begin-index=%d' % stories['begin']))
     if 'end' in stories.keys():
       per_benchmark_args.append(
-          ('--experimental-story-shard-end-index=%d' % stories['end']))
+          ('--story-shard-end-index=%d' % stories['end']))
 
   # We don't care exactly what these are. In particular, the perf results
   # could be any format (chartjson, legacy, histogram). We just pass these
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 6d37ab4..3169640 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -73,7 +73,6 @@
 crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure ]
 crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure ]
 crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure ]
-crbug.com/591099 css1/box_properties/float_on_text_elements.html [ Failure ]
 crbug.com/591099 css3/blending/mix-blend-mode-composited-reason-children.html [ Failure ]
 crbug.com/591099 css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html [ Failure ]
 crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
@@ -86,7 +85,6 @@
 crbug.com/591099 editing/selection/5232159.html [ Failure ]
 crbug.com/591099 editing/selection/continuations-with-move-caret-to-boundary.html [ Failure ]
 crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ]
-crbug.com/591099 editing/selection/select-line-break-with-opposite-directionality.html [ Failure ]
 crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.worker.html [ Timeout ]
@@ -530,9 +528,7 @@
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
 crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
-crbug.com/591099 fast/forms/select/select-initial-position.html [ Failure ]
 crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Pass Timeout ]
-crbug.com/591099 fast/frames/iframe-with-frameborder.html [ Failure ]
 crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ]
 crbug.com/591099 fast/inline/absolute-positioned-block-in-centred-block.html [ Failure ]
 crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ]
@@ -546,7 +542,6 @@
 crbug.com/714962 fast/inline/outline-offset.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
 crbug.com/591099 fast/overflow/recompute-overflow-of-layout-root-container.html [ Failure ]
-crbug.com/591099 fast/parser/001.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-html.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-xhtml.xhtml [ Failure ]
 crbug.com/591099 fast/replaced/table-replaced-element.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 23a53f79..e42b1ea0 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -399,8 +399,18 @@
 # can take almost 6 seconds to run, and it often times out on the Mac bots.
 crbug.com/833215 external/wpt/accelerometer/Accelerometer.https.html [ Slow ]
 
-crbug.com/861670 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ] 
-
 crbug.com/864887 [ Mac ] fast/scroll-snap/snaps-after-scrollbar-scrolling.html [ Slow ]
 
 crbug.com/865262 [ Mac ] media/controls/text-track-menu-pointer-selection.html [ Slow ]
+
+### virtual/gpu/fast/canvas/ blending layout tests are slow
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blend-image.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-color.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-gradient.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-image.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Slow ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Slow ]
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 76c80984..da1a2c3 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -4658,7 +4658,7 @@
 crbug.com/866785 [ Mac ] fast/table/backgr_border-table-quirks.html [ Failure Pass ]
 crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image-2.html [ Failure Pass ]
 crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image.html [ Failure Pass ]
-crbug.com/866785 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/text-track-menu-pointer-selection.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/text-track-menu-pointer-selection.html [ Failure Pass Timeout ]
 
 ### fast/canvas/color-space/ + virtual/gpu/..., color management and transparency.
 crbug.com/859102 fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Pass Failure ]
@@ -4668,18 +4668,12 @@
 crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-p3.html [ Pass Failure ]
 crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-rec2020.html [ Pass Failure ]
 
-### virtual/gpu/fast/canvas/ blending layout tests timeout
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blend-image.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-color.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-gradient.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-image.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass Timeout ]
-crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Pass Timeout ]
-
 # Sheriff 2018-07-24
 crbug.com/866965 [ Linux ] virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/interfaces-sw.https.html [ Timeout Pass ]
 crbug.com/866965 [ Linux ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/interfaces-sw.https.html [ Timeout Pass ]
 crbug.com/866965 [ Linux ] virtual/service-worker-servicification/external/wpt/service-workers/service-worker/interfaces-sw.https.html [ Timeout Pass ]
+
+crbug.com/867532 [ Linux ] external/wpt/workers/modules/dedicated-worker-import-data-url.any.worker.html [ Timeout Pass ]
+crbug.com/867532 [ Linux ] external/wpt/workers/modules/dedicated-worker-import.any.worker.html [ Timeout Pass ]
+crbug.com/867628 [ Mac ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-click-hyperlink.html [ Failure Pass ]
+crbug.com/867628 [ Mac ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/css1/box_properties/float_on_text_elements.html b/third_party/WebKit/LayoutTests/css1/box_properties/float_on_text_elements.html
index a2d75eb..5b358a13 100644
--- a/third_party/WebKit/LayoutTests/css1/box_properties/float_on_text_elements.html
+++ b/third_party/WebKit/LayoutTests/css1/box_properties/float_on_text_elements.html
@@ -1,4 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<!DOCTYPE HTML>
 <HTML>
 <HEAD>
 <TITLE>CSS1 Test Suite: 5.5.25 float</TITLE>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 68e73cf1..b08feee 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -5749,6 +5749,12 @@
      {}
     ]
    ],
+   "pointerlock/mouse_buttons_back_forward-manual.html": [
+    [
+     "/pointerlock/mouse_buttons_back_forward-manual.html",
+     {}
+    ]
+   ],
    "pointerlock/movementX_Y_basic-manual.html": [
     [
      "/pointerlock/movementX_Y_basic-manual.html",
@@ -199055,6 +199061,12 @@
      {}
     ]
    ],
+   "css/cssom/computed-style-005.html": [
+    [
+     "/css/cssom/computed-style-005.html",
+     {}
+    ]
+   ],
    "css/cssom/computed-style-set-property.html": [
     [
      "/css/cssom/computed-style-set-property.html",
@@ -343232,6 +343244,10 @@
    "55010cf90dc7fc2ef8ec6cbd13d1ec947a823aed",
    "testharness"
   ],
+  "css/cssom/computed-style-005.html": [
+   "6bf8f129c83cb014918b3af9ccb296de4fa67577",
+   "testharness"
+  ],
   "css/cssom/computed-style-set-property.html": [
    "cb05ff525eb659d43bf234d932fd860795959c9e",
    "testharness"
@@ -390052,6 +390068,10 @@
    "0838cc19db0518e115adbe07f01b195dc8b5db6f",
    "testharness"
   ],
+  "pointerlock/mouse_buttons_back_forward-manual.html": [
+   "0801af4a1f9fc2664a53d7a12d4cbec0092cd1de",
+   "manual"
+  ],
   "pointerlock/movementX_Y_basic-manual.html": [
    "45eea8be5393873e6c02331b4aff6f4622be692f",
    "manual"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/computed-style-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/computed-style-005.html
new file mode 100644
index 0000000..998f70eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/computed-style-005.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <title>CSS Test: getComputedStyle on blocks with auto margins</title>
+  <link rel="author" title="Brad Werth" href="mailto:bwerth@mozilla.com">
+  <link rel="help" href="https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle" />
+  <meta name="assert" content="getComputedStyle produces pixel values for margin: auto blocks">
+  <script src="/resources/testharness.js" type="text/javascript"></script>
+  <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+  <style>
+    x {
+      display: block;
+      position: relative;
+      background: grey;
+      width: 60px;
+      height: 10px;
+    }
+    y {
+      display: block;
+      background: blue;
+      width: 40px;
+      height: 10px;
+      margin: auto;
+    }
+
+    #absolute {
+      position: absolute;
+      left: 0;
+      right: 0;
+    }
+    #relative {
+      position: relative;
+    }
+  </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <x><y id="absolute"></y></x>
+ <x><y id="relative"></y></x>
+ <script type="text/javascript">
+   let idsToTest = [
+     "absolute",
+     "relative",
+   ];
+
+   for (let id of idsToTest) {
+     let elem = document.getElementById(id);
+     let elemStyle = window.getComputedStyle(elem);
+
+     test(function() {
+       assert_equals(elemStyle.getPropertyValue("margin-left"), "10px");
+       assert_equals(elemStyle.getPropertyValue("margin-right"), "10px");
+     }, id + "_computed_margins", {
+       assert: id + "-positioned element's auto margins should be resolved to 10px."
+     });
+
+     test(function() {
+       assert_equals(elemStyle.getPropertyValue("left"), "0px");
+       assert_equals(elemStyle.getPropertyValue("right"), "0px");
+     }, id + "_computed_left_and_right", {
+       assert: id + "-positioned element should have a left and right of 0px (as authored)."
+     });
+   }
+ </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
index 224befd..7ed9332b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
@@ -102,7 +102,7 @@
   // Test methods.
   setXRPresentationFrameData(poseMatrix, views) {
     if (poseMatrix == null) {
-      this.presentation_provider_.pose_ = null;
+      this.pose_ = null;
     } else {
       this.setPoseFromMatrix(poseMatrix);
     }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/select-initial-position.html b/third_party/WebKit/LayoutTests/fast/forms/select/select-initial-position.html
index 7e24851..c14b1db 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/select/select-initial-position.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/select/select-initial-position.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <html>
 
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/frames/iframe-with-frameborder.html b/third_party/WebKit/LayoutTests/fast/frames/iframe-with-frameborder.html
index 40574731..8bf414c 100644
--- a/third_party/WebKit/LayoutTests/fast/frames/iframe-with-frameborder.html
+++ b/third_party/WebKit/LayoutTests/fast/frames/iframe-with-frameborder.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 This iframe should have a border.<br>
 
 <iframe frameborder="1" src="about:blank"></iframe>
diff --git a/third_party/WebKit/LayoutTests/fast/parser/001.html b/third_party/WebKit/LayoutTests/fast/parser/001.html
index 9ee3581..934d792 100644
--- a/third_party/WebKit/LayoutTests/fast/parser/001.html
+++ b/third_party/WebKit/LayoutTests/fast/parser/001.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <dir>One
 <dir>Two
 <dir>Three
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
index 942e083..1df9445d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Background on 'table'</title>
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
index 595c55d..7c6a345 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Background on 'table'</title>
diff --git a/third_party/WebKit/LayoutTests/fast/table/dynamic-descendant-percentage-height.html b/third_party/WebKit/LayoutTests/fast/table/dynamic-descendant-percentage-height.html
index c296dc9..dec7478 100644
--- a/third_party/WebKit/LayoutTests/fast/table/dynamic-descendant-percentage-height.html
+++ b/third_party/WebKit/LayoutTests/fast/table/dynamic-descendant-percentage-height.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <script>
     if (window.testRunner)
         testRunner.waitUntilDone();
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_on_text_elements-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_on_text_elements-expected.txt
index 391908c..11767590 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_on_text_elements-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/css1/box_properties/float_on_text_elements-expected.txt
@@ -26,7 +26,7 @@
         LayoutImage {IMG} at (0,80) size 15x15
         LayoutText {#text} at (15,80) size 4x19
           text run at (15,80) width 4: " "
-        LayoutBR {BR} at (19,95) size 0x0
+        LayoutBR {BR} at (19,80) size 0x19
       LayoutBlockFlow (anonymous) at (0,256) size 769x120
         LayoutBlockFlow (floating) {P} at (0,0) size 384.50x120 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 384x119
@@ -39,7 +39,7 @@
         LayoutImage {IMG} at (384.50,0) size 15x15
         LayoutText {#text} at (399,0) size 5x19
           text run at (399,0) width 5: " "
-        LayoutBR {BR} at (403,15) size 1x0
+        LayoutBR {BR} at (403,0) size 1x19
       LayoutBlockFlow (anonymous) at (0,394) size 769x120
         LayoutBlockFlow (floating) {P} at (384.50,0) size 384.50x120 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 384x119
@@ -52,7 +52,7 @@
         LayoutImage {IMG} at (0,0) size 15x15
         LayoutText {#text} at (15,0) size 4x19
           text run at (15,0) width 4: " "
-        LayoutBR {BR} at (19,15) size 0x0
+        LayoutBR {BR} at (19,0) size 0x19
       LayoutBlockFlow {P} at (0,532) size 769x60
         LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
           LayoutText {#text} at (0,0) size 21x36
@@ -195,7 +195,7 @@
                 LayoutImage {IMG} at (0,80) size 15x15
                 LayoutText {#text} at (15,80) size 4x19
                   text run at (15,80) width 4: " "
-                LayoutBR {BR} at (19,95) size 0x0
+                LayoutBR {BR} at (19,80) size 0x19
               LayoutBlockFlow (anonymous) at (4,260) size 747x120
                 LayoutBlockFlow (floating) {P} at (0,0) size 373.50x120 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 373x119
@@ -208,7 +208,7 @@
                 LayoutImage {IMG} at (373.50,0) size 15x15
                 LayoutText {#text} at (388,0) size 5x19
                   text run at (388,0) width 5: " "
-                LayoutBR {BR} at (392,15) size 1x0
+                LayoutBR {BR} at (392,0) size 1x19
               LayoutBlockFlow (anonymous) at (4,398) size 747x120
                 LayoutBlockFlow (floating) {P} at (373.50,0) size 373.50x120 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 373x119
@@ -221,7 +221,7 @@
                 LayoutImage {IMG} at (0,0) size 15x15
                 LayoutText {#text} at (15,0) size 4x19
                   text run at (15,0) width 4: " "
-                LayoutBR {BR} at (19,15) size 0x0
+                LayoutBR {BR} at (19,0) size 0x19
               LayoutBlockFlow {P} at (4,536) size 747x60
                 LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
                   LayoutText {#text} at (0,0) size 21x36
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/select-initial-position-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/select-initial-position-expected.txt
index c396e62..0382ada6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/select-initial-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/select-initial-position-expected.txt
@@ -1,49 +1,49 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x409
+  LayoutBlockFlow {HTML} at (0,0) size 800x409
+    LayoutBlockFlow {BODY} at (8,8) size 784x393
       LayoutText {#text} at (0,0) size 93x19
         text run at (0,0) width 93: "initial selected:"
-      LayoutBR {BR} at (93,15) size 0x0
+      LayoutBR {BR} at (93,0) size 0x19
       LayoutText {#text} at (155,71) size 4x19
         text run at (155,71) width 4: " "
-      LayoutBR {BR} at (159,86) size 0x0
+      LayoutBR {BR} at (159,71) size 0x19
       LayoutText {#text} at (0,91) size 161x19
         text run at (0,91) width 161: "dynamic selected change:"
-      LayoutBR {BR} at (161,106) size 0x0
+      LayoutBR {BR} at (161,91) size 0x19
       LayoutText {#text} at (155,162) size 4x19
         text run at (155,162) width 4: " "
-      LayoutBR {BR} at (159,177) size 0x0
+      LayoutBR {BR} at (159,162) size 0x19
       LayoutText {#text} at (0,182) size 211x19
         text run at (0,182) width 211: "dynamic insert of selected option:"
-      LayoutBR {BR} at (211,197) size 0x0
+      LayoutBR {BR} at (211,182) size 0x19
       LayoutText {#text} at (155,253) size 4x19
         text run at (155,253) width 4: " "
-      LayoutBR {BR} at (159,268) size 0x0
+      LayoutBR {BR} at (159,253) size 0x19
       LayoutText {#text} at (0,273) size 93x19
         text run at (0,273) width 93: "initial selected:"
-      LayoutBR {BR} at (93,288) size 0x0
+      LayoutBR {BR} at (93,273) size 0x19
       LayoutMenuList {SELECT} at (0,293) size 156x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
             text run at (4,1) width 134: "this should be selected"
       LayoutText {#text} at (156,293) size 4x19
         text run at (156,293) width 4: " "
-      LayoutBR {BR} at (160,308) size 0x0
+      LayoutBR {BR} at (160,293) size 0x19
       LayoutText {#text} at (0,313) size 161x19
         text run at (0,313) width 161: "dynamic selected change:"
-      LayoutBR {BR} at (161,328) size 0x0
+      LayoutBR {BR} at (161,313) size 0x19
       LayoutMenuList {SELECT} at (0,333) size 156x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
             text run at (4,1) width 134: "this should be selected"
       LayoutText {#text} at (156,333) size 4x19
         text run at (156,333) width 4: " "
-      LayoutBR {BR} at (160,348) size 0x0
+      LayoutBR {BR} at (160,333) size 0x19
       LayoutText {#text} at (0,353) size 211x19
         text run at (0,353) width 211: "dynamic insert of selected option:"
-      LayoutBR {BR} at (211,368) size 0x0
+      LayoutBR {BR} at (211,353) size 0x19
       LayoutMenuList {SELECT} at (0,373) size 156x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-with-frameborder-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-with-frameborder-expected.txt
index d2737013..775c4391 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-with-frameborder-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/frames/iframe-with-frameborder-expected.txt
@@ -1,23 +1,23 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x549
+  LayoutBlockFlow {HTML} at (0,0) size 800x549
+    LayoutBlockFlow {BODY} at (8,8) size 784x533
       LayoutText {#text} at (0,0) size 211x19
         text run at (0,0) width 211: "This iframe should have a border."
-      LayoutBR {BR} at (211,15) size 0x0
+      LayoutBR {BR} at (211,0) size 0x19
       LayoutText {#text} at (304,159) size 4x19
         text run at (304,159) width 4: " "
       LayoutBR {BR} at (0,0) size 0x0
       LayoutText {#text} at (0,179) size 146x19
         text run at (0,179) width 146: "This iframe should not."
-      LayoutBR {BR} at (146,194) size 0x0
+      LayoutBR {BR} at (146,179) size 0x19
       LayoutText {#text} at (300,334) size 4x19
         text run at (300,334) width 4: " "
-      LayoutBR {BR} at (304,349) size 0x0
+      LayoutBR {BR} at (304,334) size 0x19
       LayoutText {#text} at (0,354) size 215x19
         text run at (0,354) width 215: "This iframe should have a border. "
-      LayoutBR {BR} at (215,369) size 0x0
+      LayoutBR {BR} at (215,354) size 0x19
       LayoutText {#text} at (0,0) size 0x0
 layer at (8,28) size 304x154
   LayoutIFrame {IFRAME} at (0,20) size 304x154 [border: (2px inset #EEEEEE)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.png
index fc002793..546483b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.txt
index 7f45351c..05359e4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/parser/001-expected.txt
@@ -1,8 +1,8 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x583
+  LayoutBlockFlow {HTML} at (0,0) size 800x583
+    LayoutBlockFlow {BODY} at (8,16) size 784x559
       LayoutBlockFlow {DIR} at (0,0) size 784x112
         LayoutBlockFlow (anonymous) at (40,0) size 744x20
           LayoutText {#text} at (0,0) size 27x19
@@ -39,5 +39,5 @@
           LayoutText {#text} at (0,0) size 234x19
             text run at (0,0) width 234: "Now we're back to nonbreaking text."
         LayoutText {#text} at (0,0) size 0x0
-layer at (8,152) size 300x300
+layer at (8,160) size 300x300
   LayoutEmbeddedObject {OBJECT} at (0,16) size 300x300 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
index c6fa676..60f5a79 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-expected.png
index 5ca7612..edfe5321 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_border-table-quirks-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/dynamic-descendant-percentage-height-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/dynamic-descendant-percentage-height-expected.png
index 1a714328..c173a48 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/dynamic-descendant-percentage-height-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/dynamic-descendant-percentage-height-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css1/box_properties/float_on_text_elements-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/css1/box_properties/float_on_text_elements-expected.txt
index 0d664fd..20628d5 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css1/box_properties/float_on_text_elements-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/css1/box_properties/float_on_text_elements-expected.txt
@@ -26,7 +26,7 @@
         LayoutImage {IMG} at (0,72) size 15x15
         LayoutText {#text} at (15,73) size 4x18
           text run at (15,73) width 4: " "
-        LayoutBR {BR} at (19,87) size 0x0
+        LayoutBR {BR} at (19,73) size 0x18
       LayoutBlockFlow (anonymous) at (0,235) size 769x108
         LayoutBlockFlow (floating) {P} at (0,0) size 384.50x108 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 385x108
@@ -39,7 +39,7 @@
         LayoutImage {IMG} at (384.50,0) size 15x15
         LayoutText {#text} at (399,1) size 5x18
           text run at (399,1) width 5: " "
-        LayoutBR {BR} at (403,15) size 1x0
+        LayoutBR {BR} at (403,1) size 1x18
       LayoutBlockFlow (anonymous) at (0,361) size 769x108
         LayoutBlockFlow (floating) {P} at (384.50,0) size 384.50x108 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 385x108
@@ -52,7 +52,7 @@
         LayoutImage {IMG} at (0,0) size 15x15
         LayoutText {#text} at (15,1) size 4x18
           text run at (15,1) width 4: " "
-        LayoutBR {BR} at (19,15) size 0x0
+        LayoutBR {BR} at (19,1) size 0x18
       LayoutBlockFlow {P} at (0,487) size 769x72
         LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
           LayoutText {#text} at (0,0) size 22x37
@@ -199,7 +199,7 @@
                 LayoutImage {IMG} at (0,72) size 15x15
                 LayoutText {#text} at (15,73) size 4x18
                   text run at (15,73) width 4: " "
-                LayoutBR {BR} at (19,87) size 0x0
+                LayoutBR {BR} at (19,73) size 0x18
               LayoutBlockFlow (anonymous) at (4,239) size 747x108
                 LayoutBlockFlow (floating) {P} at (0,0) size 373.50x108 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 374x108
@@ -212,7 +212,7 @@
                 LayoutImage {IMG} at (373.50,0) size 15x15
                 LayoutText {#text} at (388,1) size 5x18
                   text run at (388,1) width 5: " "
-                LayoutBR {BR} at (392,15) size 1x0
+                LayoutBR {BR} at (392,1) size 1x18
               LayoutBlockFlow (anonymous) at (4,365) size 747x108
                 LayoutBlockFlow (floating) {P} at (373.50,0) size 373.50x108 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 374x108
@@ -225,7 +225,7 @@
                 LayoutImage {IMG} at (0,0) size 15x15
                 LayoutText {#text} at (15,1) size 4x18
                   text run at (15,1) width 4: " "
-                LayoutBR {BR} at (19,15) size 0x0
+                LayoutBR {BR} at (19,1) size 0x18
               LayoutBlockFlow {P} at (4,491) size 747x72
                 LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
                   LayoutText {#text} at (0,0) size 22x37
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/frames/iframe-with-frameborder-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/frames/iframe-with-frameborder-expected.txt
index 6eb410f..1f02f31 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/frames/iframe-with-frameborder-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/frames/iframe-with-frameborder-expected.txt
@@ -1,23 +1,23 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x540
+  LayoutBlockFlow {HTML} at (0,0) size 800x540
+    LayoutBlockFlow {BODY} at (8,8) size 784x524
       LayoutText {#text} at (0,0) size 216x18
         text run at (0,0) width 216: "This iframe should have a border."
-      LayoutBR {BR} at (215,14) size 1x0
+      LayoutBR {BR} at (215,0) size 1x18
       LayoutText {#text} at (304,158) size 4x18
         text run at (304,158) width 4: " "
       LayoutBR {BR} at (0,0) size 0x0
       LayoutText {#text} at (0,176) size 150x18
         text run at (0,176) width 150: "This iframe should not."
-      LayoutBR {BR} at (149,190) size 1x0
+      LayoutBR {BR} at (149,176) size 1x18
       LayoutText {#text} at (300,330) size 4x18
         text run at (300,330) width 4: " "
-      LayoutBR {BR} at (304,344) size 0x0
+      LayoutBR {BR} at (304,330) size 0x18
       LayoutText {#text} at (0,348) size 220x18
         text run at (0,348) width 220: "This iframe should have a border. "
-      LayoutBR {BR} at (219,362) size 1x0
+      LayoutBR {BR} at (219,348) size 1x18
       LayoutText {#text} at (0,0) size 0x0
 layer at (8,26) size 304x154
   LayoutIFrame {IFRAME} at (0,18) size 304x154 [border: (2px inset #EEEEEE)]
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/table/dynamic-descendant-percentage-height-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/table/dynamic-descendant-percentage-height-expected.png
index d3e14130..81d732bb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/table/dynamic-descendant-percentage-height-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/table/dynamic-descendant-percentage-height-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css1/box_properties/float_on_text_elements-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css1/box_properties/float_on_text_elements-expected.txt
index 41c7b73..7c7d192 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css1/box_properties/float_on_text_elements-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/css1/box_properties/float_on_text_elements-expected.txt
@@ -25,7 +25,7 @@
         LayoutImage {IMG} at (0,80) size 15x15
         LayoutText {#text} at (15,80) size 4x19
           text run at (15,80) width 4: " "
-        LayoutBR {BR} at (19,95) size 0x0
+        LayoutBR {BR} at (19,80) size 0x19
       LayoutBlockFlow (anonymous) at (0,236) size 769x100
         LayoutBlockFlow (floating) {P} at (0,0) size 384.50x100 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 384x99
@@ -37,7 +37,7 @@
         LayoutImage {IMG} at (384.50,0) size 15x15
         LayoutText {#text} at (399,0) size 5x19
           text run at (399,0) width 5: " "
-        LayoutBR {BR} at (403,15) size 1x0
+        LayoutBR {BR} at (403,0) size 1x19
       LayoutBlockFlow (anonymous) at (0,354) size 769x120
         LayoutBlockFlow (floating) {P} at (384.50,0) size 384.50x120 [bgcolor=#FFFF00]
           LayoutText {#text} at (0,0) size 384x119
@@ -50,7 +50,7 @@
         LayoutImage {IMG} at (0,0) size 15x15
         LayoutText {#text} at (15,0) size 4x19
           text run at (15,0) width 4: " "
-        LayoutBR {BR} at (19,15) size 0x0
+        LayoutBR {BR} at (19,0) size 0x19
       LayoutBlockFlow {P} at (0,492) size 769x60
         LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
           LayoutText {#text} at (0,0) size 21x36
@@ -192,7 +192,7 @@
                 LayoutImage {IMG} at (0,80) size 15x15
                 LayoutText {#text} at (15,80) size 4x19
                   text run at (15,80) width 4: " "
-                LayoutBR {BR} at (19,95) size 0x0
+                LayoutBR {BR} at (19,80) size 0x19
               LayoutBlockFlow (anonymous) at (4,240) size 747x120
                 LayoutBlockFlow (floating) {P} at (0,0) size 373.50x120 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 373x119
@@ -205,7 +205,7 @@
                 LayoutImage {IMG} at (373.50,0) size 15x15
                 LayoutText {#text} at (388,0) size 5x19
                   text run at (388,0) width 5: " "
-                LayoutBR {BR} at (392,15) size 1x0
+                LayoutBR {BR} at (392,0) size 1x19
               LayoutBlockFlow (anonymous) at (4,378) size 747x120
                 LayoutBlockFlow (floating) {P} at (373.50,0) size 373.50x120 [bgcolor=#FFFF00]
                   LayoutText {#text} at (0,0) size 373x119
@@ -218,7 +218,7 @@
                 LayoutImage {IMG} at (0,0) size 15x15
                 LayoutText {#text} at (15,0) size 4x19
                   text run at (15,0) width 4: " "
-                LayoutBR {BR} at (19,15) size 0x0
+                LayoutBR {BR} at (19,0) size 0x19
               LayoutBlockFlow {P} at (4,516) size 747x60
                 LayoutBlockFlow (floating) {SPAN} at (0,0) size 48x37 [bgcolor=#C0C0C0]
                   LayoutText {#text} at (0,0) size 21x36
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/select-initial-position-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/select-initial-position-expected.txt
index 592605f..c5cb618 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/select-initial-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/select-initial-position-expected.txt
@@ -1,49 +1,49 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x409
+  LayoutBlockFlow {HTML} at (0,0) size 800x409
+    LayoutBlockFlow {BODY} at (8,8) size 784x393
       LayoutText {#text} at (0,0) size 86x19
         text run at (0,0) width 86: "initial selected:"
-      LayoutBR {BR} at (86,15) size 0x0
+      LayoutBR {BR} at (86,0) size 0x19
       LayoutText {#text} at (155,71) size 4x19
         text run at (155,71) width 4: " "
-      LayoutBR {BR} at (159,86) size 0x0
+      LayoutBR {BR} at (159,71) size 0x19
       LayoutText {#text} at (0,91) size 152x19
         text run at (0,91) width 152: "dynamic selected change:"
-      LayoutBR {BR} at (152,106) size 0x0
+      LayoutBR {BR} at (152,91) size 0x19
       LayoutText {#text} at (155,162) size 4x19
         text run at (155,162) width 4: " "
-      LayoutBR {BR} at (159,177) size 0x0
+      LayoutBR {BR} at (159,162) size 0x19
       LayoutText {#text} at (0,182) size 200x19
         text run at (0,182) width 200: "dynamic insert of selected option:"
-      LayoutBR {BR} at (200,197) size 0x0
+      LayoutBR {BR} at (200,182) size 0x19
       LayoutText {#text} at (155,253) size 4x19
         text run at (155,253) width 4: " "
-      LayoutBR {BR} at (159,268) size 0x0
+      LayoutBR {BR} at (159,253) size 0x19
       LayoutText {#text} at (0,273) size 86x19
         text run at (0,273) width 86: "initial selected:"
-      LayoutBR {BR} at (86,288) size 0x0
+      LayoutBR {BR} at (86,273) size 0x19
       LayoutMenuList {SELECT} at (0,293) size 156x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
             text run at (4,1) width 134: "this should be selected"
       LayoutText {#text} at (156,293) size 4x19
         text run at (156,293) width 4: " "
-      LayoutBR {BR} at (160,308) size 0x0
+      LayoutBR {BR} at (160,293) size 0x19
       LayoutText {#text} at (0,313) size 152x19
         text run at (0,313) width 152: "dynamic selected change:"
-      LayoutBR {BR} at (152,328) size 0x0
+      LayoutBR {BR} at (152,313) size 0x19
       LayoutMenuList {SELECT} at (0,333) size 156x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
             text run at (4,1) width 134: "this should be selected"
       LayoutText {#text} at (156,333) size 4x19
         text run at (156,333) width 4: " "
-      LayoutBR {BR} at (160,348) size 0x0
+      LayoutBR {BR} at (160,333) size 0x19
       LayoutText {#text} at (0,353) size 200x19
         text run at (0,353) width 200: "dynamic insert of selected option:"
-      LayoutBR {BR} at (200,368) size 0x0
+      LayoutBR {BR} at (200,353) size 0x19
       LayoutMenuList {SELECT} at (0,373) size 156x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
         LayoutBlockFlow (anonymous) at (1,1) size 154x18
           LayoutText (anonymous) at (4,1) size 134x16
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/frames/iframe-with-frameborder-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/frames/iframe-with-frameborder-expected.txt
index cc73174..0421413 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/frames/iframe-with-frameborder-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/frames/iframe-with-frameborder-expected.txt
@@ -1,23 +1,23 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x549
+  LayoutBlockFlow {HTML} at (0,0) size 800x549
+    LayoutBlockFlow {BODY} at (8,8) size 784x533
       LayoutText {#text} at (0,0) size 200x19
         text run at (0,0) width 200: "This iframe should have a border."
-      LayoutBR {BR} at (200,15) size 0x0
+      LayoutBR {BR} at (200,0) size 0x19
       LayoutText {#text} at (304,159) size 4x19
         text run at (304,159) width 4: " "
       LayoutBR {BR} at (0,0) size 0x0
       LayoutText {#text} at (0,179) size 136x19
         text run at (0,179) width 136: "This iframe should not."
-      LayoutBR {BR} at (136,194) size 0x0
+      LayoutBR {BR} at (136,179) size 0x19
       LayoutText {#text} at (300,334) size 4x19
         text run at (300,334) width 4: " "
-      LayoutBR {BR} at (304,349) size 0x0
+      LayoutBR {BR} at (304,334) size 0x19
       LayoutText {#text} at (0,354) size 204x19
         text run at (0,354) width 204: "This iframe should have a border. "
-      LayoutBR {BR} at (204,369) size 0x0
+      LayoutBR {BR} at (204,354) size 0x19
       LayoutText {#text} at (0,0) size 0x0
 layer at (8,28) size 304x154
   LayoutIFrame {IFRAME} at (0,20) size 304x154 [border: (2px inset #EEEEEE)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.png
index 7a3e7f7..f1c25d2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.txt
index e76a697..1d6fd58b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/parser/001-expected.txt
@@ -1,8 +1,8 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
+layer at (0,0) size 800x583
+  LayoutBlockFlow {HTML} at (0,0) size 800x583
+    LayoutBlockFlow {BODY} at (8,16) size 784x559
       LayoutBlockFlow {DIR} at (0,0) size 784x112
         LayoutBlockFlow (anonymous) at (40,0) size 744x20
           LayoutText {#text} at (0,0) size 26x19
@@ -39,5 +39,5 @@
           LayoutText {#text} at (0,0) size 226x19
             text run at (0,0) width 226: "Now we're back to nonbreaking text."
         LayoutText {#text} at (0,0) size 0x0
-layer at (8,152) size 300x300
+layer at (8,160) size 300x300
   LayoutEmbeddedObject {OBJECT} at (0,16) size 300x300 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
index 7fce2d66..2a1c3c27 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-expected.png
index ad49523..914f30e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_border-table-quirks-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/dynamic-descendant-percentage-height-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/dynamic-descendant-percentage-height-expected.png
index 7791047..8e8e1c84 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/table/dynamic-descendant-percentage-height-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/dynamic-descendant-percentage-height-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-collapsed-border-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
index 7c649995..a170c16 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-expected.png
index bfb79b9..19008de 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/table/backgr_border-table-quirks-expected.png
Binary files differ
diff --git a/third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h b/third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h
index 99800cbe..58b75ab 100644
--- a/third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h
+++ b/third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h
@@ -33,16 +33,14 @@
 
 #include "third_party/blink/public/platform/web_platform_event_listener.h"
 
-namespace device {
-class OrientationData;
-}
-
 namespace blink {
 
+class DeviceOrientationData;
+
 class WebDeviceOrientationListener : public WebPlatformEventListener {
  public:
   // This method is called every time new device orientation data is available.
-  virtual void DidChangeDeviceOrientation(const device::OrientationData&) = 0;
+  virtual void DidChangeDeviceOrientation(DeviceOrientationData*) = 0;
 
   ~WebDeviceOrientationListener() override = default;
 };
diff --git a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.cc b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.cc
index d849eb9..1051232 100644
--- a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.cc
+++ b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.cc
@@ -3,11 +3,10 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h"
-#include "third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.h"
+
 #include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/platform/histogram.h"
 
 namespace blink {
 
@@ -17,22 +16,8 @@
     : context_(context),
       sheet_text_(sheet_text),
       owning_contents_(contents),
-      parsed_style_rules_(0),
-      total_style_rules_(0),
-      style_rules_needed_for_next_milestone_(0),
-      usage_(kUsageGe0),
       should_use_count_(context_->IsUseCounterRecordingEnabled()) {}
 
-void CSSLazyParsingState::FinishInitialParsing() {
-  RecordUsageMetrics();
-}
-
-CSSLazyPropertyParserImpl* CSSLazyParsingState::CreateLazyParser(
-    const size_t offset) {
-  ++total_style_rules_;
-  return new CSSLazyPropertyParserImpl(offset, this);
-}
-
 const CSSParserContext* CSSLazyParsingState::Context() {
   DCHECK(owning_contents_);
   if (!should_use_count_) {
@@ -50,15 +35,6 @@
   return context_;
 }
 
-void CSSLazyParsingState::CountRuleParsed() {
-  ++parsed_style_rules_;
-  while (parsed_style_rules_ > style_rules_needed_for_next_milestone_) {
-    DCHECK_NE(kUsageAll, usage_);
-    ++usage_;
-    RecordUsageMetrics();
-  }
-}
-
 bool CSSLazyParsingState::ShouldLazilyParseProperties(
     const CSSSelectorList& selectors) const {
   //  Disallow lazy parsing for blocks which have before/after in their selector
@@ -80,42 +56,6 @@
   return true;
 }
 
-void CSSLazyParsingState::RecordUsageMetrics() {
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, usage_histogram,
-                      ("Style.LazyUsage.Percent", kUsageLastValue));
-  DEFINE_STATIC_LOCAL(CustomCountHistogram, total_rules_histogram,
-                      ("Style.TotalLazyRules", 0, 100000, 50));
-  DEFINE_STATIC_LOCAL(CustomCountHistogram, total_rules_full_usage_histogram,
-                      ("Style.TotalLazyRules.FullUsage", 0, 100000, 50));
-  switch (usage_) {
-    case kUsageGe0:
-      total_rules_histogram.Count(total_style_rules_);
-      style_rules_needed_for_next_milestone_ = total_style_rules_ * .1;
-      break;
-    case kUsageGt10:
-      style_rules_needed_for_next_milestone_ = total_style_rules_ * .25;
-      break;
-    case kUsageGt25:
-      style_rules_needed_for_next_milestone_ = total_style_rules_ * .5;
-      break;
-    case kUsageGt50:
-      style_rules_needed_for_next_milestone_ = total_style_rules_ * .75;
-      break;
-    case kUsageGt75:
-      style_rules_needed_for_next_milestone_ = total_style_rules_ * .9;
-      break;
-    case kUsageGt90:
-      style_rules_needed_for_next_milestone_ = total_style_rules_ - 1;
-      break;
-    case kUsageAll:
-      total_rules_full_usage_histogram.Count(total_style_rules_);
-      style_rules_needed_for_next_milestone_ = total_style_rules_;
-      break;
-  }
-
-  usage_histogram.Count(usage_);
-}
-
 void CSSLazyParsingState::Trace(blink::Visitor* visitor) {
   visitor->Trace(owning_contents_);
   visitor->Trace(document_);
diff --git a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
index 94eb06b..1e50644 100644
--- a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
+++ b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
@@ -12,8 +12,6 @@
 
 namespace blink {
 
-class CSSLazyPropertyParserImpl;
-
 // This class helps lazy parsing by retaining necessary state. It should not
 // outlive the StyleSheetContents that initiated the parse, as it retains a raw
 // reference to the UseCounter associated with the style sheet.
@@ -30,38 +28,13 @@
                       const String& sheet_text,
                       StyleSheetContents*);
 
-  // Called when all lazy property parsers are initialized. At this point we
-  // know the total number of style rules that deferred parsing.
-  void FinishInitialParsing();
-
-  // Helper method used to bump total_style_rules_.
-  CSSLazyPropertyParserImpl* CreateLazyParser(size_t offset);
-
   const CSSParserContext* Context();
   const String& SheetText() const { return sheet_text_; }
-  void CountRuleParsed();
   bool ShouldLazilyParseProperties(const CSSSelectorList&) const;
 
   void Trace(blink::Visitor*);
 
-  // Exposed for tests. This enum is used to back a histogram, so new values
-  // must be appended to the end, before UsageLastValue.
-  enum CSSRuleUsage {
-    kUsageGe0 = 0,
-    kUsageGt10 = 1,
-    kUsageGt25 = 2,
-    kUsageGt50 = 3,
-    kUsageGt75 = 4,
-    kUsageGt90 = 5,
-    kUsageAll = 6,
-
-    // This value must be last.
-    kUsageLastValue = 7
-  };
-
  private:
-  void RecordUsageMetrics();
-
   Member<const CSSParserContext> context_;
   // Also referenced on the css resource.
   String sheet_text_;
@@ -74,14 +47,6 @@
   // UseCounter per every property parse is a bit more expensive.
   WeakMember<Document> document_;
 
-  // Used for calculating the % of rules that ended up being parsed.
-  int parsed_style_rules_;
-  int total_style_rules_;
-
-  int style_rules_needed_for_next_milestone_;
-
-  int usage_;
-
   // Whether or not use counting is enabled for parsing. This will usually be
   // true, except for when stylesheets with @imports are removed from the page.
   // See StyleRuleImport::setCSSStyleSheet.
diff --git a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
index c541502..0770334 100644
--- a/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
@@ -13,7 +13,6 @@
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -29,7 +28,6 @@
   }
 
  protected:
-  HistogramTester histogram_tester_;
   Persistent<StyleSheetContents> cached_contents_;
 };
 
@@ -170,70 +168,4 @@
   EXPECT_FALSE(use_counter2.IsCounted(CSSPropertyBackgroundColor));
 }
 
-TEST_F(CSSLazyParsingTest, SimpleRuleUsagePercent) {
-  CSSParserContext* context = CSSParserContext::Create(
-      kHTMLStandardMode, SecureContextMode::kInsecureContext);
-  StyleSheetContents* style_sheet = StyleSheetContents::Create(context);
-
-  std::string usage_metric = "Style.LazyUsage.Percent";
-  std::string total_rules_metric = "Style.TotalLazyRules";
-  std::string total_rules_full_usage_metric = "Style.TotalLazyRules.FullUsage";
-  histogram_tester_.ExpectTotalCount(usage_metric, 0);
-
-  String sheet_text =
-      "body { background-color: red; }"
-      "p { color: blue; }"
-      "a { color: yellow; }"
-      "#id { color: blue; }"
-      "div { color: grey; }";
-  CSSParser::ParseSheet(context, style_sheet, sheet_text,
-                        true /* lazy parse */);
-
-  histogram_tester_.ExpectTotalCount(total_rules_metric, 1);
-  histogram_tester_.ExpectUniqueSample(total_rules_metric, 5, 1);
-
-  // Only log the full usage metric when all the rules have been actually
-  // parsed.
-  histogram_tester_.ExpectTotalCount(total_rules_full_usage_metric, 0);
-
-  histogram_tester_.ExpectTotalCount(usage_metric, 1);
-  histogram_tester_.ExpectUniqueSample(usage_metric,
-                                       CSSLazyParsingState::kUsageGe0, 1);
-
-  RuleAt(style_sheet, 0)->Properties();
-  histogram_tester_.ExpectTotalCount(usage_metric, 2);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageGt10, 1);
-
-  RuleAt(style_sheet, 1)->Properties();
-  histogram_tester_.ExpectTotalCount(usage_metric, 3);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageGt25, 1);
-
-  RuleAt(style_sheet, 2)->Properties();
-  histogram_tester_.ExpectTotalCount(usage_metric, 4);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageGt50, 1);
-
-  RuleAt(style_sheet, 3)->Properties();
-  histogram_tester_.ExpectTotalCount(usage_metric, 5);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageGt75, 1);
-
-  // Only log the full usage metric when all the rules have been actually
-  // parsed.
-  histogram_tester_.ExpectTotalCount(total_rules_full_usage_metric, 0);
-
-  // Parsing the last rule bumps both Gt90 and All buckets.
-  RuleAt(style_sheet, 4)->Properties();
-  histogram_tester_.ExpectTotalCount(usage_metric, 7);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageGt90, 1);
-  histogram_tester_.ExpectBucketCount(usage_metric,
-                                      CSSLazyParsingState::kUsageAll, 1);
-
-  histogram_tester_.ExpectTotalCount(total_rules_full_usage_metric, 1);
-  histogram_tester_.ExpectUniqueSample(total_rules_full_usage_metric, 5, 1);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.cc
index 1f44acce..d43f0e7 100644
--- a/third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.cc
@@ -14,7 +14,6 @@
     : CSSLazyPropertyParser(), offset_(offset), lazy_state_(state) {}
 
 CSSPropertyValueSet* CSSLazyPropertyParserImpl::ParseProperties() {
-  lazy_state_->CountRuleParsed();
   return CSSParserImpl::ParseDeclarationListForLazyStyle(
       lazy_state_->SheetText(), offset_, lazy_state_->Context());
 }
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index 22c6edb..abce963 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -266,8 +266,6 @@
         style_sheet->ParserAppendRule(rule);
       });
   style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
-  if (parser.lazy_state_)
-    parser.lazy_state_->FinishInitialParsing();
   TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");
 
   TRACE_EVENT_END2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
@@ -822,7 +820,7 @@
     DCHECK(style_sheet_);
     return StyleRule::CreateLazy(
         std::move(selector_list),
-        lazy_state_->CreateLazyParser(stream.Offset() - 1));
+        new CSSLazyPropertyParserImpl(stream.Offset() - 1, lazy_state_));
   }
   ConsumeDeclarationList(stream, StyleRule::kStyle);
 
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 50cc1321..a788952 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -417,9 +417,7 @@
   }
 
   if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
-    AccelerationHint hint =
-        Is2d() ? kPreferNoAcceleration : kPreferAcceleration;
-    if (GetOrCreateCanvasResourceProvider(hint)) {
+    if (GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
       ResourceProvider()->TryEnableSingleBuffering();
       // Push a frame
       base::TimeTicks start_time = WTF::CurrentTimeTicks();
diff --git a/third_party/blink/renderer/core/paint/OWNERS b/third_party/blink/renderer/core/paint/OWNERS
index ffef4fe..d4b697b 100644
--- a/third_party/blink/renderer/core/paint/OWNERS
+++ b/third_party/blink/renderer/core/paint/OWNERS
@@ -4,7 +4,6 @@
 enne@chromium.org
 fmalita@chromium.org
 fs@opera.com
-junov@chromium.org
 pdr@chromium.org
 schenney@chromium.org
 senorblanco@chromium.org
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 1ba89d1..874c9f57 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
@@ -919,7 +919,11 @@
     HitTestResult& result,
     const NGPaintFragment& text_paint_fragment,
     const HitTestLocation& location_in_container,
-    const LayoutPoint& physical_offset) {
+    const LayoutPoint& physical_offset,
+    HitTestAction action) {
+  if (action != kHitTestForeground)
+    return false;
+
   const NGPhysicalFragment& text_fragment =
       text_paint_fragment.PhysicalFragment();
   LayoutSize size(text_fragment.Size().width, text_fragment.Size().height);
@@ -964,17 +968,13 @@
     const HitTestLocation& location_in_container,
     const LayoutPoint& physical_offset,
     HitTestAction action) {
-  if (action != kHitTestForeground)
-    return false;
-
-  const LayoutSize size = fragment.Size().ToLayoutSize();
-
-  // TODO(xiaochengh): Hit test ellipsis box.
-
   if (HitTestChildren(result, fragment.Children(), location_in_container,
                       physical_offset, action))
     return true;
 
+  if (action != kHitTestForeground)
+    return false;
+
   if (!VisibleToHitTestRequest(result.GetHitTestRequest()))
     return false;
 
@@ -983,6 +983,7 @@
   if (HitTestClippedOutByBorder(location_in_container, overflow_location))
     return false;
 
+  const LayoutSize size = fragment.Size().ToLayoutSize();
   const LayoutRect bounds_rect(physical_offset, size);
   const ComputedStyle& containing_box_style = box_fragment_.Style();
   if (containing_box_style.HasBorderRadius() &&
@@ -1006,6 +1007,48 @@
                                              bounds_rect) == kStopHitTesting;
 }
 
+bool NGBoxFragmentPainter::HitTestChildBoxFragment(
+    HitTestResult& result,
+    const NGPaintFragment& paint_fragment,
+    const HitTestLocation& location_in_container,
+    const LayoutPoint& physical_offset,
+    HitTestAction action) {
+  const NGPhysicalFragment& fragment = paint_fragment.PhysicalFragment();
+  if (fragment.IsFloating() && action != kHitTestFloat)
+    return false;
+  // Lines and inlines are hit tested only in the foreground phase.
+  if (fragment.IsInline() && action != kHitTestForeground)
+    return false;
+
+  if (!FragmentRequiresLegacyFallback(fragment)) {
+    // TODO(layout-dev): Implement HitTestAllPhases in NG after we stop
+    // falling back to legacy for child atomic inlines and floats.
+    DCHECK(!fragment.IsAtomicInline());
+    DCHECK(!fragment.IsFloating());
+    return NGBoxFragmentPainter(paint_fragment)
+        .NodeAtPoint(result, location_in_container, physical_offset, action);
+  }
+
+  LayoutBox* const layout_box = ToLayoutBox(fragment.GetLayoutObject());
+
+  // 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.
+  const LayoutPoint fallback_accumulated_offset =
+      physical_offset - ToLayoutSize(layout_box->Location());
+
+  // https://www.w3.org/TR/CSS22/zindex.html#painting-order
+  // Hit test all phases of inline blocks, inline tables, replaced elements and
+  // non-positioned floats as if they created their own stacking contexts.
+  const bool should_hit_test_all_phases =
+      fragment.IsAtomicInline() || fragment.IsFloating();
+  return should_hit_test_all_phases
+             ? layout_box->HitTestAllPhases(result, location_in_container,
+                                            fallback_accumulated_offset)
+             : layout_box->NodeAtPoint(result, location_in_container,
+                                       fallback_accumulated_offset, action);
+}
+
 bool NGBoxFragmentPainter::HitTestChildren(
     HitTestResult& result,
     const Vector<std::unique_ptr<NGPaintFragment>>& children,
@@ -1023,31 +1066,8 @@
 
     bool stop_hit_testing = false;
     if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
-      if (FragmentRequiresLegacyFallback(fragment)) {
-        // Hit test all phases of an inline-block/table or replaced element
-        // 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 =
-            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);
-        } else {
-          stop_hit_testing = fragment.GetLayoutObject()->NodeAtPoint(
-              result, location_in_container, fallback_accumulated_offset,
-              action);
-        }
-      } else {
-        // TODO(layout-dev): Implement HitTestAllPhases in NG after we stop
-        // falling back to legacy for atomic inlines.
-        stop_hit_testing = NGBoxFragmentPainter(*child).NodeAtPoint(
-            result, location_in_container, child_physical_offset, action);
-      }
+      stop_hit_testing = HitTestChildBoxFragment(
+          result, *child, location_in_container, child_physical_offset, action);
 
     } else if (fragment.Type() == NGPhysicalFragment::kFragmentLineBox) {
       stop_hit_testing = HitTestLineBoxFragment(
@@ -1057,12 +1077,12 @@
       // TODO(eae): Should this hit test on the text itself or the containing
       // node?
       stop_hit_testing = HitTestTextFragment(
-          result, *child, location_in_container, child_physical_offset);
+          result, *child, location_in_container, child_physical_offset, action);
     }
     if (stop_hit_testing)
       return true;
 
-    if (!fragment.IsInline())
+    if (!fragment.IsInline() || action != kHitTestForeground)
       continue;
 
     // Hit test culled inline boxes between |fragment| and its parent fragment.
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index 73fd17b..f88f840 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -122,12 +122,23 @@
                        const LayoutPoint& physical_offset,
                        HitTestAction);
 
+  // Hit tests a box fragment, which is a child of either |box_fragment_|, or
+  // one of its child line box fragments.
+  // @param physical_offset Physical offset of the given box fragment in the
+  // paint layer.
+  bool HitTestChildBoxFragment(HitTestResult&,
+                               const NGPaintFragment&,
+                               const HitTestLocation& location_in_container,
+                               const LayoutPoint& physical_offset,
+                               HitTestAction);
+
   // Hit tests the given text fragment.
   // @param physical_offset Physical offset of the text fragment in paint layer.
   bool HitTestTextFragment(HitTestResult&,
                            const NGPaintFragment&,
                            const HitTestLocation& location_in_container,
-                           const LayoutPoint& physical_offset);
+                           const LayoutPoint& physical_offset,
+                           HitTestAction);
 
   // Hit tests the given line box fragment.
   // @param physical_offset Physical offset of the line box fragment in paint
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js b/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
index 70eae3c..aa75a6a 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
@@ -195,6 +195,11 @@
     const entry = SDK.CSSMetadata._propertyDataMap[propertyName] || SDK.CSSMetadata._propertyDataMap[unprefixedName];
     if (entry && entry.values)
       acceptedKeywords.pushAll(entry.values);
+    const commonKeywords = ['auto', 'none'];
+    for (const commonKeyword of commonKeywords) {
+      if (CSS.supports(propertyName, commonKeyword))
+        acceptedKeywords.push(commonKeyword);
+    }
     if (this.isColorAwareProperty(propertyName)) {
       acceptedKeywords.push('currentColor');
       for (const color in Common.Color.Nicknames)
@@ -227,7 +232,7 @@
 SDK.CSSMetadata._distanceProperties = new Set([
   'background-position', 'border-spacing', 'bottom', 'font-size', 'height', 'left', 'letter-spacing', 'max-height',
   'max-width', 'min-height', 'min-width', 'right', 'text-indent', 'top', 'width', 'word-spacing', 'grid-row-gap',
-  'grid-column-gap'
+  'grid-column-gap', 'row-gap'
 ]);
 
 SDK.CSSMetadata._bezierAwareProperties = new Set([
@@ -291,18 +296,17 @@
 ]);
 
 SDK.CSSMetadata._propertyDataMap = {
-  'table-layout': {values: ['auto', 'fixed']},
+  'table-layout': {values: ['fixed']},
   'visibility': {values: ['hidden', 'visible', 'collapse']},
   'background-repeat': {values: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space', 'round']},
-  'content': {values: ['none', 'normal', 'close-quote', 'no-close-quote', 'no-open-quote', 'open-quote']},
-  'list-style-image': {values: ['none']},
-  'clear': {values: ['none', 'left', 'right', 'both']},
-  'overflow-x': {values: ['hidden', 'auto', 'visible', 'overlay', 'scroll']},
+  'content': {values: ['normal', 'close-quote', 'no-close-quote', 'no-open-quote', 'open-quote']},
+  'clear': {values: ['left', 'right', 'both']},
+  'overflow-x': {values: ['hidden', 'visible', 'overlay', 'scroll', '-webkit-paged-x', '-webkit-paged-y']},
   'stroke-linejoin': {values: ['round', 'miter', 'bevel']},
   'baseline-shift': {values: ['baseline', 'sub', 'super']},
   'border-bottom-width': {values: ['medium', 'thick', 'thin']},
   'margin-top-collapse': {values: ['collapse', 'separate', 'discard']},
-  'max-height': {values: ['none', 'min-content', 'max-content', '-webkit-fill-available', 'fit-content']},
+  'max-height': {values: ['min-content', 'max-content', '-webkit-fill-available', 'fit-content']},
   'box-orient': {
     values: ['horizontal', 'vertical', 'inline-axis', 'block-axis'],
   },
@@ -313,22 +317,21 @@
     ]
   },
   'border-left-width': {values: ['medium', 'thick', 'thin']},
-  'box-shadow': {values: ['inset', 'none']},
+  'box-shadow': {values: ['inset']},
   '-webkit-writing-mode': {values: ['horizontal-tb', 'vertical-rl', 'vertical-lr']},
   'writing-mode':
       {values: ['lr', 'rl', 'tb', 'lr-tb', 'rl-tb', 'tb-rl', 'horizontal-tb', 'vertical-rl', 'vertical-lr']},
   'border-collapse': {values: ['collapse', 'separate']},
-  'page-break-inside': {values: ['auto', 'avoid']},
+  'page-break-inside': {values: ['avoid']},
   'border-top-width': {values: ['medium', 'thick', 'thin']},
-  'outline-style':
-      {values: ['auto', 'none', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+  'outline-style': {values: ['inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double', 'hidden']},
   'cursor': {
     values: [
-      'none',
       'copy',
-      'auto',
       'crosshair',
       'default',
+      'grab',
+      'grabbing',
       'pointer',
       'move',
       'vertical-text',
@@ -365,19 +368,21 @@
     ]
   },
   'border-width': {values: ['medium', 'thick', 'thin']},
-  'border-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
-  'size': {values: ['auto', 'a3', 'a4', 'a5', 'b4', 'b5', 'landscape', 'ledger', 'legal', 'letter', 'portrait']},
-  'background-size': {values: ['auto', 'contain', 'cover']},
+  'border-style': {values: ['hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+  'size': {values: ['a3', 'a4', 'a5', 'b4', 'b5', 'landscape', 'ledger', 'legal', 'letter', 'portrait']},
+  'background-size': {values: ['contain', 'cover']},
   'direction': {values: ['ltr', 'rtl']},
   'enable-background': {values: ['accumulate', 'new']},
-  'float': {values: ['none', 'left', 'right']},
-  'overflow-y': {values: ['hidden', 'auto', 'visible', 'overlay', 'scroll', '-webkit-paged-x', '-webkit-paged-y']},
+  'float': {values: ['left', 'right']},
+  'overflow-y': {values: ['hidden', 'visible', 'overlay', 'scroll', '-webkit-paged-x', '-webkit-paged-y']},
   'margin-bottom-collapse': {values: ['collapse', 'separate', 'discard']},
   'box-reflect': {values: ['left', 'right', 'above', 'below']},
-  'overflow': {values: ['hidden', 'auto', 'visible', 'overlay', 'scroll', '-webkit-paged-x', '-webkit-paged-y']},
-  'contain': {values: ['none', 'strict', 'content', 'size', 'layout', 'style', 'paint']},
-  'text-rendering': {values: ['auto', 'optimizeSpeed', 'optimizeLegibility', 'geometricPrecision']},
+  'overflow': {values: ['hidden', 'visible', 'overlay', 'scroll', '-webkit-paged-x', '-webkit-paged-y']},
+  'overscroll-behavior': {values: ['contain']},
+  'overscroll-behavior-x': {values: ['contain']},
+  'overscroll-behavior-y': {values: ['contain']},
+  'contain': {values: ['strict', 'content', 'size', 'layout', 'style', 'paint']},
+  'text-rendering': {values: ['optimizeSpeed', 'optimizeLegibility', 'geometricPrecision']},
   'text-align': {
     values: [
       '-webkit-auto', 'start', 'end', 'left', 'right', 'center', 'justify', '-webkit-left', '-webkit-right',
@@ -385,25 +390,23 @@
     ]
   },
   'list-style-position': {values: ['outside', 'inside']},
-  'margin-bottom': {values: ['auto']},
-  'color-interpolation': {values: ['auto', 'sRGB', 'linearRGB']},
+  'color-interpolation': {values: ['sRGB', 'linearRGB']},
   'background-origin': {values: ['border-box', 'content-box', 'padding-box']},
   'word-wrap': {values: ['normal', 'break-word']},
   'font-weight':
       {values: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900']},
   'margin-before-collapse': {values: ['collapse', 'separate', 'discard']},
-  'text-transform': {values: ['none', 'capitalize', 'uppercase', 'lowercase']},
+  'text-transform': {values: ['capitalize', 'uppercase', 'lowercase']},
   'border-right-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
   'border-left-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
-  '-webkit-text-emphasis': {values: ['circle', 'filled', 'open', 'dot', 'double-circle', 'triangle', 'sesame', 'none']},
+      {values: ['hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+  '-webkit-text-emphasis': {values: ['circle', 'filled', 'open', 'dot', 'double-circle', 'triangle', 'sesame']},
   'font-style': {values: ['italic', 'oblique', 'normal']},
-  'speak': {values: ['none', 'normal', 'spell-out', 'digits', 'literal-punctuation', 'no-punctuation']},
-  'color-rendering': {values: ['auto', 'optimizeSpeed', 'optimizeQuality']},
+  'speak': {values: ['normal', 'spell-out', 'digits', 'literal-punctuation', 'no-punctuation']},
+  'color-rendering': {values: ['optimizeSpeed', 'optimizeQuality']},
   'list-style-type': {
     values: [
-      'none',
       'disc',
       'circle',
       'square',
@@ -461,14 +464,11 @@
       'katakana-iroha'
     ]
   },
-  'text-combine-upright': {values: ['none', 'all']},
-  '-webkit-text-combine': {values: ['none', 'horizontal']},
+  'text-combine-upright': {values: ['all']},
+  '-webkit-text-combine': {values: ['horizontal']},
   'text-orientation': {values: ['mixed', 'upright', 'sideways', 'sideways-right']},
   'outline': {
-    values: [
-      'none', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double', 'medium', 'auto', 'thick',
-      'thin'
-    ]
+    values: ['inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin']
   },
   'font': {
     values: [
@@ -518,13 +518,12 @@
   },
   'dominant-baseline': {
     values: [
-      'middle', 'auto', 'central', 'text-before-edge', 'text-after-edge', 'ideographic', 'alphabetic', 'hanging',
+      'middle', 'central', 'text-before-edge', 'text-after-edge', 'ideographic', 'alphabetic', 'hanging',
       'mathematical', 'use-script', 'no-change', 'reset-size'
     ]
   },
   'display': {
     values: [
-      'none',
       'inline',
       'block',
       'flow-root',
@@ -550,55 +549,48 @@
     ]
   },
   '-webkit-text-emphasis-position': {values: ['over', 'under']},
-  'image-rendering': {values: ['auto', 'pixelated', '-webkit-optimize-contrast']},
+  'image-rendering': {values: ['pixelated', '-webkit-optimize-contrast', 'optimizeSpeed', 'optimizeQuality']},
   'alignment-baseline': {
     values: [
-      'baseline', 'middle', 'auto', 'before-edge', 'after-edge', 'central', 'text-before-edge', 'text-after-edge',
+      'baseline', 'middle', 'before-edge', 'after-edge', 'central', 'text-before-edge', 'text-after-edge',
       'ideographic', 'alphabetic', 'hanging', 'mathematical'
     ]
   },
   'outline-width': {values: ['medium', 'thick', 'thin']},
   'box-align': {values: ['baseline', 'center', 'stretch', 'start', 'end']},
   'border-right-width': {values: ['medium', 'thick', 'thin']},
-  'border-top-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+  'border-top-style': {values: ['hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
   'line-height': {values: ['normal']},
   'text-overflow': {values: ['clip', 'ellipsis']},
   'overflow-wrap': {values: ['normal', 'break-word']},
   'box-direction': {values: ['normal', 'reverse']},
   'margin-after-collapse': {values: ['collapse', 'separate', 'discard']},
-  'page-break-before': {values: ['left', 'right', 'auto', 'always', 'avoid']},
-  'border-image': {values: ['repeat', 'stretch', 'none', 'space', 'round']},
-  'text-decoration': {
-    values: ['none', 'blink', 'line-through', 'overline', 'underline', 'wavy', 'double', 'solid', 'dashed', 'dotted']
-  },
+  'page-break-before': {values: ['left', 'right', 'always', 'avoid']},
+  'border-image': {values: ['repeat', 'stretch', 'space', 'round']},
+  'text-decoration':
+      {values: ['blink', 'line-through', 'overline', 'underline', 'wavy', 'double', 'solid', 'dashed', 'dotted']},
   'position': {values: ['absolute', 'fixed', 'relative', 'static', 'sticky']},
   'font-family':
       {values: ['serif', 'sans-serif', 'cursive', 'fantasy', 'monospace', '-webkit-body', '-webkit-pictograph']},
-  'text-overflow-mode': {values: ['clip', 'ellipsis']},
   'border-bottom-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double']},
   'unicode-bidi': {values: ['normal', 'bidi-override', 'embed', 'isolate', 'isolate-override', 'plaintext']},
   'clip-rule': {values: ['nonzero', 'evenodd']},
-  'margin-left': {values: ['auto']},
-  'margin-top': {values: ['auto']},
   'zoom': {values: ['normal']},
-  'max-width': {values: ['none', 'min-content', 'max-content', '-webkit-fill-available', 'fit-content']},
+  'max-width': {values: ['min-content', 'max-content', '-webkit-fill-available', 'fit-content']},
   'caption-side': {values: ['top', 'bottom']},
   'empty-cells': {values: ['hide', 'show']},
   'pointer-events': {
     values: [
-      'none', 'all', 'auto', 'visible', 'visiblepainted', 'visiblefill', 'visiblestroke', 'painted', 'fill', 'stroke',
-      'bounding-box'
+      'all', 'visible', 'visiblepainted', 'visiblefill', 'visiblestroke', 'painted', 'fill', 'stroke', 'bounding-box'
     ]
   },
   'letter-spacing': {values: ['normal']},
   'background-clip': {values: ['border-box', 'content-box', 'padding-box']},
-  '-webkit-font-smoothing': {values: ['none', 'auto', 'antialiased', 'subpixel-antialiased']},
+  '-webkit-font-smoothing': {values: ['antialiased', 'subpixel-antialiased']},
   'border': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'ridge', 'outset', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   'font-size': {
@@ -610,7 +602,6 @@
     values: [
       'small-caps',
       'normal',
-      'none',
       'common-ligatures',
       'no-common-ligatures',
       'discretionary-ligatures',
@@ -648,25 +639,19 @@
         ['baseline', 'middle', 'sub', 'super', 'text-top', 'text-bottom', 'top', 'bottom', '-webkit-baseline-middle']
   },
   'white-space': {values: ['normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap']},
-  'page-break-after': {values: ['left', 'right', 'auto', 'always', 'avoid']},
-  'clip-path': {values: ['none']},
-  'margin': {values: ['auto']},
-  'margin-right': {values: ['auto']},
+  'page-break-after': {values: ['left', 'right', 'always', 'avoid']},
   'word-break': {values: ['normal', 'break-all', 'break-word', 'keep-all']},
   'word-spacing': {values: ['normal']},
-  '-webkit-text-emphasis-style':
-      {values: ['circle', 'filled', 'open', 'dot', 'double-circle', 'triangle', 'sesame', 'none']},
+  '-webkit-text-emphasis-style': {values: ['circle', 'filled', 'open', 'dot', 'double-circle', 'triangle', 'sesame']},
   'transform': {
     values: [
-      'scale',      'scaleX',     'scaleY',      'scale3d', 'rotate',   'rotateX',     'rotateY',
-      'rotateZ',    'rotate3d',   'skew',        'skewX',   'skewY',    'translate',   'translateX',
-      'translateY', 'translateZ', 'translate3d', 'matrix',  'matrix3d', 'perspective', 'none'
+      'scale',      'scaleX',     'scaleY',      'scale3d', 'rotate',   'rotateX',    'rotateY',
+      'rotateZ',    'rotate3d',   'skew',        'skewX',   'skewY',    'translate',  'translateX',
+      'translateY', 'translateZ', 'translate3d', 'matrix',  'matrix3d', 'perspective'
     ]
   },
-  'image-resolution': {values: ['from-image', 'snap']},
   'box-sizing': {values: ['content-box', 'border-box']},
-  'clip': {values: ['auto']},
-  'resize': {values: ['none', 'both', 'horizontal', 'vertical', 'auto']},
+  'resize': {values: ['both', 'horizontal', 'vertical']},
   'align-content': {
     values: [
       'normal', 'baseline', 'space-between', 'space-around', 'space-evenly', 'stretch', 'unsafe', 'safe', 'center',
@@ -694,36 +679,35 @@
   'justify-items': {
     values: [
       'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
-      'flex-start', 'flex-end', 'left', 'right', 'legacy', 'auto'
+      'flex-start', 'flex-end', 'left', 'right', 'legacy'
     ]
   },
   'place-items': {
     values: [
-      'auto', 'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
+      'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
       'flex-start', 'flex-end', 'left', 'right'
     ]
   },
   'align-self': {
     values: [
-      'auto', 'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
+      'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
       'flex-start', 'flex-end', 'left', 'right'
     ]
   },
   'justify-self': {
     values: [
-      'auto', 'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
+      'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
       'flex-start', 'flex-end', 'left', 'right'
     ]
   },
   'place-self': {
     values: [
-      'auto', 'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
+      'normal', 'stretch', 'baseline', 'unsafe', 'safe', 'center', 'start', 'end', 'self-start', 'self-end',
       'flex-start', 'flex-end', 'left', 'right'
     ]
   },
   'flex-direction': {values: ['row', 'row-reverse', 'column', 'column-reverse']},
   'flex-wrap': {values: ['nowrap', 'wrap', 'wrap-reverse']},
-  'perspective': {values: ['none']},
   'perspective-origin': {values: ['left', 'center', 'right', 'top', 'bottom']},
   'transform-origin': {values: ['left', 'center', 'right', 'top', 'bottom']},
   'transform-style': {values: ['flat', 'preserve-3d']},
@@ -741,30 +725,28 @@
   },
   'animation-direction': {values: ['normal', 'reverse', 'alternate', 'alternate-reverse']},
   'animation-play-state': {values: ['running', 'paused']},
-  'animation-fill-mode': {values: ['none', 'forwards', 'backwards', 'both']},
+  'animation-fill-mode': {values: ['forwards', 'backwards', 'both']},
   '-webkit-backface-visibility': {values: ['visible', 'hidden']},
   '-webkit-box-decoration-break': {values: ['slice', 'clone']},
   '-webkit-column-break-after':
-      {values: ['auto', 'always', 'avoid', 'left', 'right', 'page', 'column', 'avoid-page', 'avoid-column']},
+      {values: ['always', 'avoid', 'left', 'right', 'page', 'column', 'avoid-page', 'avoid-column']},
   '-webkit-column-break-before':
-      {values: ['auto', 'always', 'avoid', 'left', 'right', 'page', 'column', 'avoid-page', 'avoid-column']},
-  '-webkit-column-break-inside': {values: ['auto', 'avoid', 'avoid-page', 'avoid-column']},
-  '-webkit-column-span': {values: ['none', 'all']},
-  '-webkit-column-count': {values: ['auto']},
+      {values: ['always', 'avoid', 'left', 'right', 'page', 'column', 'avoid-page', 'avoid-column']},
+  '-webkit-column-break-inside': {values: ['avoid', 'avoid-page', 'avoid-column']},
+  '-webkit-column-span': {values: ['all']},
   '-webkit-column-gap': {values: ['normal']},
   'filter': {
     values: [
       'url', 'blur', 'brightness', 'contrast', 'drop-shadow', 'grayscale', 'hue-rotate', 'invert', 'opacity',
-      'saturate', 'sepia', 'none'
+      'saturate', 'sepia'
     ]
   },
-  'line-break': {values: ['auto', 'loose', 'normal', 'strict', 'after-white-space']},
-  'user-select': {values: ['none', 'text', 'all', 'auto']},
+  'line-break': {values: ['loose', 'normal', 'strict', 'after-white-space']},
+  'user-select': {values: ['text', 'all']},
   '-webkit-user-modify': {values: ['read-only', 'read-write', 'read-write-plaintext-only']},
-  'text-align-last': {values: ['auto', 'start', 'end', 'left', 'right', 'center', 'justify']},
-  '-webkit-text-decoration-line': {values: ['none', 'underline', 'overline', 'line-through', 'blink']},
+  'text-align-last': {values: ['start', 'end', 'left', 'right', 'center', 'justify']},
+  '-webkit-text-decoration-line': {values: ['underline', 'overline', 'line-through', 'blink']},
   '-webkit-text-decoration-style': {values: ['solid', 'double', 'dotted', 'dashed', 'wavy']},
-  '-webkit-text-decoration-skip': {values: ['none', 'objects', 'spaces', 'ink', 'edges', 'box-decoration']},
   'mix-blend-mode': {
     values: [
       'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light',
@@ -777,35 +759,26 @@
       'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity', 'unset'
     ]
   },
-  'caret-color': {values: ['auto']},
-  'grid-template-columns': {values: ['none', 'auto', 'min-content', 'max-content']},
-  'grid-template-rows': {values: ['none', 'auto', 'min-content', 'max-content']},
-  'grid-template-areas': {values: ['none']},
-  'grid-template': {values: ['none']},
-  'grid-auto-columns': {values: ['auto', 'min-content', 'max-content']},
-  'grid-auto-rows': {values: ['auto', 'min-content', 'max-content']},
+  'grid-template-columns': {values: ['min-content', 'max-content']},
+  'grid-template-rows': {values: ['min-content', 'max-content']},
+  'grid-auto-columns': {values: ['min-content', 'max-content']},
+  'grid-auto-rows': {values: ['min-content', 'max-content']},
   'grid-auto-flow': {values: ['row', 'column', 'dense']},
-  'grid': {values: ['none']},
-  'grid-row-start': {values: ['auto']},
-  'grid-column-start': {values: ['auto']},
-  'grid-row-end': {values: ['auto']},
-  'grid-column-end': {values: ['auto']},
-  'grid-row': {values: ['auto']},
-  'grid-column': {values: ['auto']},
-  'grid-area': {values: ['auto']},
+  'row-gap': {values: ['normal']},
   'animation-iteration-count': {values: ['infinite']},
   'font-feature-settings': {values: ['normal']},
-  'font-kerning': {values: ['none', 'normal', 'auto']},
-  'font-size-adjust': {values: ['none']},
+  'font-kerning': {values: ['normal']},
   'font-variant-caps':
       {values: ['small-caps', 'all-small-caps', 'petite-caps', 'all-petite-caps', 'unicase', 'titling-caps', 'normal']},
   'font-variant-east-asian': {
-    values:
-        ['jis78', 'jis83', 'jis90', 'jis04', 'simplified', 'traditional', 'full-width', 'proportional-width', 'ruby']
+    values: [
+      'jis78', 'jis83', 'jis90', 'jis04', 'simplified', 'traditional', 'full-width', 'proportional-width', 'ruby',
+      'normal'
+    ]
   },
   'font-variant-ligatures': {
     values: [
-      'none', 'common-ligatures', 'no-common-ligatures', 'discretionary-ligatures', 'no-discretionary-ligatures',
+      'common-ligatures', 'no-common-ligatures', 'discretionary-ligatures', 'no-discretionary-ligatures',
       'historical-ligatures', 'no-historical-ligatures', 'contextual', 'no-contextual', 'normal'
     ]
   },
@@ -816,17 +789,14 @@
     ]
   },
   'font-variation-settings': {values: ['normal']},
-  '-webkit-locale': {values: ['auto']},
-  'backdrop-filter': {values: ['none']},
   'backface-visibility': {values: ['hidden', 'visible']},
   'background': {
     values: [
-      'none', 'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'top', 'bottom', 'left', 'right', 'center', 'fixed',
-      'local', 'scroll', 'space', 'round', 'border-box', 'content-box', 'padding-box'
+      'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'top', 'bottom', 'left', 'right', 'center', 'fixed', 'local',
+      'scroll', 'space', 'round', 'border-box', 'content-box', 'padding-box'
     ]
   },
   'background-attachment': {values: ['fixed', 'local', 'scroll']},
-  'background-image': {values: ['none']},
   'background-position': {values: ['top', 'bottom', 'left', 'right', 'center']},
   'background-position-x': {values: ['left', 'right', 'center']},
   'background-position-y': {values: ['top', 'bottom', 'center']},
@@ -834,68 +804,50 @@
   'background-repeat-y': {values: ['repeat', 'no-repeat']},
   'border-bottom': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   'border-image-repeat': {values: ['repeat', 'stretch', 'space', 'round']},
-  'border-image-source': {values: ['none']},
-  'border-image-width': {values: ['auto']},
   'border-left': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   'border-right': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   'border-top': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
-  'bottom': {values: ['auto']},
-  'break-after':
-      {values: ['left', 'right', 'auto', 'avoid', 'column', 'avoid-page', 'page', 'recto', 'verso', 'avoid-column']},
+  'break-after': {values: ['left', 'right', 'avoid', 'column', 'avoid-page', 'page', 'recto', 'verso', 'avoid-column']},
   'break-before':
-      {values: ['left', 'right', 'auto', 'avoid', 'column', 'avoid-page', 'page', 'recto', 'verso', 'avoid-column']},
-  'break-inside': {values: ['auto', 'avoid', 'avoid-page', 'avoid-column']},
-  'buffered-rendering': {values: ['auto', 'static', 'dynamic']},
-  'color-interpolation-filters': {values: ['auto', 'srgb', 'linearrgb']},
-  'column-count': {values: ['auto']},
-  'column-fill': {values: ['auto', 'balance']},
+      {values: ['left', 'right', 'avoid', 'column', 'avoid-page', 'page', 'recto', 'verso', 'avoid-column']},
+  'break-inside': {values: ['avoid', 'avoid-page', 'avoid-column']},
+  'buffered-rendering': {values: ['static', 'dynamic']},
+  'color-interpolation-filters': {values: ['srgb', 'linearrgb']},
+  'column-fill': {values: ['balance']},
   'column-gap': {values: ['normal']},
   'column-rule': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   'column-rule-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
   'column-rule-width': {values: ['medium', 'thick', 'thin']},
-  'column-span': {values: ['none', 'all']},
-  'column-width': {values: ['auto']},
-  'columns': {values: ['auto']},
-  'd': {values: ['none']},
-  'fill': {values: ['none']},
+  'column-span': {values: ['all']},
   'fill-rule': {values: ['nonzero', 'evenodd']},
-  'flex': {values: ['none', 'auto']},
-  'flex-basis': {values: ['auto']},
   'flex-flow': {values: ['nowrap', 'row', 'row-reverse', 'column', 'column-reverse', 'wrap', 'wrap-reverse']},
-  'height': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'hyphens': {values: ['none', 'manual']},
-  'inline-size': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'isolation': {values: ['auto', 'isolate']},
-  'left': {values: ['auto']},
+  'height': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'hyphens': {values: ['manual']},
+  'inline-size': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'isolation': {values: ['isolate']},
   'list-style': {
     values: [
-      'none',
       'outside',
       'inside',
       'disc',
@@ -955,38 +907,24 @@
       'katakana-iroha'
     ]
   },
-  'marker': {values: ['none']},
-  'marker-end': {values: ['none']},
-  'marker-mid': {values: ['none']},
-  'marker-start': {values: ['none']},
-  'mask': {values: ['none']},
-  'mask-source-type': {values: ['auto', 'alpha', 'luminance']},
+  'mask-source-type': {values: ['alpha', 'luminance']},
   'mask-type': {values: ['alpha', 'luminance']},
-  'max-block-size': {values: ['none', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'max-inline-size': {values: ['none', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'min-block-size': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'min-height': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'min-inline-size': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'min-width': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'object-fit': {values: ['none', 'contain', 'cover', 'fill', 'scale-down']},
+  'max-block-size': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'max-inline-size': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'min-block-size': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'min-height': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'min-inline-size': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'min-width': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  'object-fit': {values: ['contain', 'cover', 'fill', 'scale-down']},
   'object-position': {values: ['top', 'bottom', 'left', 'right', 'center']},
-  'offset-anchor': {values: ['top', 'bottom', 'left', 'right', 'center', 'auto']},
-  'offset-path': {values: ['none']},
-  'offset-position': {values: ['top', 'bottom', 'left', 'right', 'center', 'auto']},
-  'offset-rotate': {values: ['auto', 'reverse']},
-  'overflow-anchor': {values: ['none', 'auto', 'visible']},
+  'offset-anchor': {values: ['top', 'bottom', 'left', 'right', 'center']},
+  'offset-position': {values: ['top', 'bottom', 'left', 'right', 'center']},
+  'offset-rotate': {values: ['reverse']},
+  'overflow-anchor': {values: ['visible']},
   'paint-order': {values: ['normal', 'fill', 'stroke', 'markers']},
-  'quotes': {values: ['none']},
-  'right': {values: ['auto']},
-  'rotate': {values: ['none']},
-  'rx': {values: ['auto']},
-  'ry': {values: ['auto']},
-  'scale': {values: ['none']},
-  'scroll-behavior': {values: ['auto', 'smooth']},
+  'scroll-behavior': {values: ['smooth']},
   'scroll-customization': {
     values: [
-      'none',
-      'auto',
       'pan-x',
       'pan-y',
       'pan-left',
@@ -995,32 +933,24 @@
       'pan-down',
     ]
   },
-  'shape-outside': {values: ['none', 'border-box', 'content-box', 'padding-box', 'margin-box']},
-  'shape-rendering': {values: ['auto', 'optimizespeed', 'geometricprecision', 'crispedges']},
-  'stroke': {values: ['none']},
-  'stroke-dasharray': {values: ['none']},
+  'scroll-snap-align': {values: ['start', 'end', 'center']},
+  'scroll-snap-stop': {values: ['normal', 'always']},
+  'scroll-snap-type': {values: ['x', 'y', 'block', 'inline', 'both', 'mandatory', 'proximity']},
+  'shape-outside': {values: ['border-box', 'content-box', 'padding-box', 'margin-box']},
+  'shape-rendering': {values: ['optimizespeed', 'geometricprecision', 'crispedges']},
   'stroke-linecap': {values: ['square', 'round', 'butt']},
   'text-anchor': {values: ['middle', 'start', 'end']},
-  'text-decoration-line': {values: ['none', 'blink', 'line-through', 'overline', 'underline']},
-  'text-decoration-skip': {values: ['objects', 'ink']},
+  'text-decoration-line': {values: ['blink', 'line-through', 'overline', 'underline']},
   'text-decoration-style': {values: ['dotted', 'dashed', 'solid', 'double', 'wavy']},
-  'text-justify': {values: ['none', 'inter-word', 'distribute', 'auto']},
-  'text-shadow': {values: ['none']},
-  'text-size-adjust': {values: ['none', 'auto']},
-  'text-underline-position': {values: ['auto', 'under']},
-  'top': {values: ['auto']},
-  'touch-action': {
-    values: [
-      'none', 'auto', 'pan-x', 'pan-y', 'pan-left', 'pan-right', 'pan-up', 'pan-down', 'manipulation', 'pinch-zoom'
-    ]
-  },
+  'text-justify': {values: ['inter-word', 'distribute']},
+  'text-underline-position': {values: ['under']},
+  'touch-action':
+      {values: ['pan-x', 'pan-y', 'pan-left', 'pan-right', 'pan-up', 'pan-down', 'manipulation', 'pinch-zoom']},
   'transform-box': {values: ['border-box', 'fill-box', 'view-box']},
-  'translate': {values: ['none']},
-  'vector-effect': {values: ['none', 'non-scaling-stroke']},
+  'vector-effect': {values: ['non-scaling-stroke']},
   '-webkit-app-region': {values: ['drag', 'no-drag']},
   '-webkit-appearance': {
     values: [
-      'none',
       'checkbox',
       'radio',
       'push-button',
@@ -1065,54 +995,42 @@
   },
   '-webkit-border-after': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   '-webkit-border-after-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
   '-webkit-border-after-width': {values: ['medium', 'thick', 'thin']},
   '-webkit-border-before': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   '-webkit-border-before-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
   '-webkit-border-before-width': {values: ['medium', 'thick', 'thin']},
   '-webkit-border-end': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   '-webkit-border-end-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
   '-webkit-border-end-width': {values: ['medium', 'thick', 'thin']},
   '-webkit-border-start': {
     values: [
-      'none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick',
-      'thin'
+      'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double', 'medium', 'thick', 'thin'
     ]
   },
   '-webkit-border-start-style':
-      {values: ['none', 'hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
+      {values: ['hidden', 'inset', 'groove', 'outset', 'ridge', 'dotted', 'dashed', 'solid', 'double']},
   '-webkit-border-start-width': {values: ['medium', 'thick', 'thin']},
   '-webkit-box-pack': {values: ['center', 'justify', 'start', 'end']},
-  '-webkit-highlight': {values: ['none']},
-  '-webkit-hyphenate-character': {values: ['auto']},
-  '-webkit-logical-height': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  '-webkit-logical-width': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  '-webkit-margin-after': {values: ['auto']},
-  '-webkit-margin-before': {values: ['auto']},
+  '-webkit-logical-height': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  '-webkit-logical-width': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
   '-webkit-margin-collapse': {values: ['collapse', 'separate', 'discard']},
-  '-webkit-margin-end': {values: ['auto']},
-  '-webkit-margin-start': {values: ['auto']},
-  '-webkit-mask-box-image': {values: ['none', 'repeat', 'stretch', 'space', 'round']},
+  '-webkit-mask-box-image': {values: ['repeat', 'stretch', 'space', 'round']},
   '-webkit-mask-box-image-repeat': {values: ['repeat', 'stretch', 'space', 'round']},
-  '-webkit-mask-box-image-source': {values: ['none']},
-  '-webkit-mask-box-image-width': {values: ['auto']},
   '-webkit-mask-clip': {values: ['text', 'border', 'border-box', 'content', 'content-box', 'padding', 'padding-box']},
   '-webkit-mask-composite': {
     values: [
@@ -1120,35 +1038,29 @@
       'destination-out', 'destination-atop', 'xor', 'plus-lighter'
     ]
   },
-  '-webkit-mask-image': {values: ['none']},
   '-webkit-mask-origin': {values: ['border', 'border-box', 'content', 'content-box', 'padding', 'padding-box']},
   '-webkit-mask-position': {values: ['top', 'bottom', 'left', 'right', 'center']},
   '-webkit-mask-position-x': {values: ['left', 'right', 'center']},
   '-webkit-mask-position-y': {values: ['top', 'bottom', 'center']},
   '-webkit-mask-repeat': {values: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space', 'round']},
-  '-webkit-mask-size': {values: ['auto', 'contain', 'cover']},
-  '-webkit-max-logical-height':
-      {values: ['none', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  '-webkit-max-logical-width':
-      {values: ['none', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  '-webkit-min-logical-height':
-      {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  '-webkit-min-logical-width':
-      {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  '-webkit-mask-size': {values: ['contain', 'cover']},
+  '-webkit-max-logical-height': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  '-webkit-max-logical-width': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  '-webkit-min-logical-height': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
+  '-webkit-min-logical-width': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
   '-webkit-perspective-origin-x': {values: ['left', 'right', 'center']},
   '-webkit-perspective-origin-y': {values: ['top', 'bottom', 'center']},
   '-webkit-print-color-adjust': {values: ['economy', 'exact']},
   '-webkit-rtl-ordering': {values: ['logical', 'visual']},
   '-webkit-ruby-position': {values: ['after', 'before']},
-  '-webkit-text-decorations-in-effect': {values: ['none', 'blink', 'line-through', 'overline', 'underline']},
-  '-webkit-text-security': {values: ['none', 'disc', 'circle', 'square']},
+  '-webkit-text-decorations-in-effect': {values: ['blink', 'line-through', 'overline', 'underline']},
+  '-webkit-text-security': {values: ['disc', 'circle', 'square']},
   '-webkit-text-stroke': {values: ['medium', 'thick', 'thin']},
   '-webkit-text-stroke-width': {values: ['medium', 'thick', 'thin']},
   '-webkit-transform-origin-x': {values: ['left', 'right', 'center']},
   '-webkit-transform-origin-y': {values: ['top', 'bottom', 'center']},
-  '-webkit-user-drag': {values: ['none', 'auto', 'element']},
-  'width': {values: ['auto', '-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
-  'z-index': {values: ['auto']}
+  '-webkit-user-drag': {values: ['element']},
+  'width': {values: ['-webkit-fill-available', 'min-content', 'max-content', 'fit-content']},
 };
 
 // Weight of CSS properties based on their usage from https://www.chromestatus.com/metrics/css/popularity
diff --git a/third_party/blink/renderer/modules/csspaint/OWNERS b/third_party/blink/renderer/modules/csspaint/OWNERS
index 2f8630d2..b9770dac 100644
--- a/third_party/blink/renderer/modules/csspaint/OWNERS
+++ b/third_party/blink/renderer/modules/csspaint/OWNERS
@@ -1,6 +1,5 @@
 flackr@chromium.org
 ikilpatrick@chromium.org
-junov@chromium.org
 xidachen@chromium.org
 
 # TEAM: style-dev@chromium.org
diff --git a/third_party/blink/renderer/modules/device_orientation/DEPS b/third_party/blink/renderer/modules/device_orientation/DEPS
index 71a097e..7c1b789 100644
--- a/third_party/blink/renderer/modules/device_orientation/DEPS
+++ b/third_party/blink/renderer/modules/device_orientation/DEPS
@@ -1,11 +1,6 @@
 include_rules = [
     "+base/run_loop.h",
     "+mojo/public/cpp/bindings/binding.h",
-
-    # NOTE: These files are POD structs used to interpret shared memory across
-    # the Device Sensors implementation and the Blink client.
-    "+services/device/public/cpp/generic_sensor/orientation_data.h",
-
     "+services/device/public/mojom/sensor.mojom-blink.h",
     "+services/device/public/mojom/sensor_provider.mojom-blink.h",
     "+services/device/public/cpp/test/fake_sensor_and_provider.h",
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_data.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_data.cc
index 9c22671..f8c4153 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_data.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_data.cc
@@ -25,7 +25,6 @@
 
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
 
-#include "services/device/public/cpp/generic_sensor/orientation_data.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_init.h"
 
 namespace blink {
@@ -56,20 +55,6 @@
   return DeviceOrientationData::Create(alpha, beta, gamma, init.absolute());
 }
 
-DeviceOrientationData* DeviceOrientationData::Create(
-    const device::OrientationData& data) {
-  base::Optional<double> alpha;
-  base::Optional<double> beta;
-  base::Optional<double> gamma;
-  if (data.has_alpha)
-    alpha = data.alpha;
-  if (data.has_beta)
-    beta = data.beta;
-  if (data.has_gamma)
-    gamma = data.gamma;
-  return DeviceOrientationData::Create(alpha, beta, gamma, data.absolute);
-}
-
 DeviceOrientationData::DeviceOrientationData() : absolute_(false) {}
 
 DeviceOrientationData::DeviceOrientationData(
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_data.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_data.h
index b2d771b..cba97f33 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_data.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_data.h
@@ -30,10 +30,6 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
-namespace device {
-class OrientationData;
-}
-
 namespace blink {
 
 class DeviceOrientationEventInit;
@@ -47,7 +43,6 @@
                                        const base::Optional<double>& gamma,
                                        bool absolute);
   static DeviceOrientationData* Create(const DeviceOrientationEventInit&);
-  static DeviceOrientationData* Create(const device::OrientationData&);
   void Trace(blink::Visitor* visitor) {}
 
   double Alpha() const;
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
index 01f17d13..3c91bd4 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
@@ -78,8 +78,8 @@
 }
 
 void DeviceOrientationDispatcher::DidChangeDeviceOrientation(
-    const device::OrientationData& motion) {
-  last_device_orientation_data_ = DeviceOrientationData::Create(motion);
+    DeviceOrientationData* orientation) {
+  last_device_orientation_data_ = orientation;
   NotifyControllers();
 }
 
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
index b8e25cb0..fa0821f 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
@@ -36,10 +36,6 @@
 #include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
-namespace device {
-class OrientationData;
-}
-
 namespace blink {
 
 class DeviceOrientationData;
@@ -62,7 +58,7 @@
   DeviceOrientationData* LatestDeviceOrientationData();
 
   // Inherited from WebDeviceOrientationListener.
-  void DidChangeDeviceOrientation(const device::OrientationData&) override;
+  void DidChangeDeviceOrientation(DeviceOrientationData*) override;
 
   void Trace(blink::Visitor*) override;
 
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
index 459caef..1dd17979 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
@@ -7,30 +7,28 @@
 #include "services/device/public/mojom/sensor.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
 
 namespace {
 
-bool IsAngleDifferentThreshold(bool has_angle1,
-                               double angle1,
-                               bool has_angle2,
-                               double angle2) {
-  if (has_angle1 != has_angle2)
-    return true;
-
-  return (has_angle1 &&
-          std::fabs(angle1 - angle2) >=
-              blink::DeviceOrientationEventPump::kOrientationThreshold);
+bool IsAngleDifferentThreshold(double angle1, double angle2) {
+  return (std::fabs(angle1 - angle2) >=
+          blink::DeviceOrientationEventPump::kOrientationThreshold);
 }
 
-bool IsSignificantlyDifferent(const device::OrientationData& data1,
-                              const device::OrientationData& data2) {
-  return IsAngleDifferentThreshold(data1.has_alpha, data1.alpha,
-                                   data2.has_alpha, data2.alpha) ||
-         IsAngleDifferentThreshold(data1.has_beta, data1.beta, data2.has_beta,
-                                   data2.beta) ||
-         IsAngleDifferentThreshold(data1.has_gamma, data1.gamma,
-                                   data2.has_gamma, data2.gamma);
+bool IsSignificantlyDifferent(const blink::DeviceOrientationData* data1,
+                              const blink::DeviceOrientationData* data2) {
+  if (data1->CanProvideAlpha() != data2->CanProvideAlpha() ||
+      data1->CanProvideBeta() != data2->CanProvideBeta() ||
+      data1->CanProvideGamma() != data2->CanProvideGamma())
+    return true;
+  return (data1->CanProvideAlpha() &&
+          IsAngleDifferentThreshold(data1->Alpha(), data2->Alpha())) ||
+         (data1->CanProvideBeta() &&
+          IsAngleDifferentThreshold(data1->Beta(), data2->Beta())) ||
+         (data1->CanProvideGamma() &&
+          IsAngleDifferentThreshold(data1->Gamma(), data2->Gamma()));
 }
 
 }  // namespace
@@ -105,15 +103,13 @@
   // data when stopping. If we don't reset here as well, then when starting back
   // up we won't notify DeviceOrientationDispatcher of the orientation, since
   // we think it hasn't changed.
-  data_ = device::OrientationData();
+  data_ = nullptr;
 }
 
 void DeviceOrientationEventPump::FireEvent(TimerBase*) {
-  device::OrientationData data;
-
   DCHECK(listener());
 
-  GetDataFromSharedMemory(&data);
+  DeviceOrientationData* data = GetDataFromSharedMemory();
 
   if (ShouldFireEvent(data)) {
     data_ = data;
@@ -152,60 +148,67 @@
   return true;
 }
 
-void DeviceOrientationEventPump::GetDataFromSharedMemory(
-    device::OrientationData* data) {
-  data->all_available_sensors_are_active = true;
+DeviceOrientationData* DeviceOrientationEventPump::GetDataFromSharedMemory() {
+  base::Optional<double> alpha;
+  base::Optional<double> beta;
+  base::Optional<double> gamma;
+  bool absolute = false;
 
   if (!absolute_ && relative_orientation_sensor_.SensorReadingCouldBeRead()) {
     // For DeviceOrientation Event, this provides relative orientation data.
-    data->all_available_sensors_are_active =
-        relative_orientation_sensor_.reading.timestamp() != 0.0;
-    if (!data->all_available_sensors_are_active)
-      return;
-    data->alpha = relative_orientation_sensor_.reading.orientation_euler.z;
-    data->beta = relative_orientation_sensor_.reading.orientation_euler.x;
-    data->gamma = relative_orientation_sensor_.reading.orientation_euler.y;
-    data->has_alpha = !std::isnan(
-        relative_orientation_sensor_.reading.orientation_euler.z.value());
-    data->has_beta = !std::isnan(
-        relative_orientation_sensor_.reading.orientation_euler.x.value());
-    data->has_gamma = !std::isnan(
-        relative_orientation_sensor_.reading.orientation_euler.y.value());
-    data->absolute = false;
+    if (relative_orientation_sensor_.reading.timestamp() == 0.0)
+      return nullptr;
+
+    if (!std::isnan(
+            relative_orientation_sensor_.reading.orientation_euler.z.value()))
+      alpha = relative_orientation_sensor_.reading.orientation_euler.z;
+
+    if (!std::isnan(
+            relative_orientation_sensor_.reading.orientation_euler.x.value()))
+      beta = relative_orientation_sensor_.reading.orientation_euler.x;
+
+    if (!std::isnan(
+            relative_orientation_sensor_.reading.orientation_euler.y.value()))
+      gamma = relative_orientation_sensor_.reading.orientation_euler.y;
   } else if (absolute_orientation_sensor_.SensorReadingCouldBeRead()) {
     // For DeviceOrientationAbsolute Event, this provides absolute orientation
     // data.
     //
     // For DeviceOrientation Event, this provides absolute orientation data if
     // relative orientation data is not available.
-    data->all_available_sensors_are_active =
-        absolute_orientation_sensor_.reading.timestamp() != 0.0;
-    if (!data->all_available_sensors_are_active)
-      return;
-    data->alpha = absolute_orientation_sensor_.reading.orientation_euler.z;
-    data->beta = absolute_orientation_sensor_.reading.orientation_euler.x;
-    data->gamma = absolute_orientation_sensor_.reading.orientation_euler.y;
-    data->has_alpha = !std::isnan(
-        absolute_orientation_sensor_.reading.orientation_euler.z.value());
-    data->has_beta = !std::isnan(
-        absolute_orientation_sensor_.reading.orientation_euler.x.value());
-    data->has_gamma = !std::isnan(
-        absolute_orientation_sensor_.reading.orientation_euler.y.value());
-    data->absolute = true;
+    if (absolute_orientation_sensor_.reading.timestamp() == 0.0)
+      return nullptr;
+
+    if (!std::isnan(
+            absolute_orientation_sensor_.reading.orientation_euler.z.value()))
+      alpha = absolute_orientation_sensor_.reading.orientation_euler.z;
+
+    if (!std::isnan(
+            absolute_orientation_sensor_.reading.orientation_euler.x.value()))
+      beta = absolute_orientation_sensor_.reading.orientation_euler.x;
+
+    if (!std::isnan(
+            absolute_orientation_sensor_.reading.orientation_euler.y.value()))
+      gamma = absolute_orientation_sensor_.reading.orientation_euler.y;
+
+    absolute = true;
   } else {
-    data->absolute = absolute_;
+    absolute = absolute_;
   }
+
+  return DeviceOrientationData::Create(alpha, beta, gamma, absolute);
 }
 
 bool DeviceOrientationEventPump::ShouldFireEvent(
-    const device::OrientationData& data) const {
-  if (!data.all_available_sensors_are_active)
+    const DeviceOrientationData* data) const {
+  // |data| is null if not all sensors are active
+  if (!data)
     return false;
 
-  if (!data.has_alpha && !data.has_beta && !data.has_gamma) {
-    // no data can be provided, this is an all-null event.
+  // when the state changes from not having data to having data,
+  // the event should be fired
+  if (!data_)
     return true;
-  }
 
   return IsSignificantlyDifferent(data_, data);
 }
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
index cc2122b9..7b774f5 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_PUMP_H_
 
 #include "base/macros.h"
-#include "services/device/public/cpp/generic_sensor/orientation_data.h"
 #include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -44,14 +43,14 @@
   // DeviceSensorEventPump:
   bool SensorsReadyOrErrored() const override;
 
-  void GetDataFromSharedMemory(device::OrientationData* data);
+  DeviceOrientationData* GetDataFromSharedMemory();
 
-  bool ShouldFireEvent(const device::OrientationData& data) const;
+  bool ShouldFireEvent(const DeviceOrientationData* data) const;
 
   bool absolute_;
   bool fall_back_to_absolute_orientation_sensor_;
   bool should_suspend_absolute_orientation_sensor_ = false;
-  device::OrientationData data_;
+  Persistent<DeviceOrientationData> data_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPump);
 };
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
index 95b644c6..fbd6cd6 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
@@ -7,12 +7,13 @@
 #include <memory>
 
 #include "base/run_loop.h"
-#include "services/device/public/cpp/generic_sensor/orientation_data.h"
 #include "services/device/public/cpp/test/fake_sensor_and_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
 
 namespace {
 
@@ -28,13 +29,12 @@
     : public blink::WebDeviceOrientationListener {
  public:
   MockDeviceOrientationListener() : did_change_device_orientation_(false) {
-    memset(&data_, 0, sizeof(data_));
+    data_ = DeviceOrientationData::Create();
   }
   ~MockDeviceOrientationListener() override {}
 
-  void DidChangeDeviceOrientation(
-      const device::OrientationData& data) override {
-    memcpy(&data_, &data, sizeof(data));
+  void DidChangeDeviceOrientation(DeviceOrientationData* data) override {
+    data_ = data;
     did_change_device_orientation_ = true;
   }
 
@@ -44,11 +44,11 @@
   void set_did_change_device_orientation(bool value) {
     did_change_device_orientation_ = value;
   }
-  const device::OrientationData& data() const { return data_; }
+  const DeviceOrientationData* data() const { return data_.Get(); }
 
  private:
   bool did_change_device_orientation_;
-  device::OrientationData data_;
+  Persistent<DeviceOrientationData> data_;
 
   DISALLOW_COPY_AND_ASSIGN(MockDeviceOrientationListener);
 };
@@ -343,18 +343,18 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   // DeviceOrientation Event provides relative orientation data when it is
   // available.
-  EXPECT_DOUBLE_EQ(1, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(2, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(3, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(1, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(2, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(3, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -378,21 +378,22 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   // DeviceOrientation Event provides absolute orientation data when relative
   // orientation data is not available but absolute orientation data is
   // available.
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+
   // Since no relative orientation data is available, DeviceOrientationEvent
   // fallback to provide absolute orientation data.
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_TRUE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -414,15 +415,15 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_FALSE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(2, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(3, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+  EXPECT_FALSE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(2, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(3, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -447,20 +448,20 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   // DeviceOrientation Event provides absolute orientation data when relative
   // orientation data is not available but absolute orientation data is
   // available.
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_FALSE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_FALSE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
   // Since no relative orientation data is available, DeviceOrientationEvent
   // fallback to provide absolute orientation data.
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_TRUE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -485,13 +486,13 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_FALSE(received_data.has_alpha);
-  EXPECT_FALSE(received_data.has_beta);
-  EXPECT_FALSE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+  EXPECT_FALSE(received_data->CanProvideAlpha());
+  EXPECT_FALSE(received_data->CanProvideBeta());
+  EXPECT_FALSE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -555,18 +556,18 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   // DeviceOrientation Event provides relative orientation data when it is
   // available.
-  EXPECT_DOUBLE_EQ(1, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(2, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(3, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(1, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(2, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(3, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -579,13 +580,13 @@
   received_data = listener()->data();
   EXPECT_FALSE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(1, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(2, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(3, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(1, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(2, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(3, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -599,13 +600,13 @@
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   EXPECT_DOUBLE_EQ(1 + DeviceOrientationEventPump::kOrientationThreshold,
-                   received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(2, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(3, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_FALSE(received_data.absolute);
+                   received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(2, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(3, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_FALSE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -630,21 +631,21 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
   // DeviceOrientation Event provides absolute orientation data when relative
   // orientation data is not available but absolute orientation data is
   // available.
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
   // Since no relative orientation data is available, DeviceOrientationEvent
   // fallback to provide absolute orientation data.
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_TRUE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -658,13 +659,13 @@
   received_data = listener()->data();
   EXPECT_FALSE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -679,15 +680,15 @@
   received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
   EXPECT_DOUBLE_EQ(
       5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon,
-      received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+      received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   orientation_pump()->Stop();
 
@@ -845,16 +846,16 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   absolute_orientation_pump()->Stop();
 
@@ -875,15 +876,15 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_FALSE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_FALSE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   absolute_orientation_pump()->Stop();
 
@@ -903,13 +904,13 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_FALSE(received_data.has_alpha);
-  EXPECT_FALSE(received_data.has_beta);
-  EXPECT_FALSE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_FALSE(received_data->CanProvideAlpha());
+  EXPECT_FALSE(received_data->CanProvideBeta());
+  EXPECT_FALSE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   absolute_orientation_pump()->Stop();
 
@@ -948,16 +949,16 @@
 
   FireEvent();
 
-  device::OrientationData received_data = listener()->data();
+  const DeviceOrientationData* received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -971,13 +972,13 @@
   received_data = listener()->data();
   EXPECT_FALSE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
-  EXPECT_DOUBLE_EQ(5, received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
+  EXPECT_DOUBLE_EQ(5, received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   listener()->set_did_change_device_orientation(false);
 
@@ -992,15 +993,15 @@
   received_data = listener()->data();
   EXPECT_TRUE(listener()->did_change_device_orientation());
 
-  EXPECT_DOUBLE_EQ(4, received_data.alpha);
-  EXPECT_TRUE(received_data.has_alpha);
+  EXPECT_DOUBLE_EQ(4, received_data->Alpha());
+  EXPECT_TRUE(received_data->CanProvideAlpha());
   EXPECT_DOUBLE_EQ(
       5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon,
-      received_data.beta);
-  EXPECT_TRUE(received_data.has_beta);
-  EXPECT_DOUBLE_EQ(6, received_data.gamma);
-  EXPECT_TRUE(received_data.has_gamma);
-  EXPECT_TRUE(received_data.absolute);
+      received_data->Beta());
+  EXPECT_TRUE(received_data->CanProvideBeta());
+  EXPECT_DOUBLE_EQ(6, received_data->Gamma());
+  EXPECT_TRUE(received_data->CanProvideGamma());
+  EXPECT_TRUE(received_data->Absolute());
 
   absolute_orientation_pump()->Stop();
 
diff --git a/third_party/blink/renderer/platform/OWNERS b/third_party/blink/renderer/platform/OWNERS
index 7e45d47..a6ca217c 100644
--- a/third_party/blink/renderer/platform/OWNERS
+++ b/third_party/blink/renderer/platform/OWNERS
@@ -3,6 +3,7 @@
 drott@chromium.org
 eae@chromium.org
 fmalita@chromium.org
+fserb@chromium.org
 haraken@chromium.org
 jbroman@chromium.org
 jochen@chromium.org
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
index 53bbbfc..2c108da 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -851,7 +851,7 @@
 
     uint16_t character_index =
         glyph_infos[start_glyph + i].cluster - start_cluster;
-    if (UNLIKELY(character_index > HarfBuzzRunGlyphData::kMaxCharacterIndex)) {
+    if (UNLIKELY(character_index >= HarfBuzzRunGlyphData::kMaxCharacterIndex)) {
       // If the character index exceeds the limit, abort and shrink the run to
       // what are actually stored.
       run->num_characters_ = character_index;
@@ -884,7 +884,6 @@
                             hb_buffer_t* harfbuzz_buffer) {
   DCHECK_GT(num_glyphs, 0u);
   std::unique_ptr<ShapeResult::RunInfo> run(std::move(run_to_insert));
-  DCHECK_EQ(num_glyphs, run->glyph_data_.size());
 
   if (run->IsHorizontal()) {
     // Inserting a horizontal run into a horizontal or vertical result. In both
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
index 3609c766..561a86d 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -79,7 +79,7 @@
         direction_(dir),
         canvas_rotation_(canvas_rotation),
         script_(script),
-        glyph_data_(num_glyphs),
+        glyph_data_(std::min(num_glyphs, HarfBuzzRunGlyphData::kMaxCharacterIndex)),
         graphemes_(graphemes),
         start_index_(start_index),
         num_characters_(num_characters),
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn
index 01ea9fc..95b71bc 100644
--- a/third_party/breakpad/BUILD.gn
+++ b/third_party/breakpad/BUILD.gn
@@ -623,11 +623,6 @@
       cflags = [ "-marm" ]
     }
 
-    # Clang's -mstackrealign doesn't work well with
-    # linux_syscall_support.h hand written asm syscalls.
-    # See https://crbug.com/556393
-    configs -= [ "//build/config/compiler:clang_stackrealign" ]
-
     if (is_android) {
       sources += [ "breakpad/src/common/android/breakpad_getcontext.S" ]
     }
@@ -737,11 +732,6 @@
       extra_dist_files = [ "$root_out_dir/linux_dumper_unittest_helper" ]
     }
 
-    # Clang's -mstackrealign doesn't work well with
-    # linux_syscall_support.h hand written asm syscalls.
-    # See https://crbug.com/556393
-    configs -= [ "//build/config/compiler:clang_stackrealign" ]
-
     # Add the breakpad unittest config at the end to override all configs.
     configs += [ ":breakpad_unittest_config" ]
   }
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
index fef1dbd..084e2c6 100644
--- a/third_party/libaom/README.chromium
+++ b/third_party/libaom/README.chromium
@@ -2,9 +2,9 @@
 Short Name: libaom
 URL: https://aomedia.googlesource.com/aom/
 Version: 0
-Date: Thursday July 19 2018
+Date: Monday July 23 2018
 Branch: master
-Commit: 88e4b0a4ee32d39371e15040fa0a1ee7c9d8a19d
+Commit: 0415f2e501a2ef3282771d7500e9a325068436cb
 License: BSD
 License File: source/libaom/LICENSE
 Security Critical: yes
diff --git a/third_party/libaom/libaom_srcs.gni b/third_party/libaom/libaom_srcs.gni
index 99dfb688..4e6b5c2d 100644
--- a/third_party/libaom/libaom_srcs.gni
+++ b/third_party/libaom/libaom_srcs.gni
@@ -110,7 +110,6 @@
   "//third_party/libaom/source/libaom/av1/common/entropymv.c",
   "//third_party/libaom/source/libaom/av1/common/entropymv.h",
   "//third_party/libaom/source/libaom/av1/common/enums.h",
-  "//third_party/libaom/source/libaom/av1/common/filter.c",
   "//third_party/libaom/source/libaom/av1/common/filter.h",
   "//third_party/libaom/source/libaom/av1/common/frame_buffers.c",
   "//third_party/libaom/source/libaom/av1/common/frame_buffers.h",
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h
index 1f1f3e5..4d3e6e1 100644
--- a/third_party/libaom/source/config/config/aom_version.h
+++ b/third_party/libaom/source/config/config/aom_version.h
@@ -12,8 +12,8 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 0
 #define VERSION_PATCH 0
-#define VERSION_EXTRA "173-g88e4b0a4e"
+#define VERSION_EXTRA "195-g0415f2e50"
 #define VERSION_PACKED \
   ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH))
-#define VERSION_STRING_NOSP "1.0.0-173-g88e4b0a4e"
-#define VERSION_STRING " 1.0.0-173-g88e4b0a4e"
+#define VERSION_STRING_NOSP "1.0.0-195-g0415f2e50"
+#define VERSION_STRING " 1.0.0-195-g0415f2e50"
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.c b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.c
index 27a92cf..d6e96a9 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.c
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
index fb13551..11a97ba 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
@@ -152,8 +152,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -163,22 +163,23 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(const uint8_t* src,
-                                            int src_stride,
-                                            uint8_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_scale_c(const uint8_t* src,
                              int src_stride,
@@ -186,8 +187,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -201,8 +202,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -212,22 +213,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_sr)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_horiz_rs_c(const uint8_t* src,
                              int src_stride,
@@ -246,8 +248,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -257,8 +259,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -268,8 +270,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -280,8 +282,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -291,8 +293,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -302,8 +304,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -401,8 +403,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -415,8 +417,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
@@ -431,8 +433,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -483,8 +485,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -497,8 +499,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -560,26 +562,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
 #define av1_highbd_jnt_convolve_2d av1_highbd_jnt_convolve_2d_c
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 #define av1_highbd_jnt_convolve_2d_copy av1_highbd_jnt_convolve_2d_copy_c
 
 void av1_highbd_jnt_convolve_x_c(const uint16_t* src,
@@ -588,8 +591,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -602,8 +605,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -797,8 +800,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -808,22 +811,23 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_2d)(const uint8_t* src,
-                                        int src_stride,
-                                        uint8_t* dst,
-                                        int dst_stride,
-                                        int w,
-                                        int h,
-                                        InterpFilterParams* filter_params_x,
-                                        InterpFilterParams* filter_params_y,
-                                        const int subpel_x_q4,
-                                        const int subpel_y_q4,
-                                        ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_2d)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_2d_copy_c(const uint8_t* src,
                                 int src_stride,
@@ -831,8 +835,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -842,8 +846,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -854,8 +858,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params);
@@ -866,8 +870,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -877,22 +881,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_x)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_x)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_y_c(const uint8_t* src,
                           int src_stride,
@@ -900,8 +905,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -911,22 +916,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_y)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_y)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_selfguided_restoration_c(const uint8_t* dgd8,
                                   int width,
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.c b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.c
index 27a92cf..d6e96a9 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.c
+++ b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
index 1a74a5b..e2f99fa0 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
@@ -133,8 +133,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -144,8 +144,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -157,8 +157,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -172,8 +172,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -183,8 +183,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -207,8 +207,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -218,8 +218,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -231,8 +231,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -242,8 +242,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -342,8 +342,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -356,8 +356,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
@@ -372,8 +372,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -424,8 +424,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -438,8 +438,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -501,26 +501,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
 #define av1_highbd_jnt_convolve_2d av1_highbd_jnt_convolve_2d_c
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 #define av1_highbd_jnt_convolve_2d_copy av1_highbd_jnt_convolve_2d_copy_c
 
 void av1_highbd_jnt_convolve_x_c(const uint16_t* src,
@@ -529,8 +530,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -543,8 +544,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -735,8 +736,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -746,8 +747,8 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
@@ -759,8 +760,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -770,8 +771,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -783,8 +784,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -794,8 +795,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -807,8 +808,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -818,8 +819,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
diff --git a/third_party/libaom/source/config/linux/arm/config/aom_config.c b/third_party/libaom/source/config/linux/arm/config/aom_config.c
index 27a92cf..d6e96a9 100644
--- a/third_party/libaom/source/config/linux/arm/config/aom_config.c
+++ b/third_party/libaom/source/config/linux/arm/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/armv7-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
index cddcc8b..a418e4d7 100644
--- a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
@@ -112,8 +112,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -125,8 +125,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -140,8 +140,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -164,8 +164,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -177,8 +177,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -277,8 +277,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -291,8 +291,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
@@ -307,8 +307,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -359,8 +359,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -373,8 +373,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -436,26 +436,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
 #define av1_highbd_jnt_convolve_2d av1_highbd_jnt_convolve_2d_c
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 #define av1_highbd_jnt_convolve_2d_copy av1_highbd_jnt_convolve_2d_copy_c
 
 void av1_highbd_jnt_convolve_x_c(const uint16_t* src,
@@ -464,8 +465,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -478,8 +479,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -666,8 +667,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -679,8 +680,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -692,8 +693,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -705,8 +706,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
diff --git a/third_party/libaom/source/config/linux/arm64/config/aom_config.c b/third_party/libaom/source/config/linux/arm64/config/aom_config.c
index 66ea6af..e1f78251 100644
--- a/third_party/libaom/source/config/linux/arm64/config/aom_config.c
+++ b/third_party/libaom/source/config/linux/arm64/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/arm64-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/arm64-linux-gcc.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
index 1a74a5b..e2f99fa0 100644
--- a/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
@@ -133,8 +133,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -144,8 +144,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -157,8 +157,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -172,8 +172,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -183,8 +183,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -207,8 +207,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -218,8 +218,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -231,8 +231,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -242,8 +242,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -342,8 +342,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -356,8 +356,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
@@ -372,8 +372,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -424,8 +424,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -438,8 +438,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -501,26 +501,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
 #define av1_highbd_jnt_convolve_2d av1_highbd_jnt_convolve_2d_c
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 #define av1_highbd_jnt_convolve_2d_copy av1_highbd_jnt_convolve_2d_copy_c
 
 void av1_highbd_jnt_convolve_x_c(const uint16_t* src,
@@ -529,8 +530,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -543,8 +544,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -735,8 +736,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -746,8 +747,8 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
@@ -759,8 +760,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -770,8 +771,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -783,8 +784,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -794,8 +795,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -807,8 +808,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -818,8 +819,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
diff --git a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
index bcf9a011..9bd2ed9 100644
--- a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
@@ -112,8 +112,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -125,8 +125,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -140,8 +140,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -164,8 +164,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -177,8 +177,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -277,8 +277,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -291,8 +291,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
@@ -307,8 +307,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -359,8 +359,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -373,8 +373,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -436,26 +436,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
 #define av1_highbd_jnt_convolve_2d av1_highbd_jnt_convolve_2d_c
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 #define av1_highbd_jnt_convolve_2d_copy av1_highbd_jnt_convolve_2d_copy_c
 
 void av1_highbd_jnt_convolve_x_c(const uint16_t* src,
@@ -464,8 +465,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -478,8 +479,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -666,8 +667,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -679,8 +680,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -692,8 +693,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -705,8 +706,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
diff --git a/third_party/libaom/source/config/linux/ia32/config/aom_config.c b/third_party/libaom/source/config/linux/ia32/config/aom_config.c
index 8a54b63..9db327c 100644
--- a/third_party/libaom/source/config/linux/ia32/config/aom_config.c
+++ b/third_party/libaom/source/config/linux/ia32/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/x86-linux.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/x86-linux.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
index 724cd0b68..d3f9eac 100644
--- a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
@@ -204,8 +204,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -215,8 +215,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -226,22 +226,23 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(const uint8_t* src,
-                                            int src_stride,
-                                            uint8_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_scale_c(const uint8_t* src,
                              int src_stride,
@@ -249,8 +250,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -262,26 +263,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_qn,
                                   const int x_step_qn,
                                   const int subpel_y_q4,
                                   const int y_step_qn,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_scale)(const uint8_t* src,
-                                          int src_stride,
-                                          uint8_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_qn,
-                                          const int x_step_qn,
-                                          const int subpel_y_q4,
-                                          const int y_step_qn,
-                                          ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_scale)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_qn,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_sr_c(const uint8_t* src,
                           int src_stride,
@@ -289,8 +291,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -300,8 +302,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -311,22 +313,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_sr)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_horiz_rs_c(const uint8_t* src,
                              int src_stride,
@@ -362,8 +365,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -373,8 +376,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -384,8 +387,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -395,8 +398,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -407,8 +410,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -418,8 +421,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -429,8 +432,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -440,8 +443,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -554,36 +557,38 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
                                       int bd);
-void av1_highbd_convolve_2d_copy_sr_sse2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
-void av1_highbd_convolve_2d_copy_sr_avx2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_copy_sr_sse2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_convolve_2d_copy_sr_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_copy_sr)(
     const uint16_t* src,
     int src_stride,
@@ -591,8 +596,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -604,28 +609,29 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
                                     const int y_step_qn,
                                     ConvolveParams* conv_params,
                                     int bd);
-void av1_highbd_convolve_2d_scale_sse4_1(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int x_step_qn,
-                                         const int subpel_y_q4,
-                                         const int y_step_qn,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_scale_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_scale)(
     const uint16_t* src,
     int src_stride,
@@ -633,8 +639,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int x_step_qn,
     const int subpel_y_q4,
@@ -648,8 +654,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -660,8 +666,8 @@
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -672,8 +678,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -685,8 +691,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -755,8 +761,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -767,8 +773,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -779,8 +785,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -792,8 +798,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -805,8 +811,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -817,8 +823,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -829,8 +835,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -842,8 +848,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -904,32 +910,33 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
-void av1_highbd_jnt_convolve_2d_sse4_1(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 void av1_highbd_jnt_convolve_2d_avx2(const uint16_t* src,
                                      int src_stride,
                                      uint16_t* dst,
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -941,49 +948,52 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
     int bd);
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
-void av1_highbd_jnt_convolve_2d_copy_sse4_1(const uint16_t* src,
-                                            int src_stride,
-                                            uint16_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params,
-                                            int bd);
-void av1_highbd_jnt_convolve_2d_copy_avx2(const uint16_t* src,
-                                          int src_stride,
-                                          uint16_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_q4,
-                                          const int subpel_y_q4,
-                                          ConvolveParams* conv_params,
-                                          int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_jnt_convolve_2d_copy)(
     const uint16_t* src,
     int src_stride,
@@ -991,8 +1001,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1004,8 +1014,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1016,8 +1026,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1028,8 +1038,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1041,8 +1051,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1054,8 +1064,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1066,8 +1076,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1078,8 +1088,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1091,8 +1101,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1407,8 +1417,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -1418,8 +1428,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -1429,22 +1439,23 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_2d)(const uint8_t* src,
-                                        int src_stride,
-                                        uint8_t* dst,
-                                        int dst_stride,
-                                        int w,
-                                        int h,
-                                        InterpFilterParams* filter_params_x,
-                                        InterpFilterParams* filter_params_y,
-                                        const int subpel_x_q4,
-                                        const int subpel_y_q4,
-                                        ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_2d)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_2d_copy_c(const uint8_t* src,
                                 int src_stride,
@@ -1452,8 +1463,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -1463,8 +1474,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1474,8 +1485,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1486,8 +1497,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params);
@@ -1498,8 +1509,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1509,8 +1520,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1520,22 +1531,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_x)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_x)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_y_c(const uint8_t* src,
                           int src_stride,
@@ -1543,8 +1555,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1554,8 +1566,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1565,22 +1577,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_y)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_y)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_selfguided_restoration_c(const uint8_t* dgd8,
                                   int width,
diff --git a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
index 961d3dd7..168825d2 100644
--- a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
@@ -204,8 +204,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -215,8 +215,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -226,22 +226,23 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(const uint8_t* src,
-                                            int src_stride,
-                                            uint8_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_scale_c(const uint8_t* src,
                              int src_stride,
@@ -249,8 +250,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -262,26 +263,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_qn,
                                   const int x_step_qn,
                                   const int subpel_y_q4,
                                   const int y_step_qn,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_scale)(const uint8_t* src,
-                                          int src_stride,
-                                          uint8_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_qn,
-                                          const int x_step_qn,
-                                          const int subpel_y_q4,
-                                          const int y_step_qn,
-                                          ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_scale)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_qn,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_sr_c(const uint8_t* src,
                           int src_stride,
@@ -289,8 +291,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -300,8 +302,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -311,22 +313,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_sr)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_horiz_rs_c(const uint8_t* src,
                              int src_stride,
@@ -362,8 +365,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -373,8 +376,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -384,8 +387,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -395,8 +398,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -407,8 +410,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -418,8 +421,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -429,8 +432,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -440,8 +443,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -587,36 +590,38 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
                                       int bd);
-void av1_highbd_convolve_2d_copy_sr_sse2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
-void av1_highbd_convolve_2d_copy_sr_avx2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_copy_sr_sse2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_convolve_2d_copy_sr_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_copy_sr)(
     const uint16_t* src,
     int src_stride,
@@ -624,8 +629,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -637,28 +642,29 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
                                     const int y_step_qn,
                                     ConvolveParams* conv_params,
                                     int bd);
-void av1_highbd_convolve_2d_scale_sse4_1(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int x_step_qn,
-                                         const int subpel_y_q4,
-                                         const int y_step_qn,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_scale_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_scale)(
     const uint16_t* src,
     int src_stride,
@@ -666,8 +672,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int x_step_qn,
     const int subpel_y_q4,
@@ -681,8 +687,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -693,8 +699,8 @@
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -705,8 +711,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -718,8 +724,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -788,8 +794,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -800,8 +806,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -812,8 +818,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -825,8 +831,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -838,8 +844,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -850,8 +856,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -862,8 +868,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -875,8 +881,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -937,32 +943,33 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
-void av1_highbd_jnt_convolve_2d_sse4_1(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 void av1_highbd_jnt_convolve_2d_avx2(const uint16_t* src,
                                      int src_stride,
                                      uint16_t* dst,
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -974,49 +981,52 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
     int bd);
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
-void av1_highbd_jnt_convolve_2d_copy_sse4_1(const uint16_t* src,
-                                            int src_stride,
-                                            uint16_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params,
-                                            int bd);
-void av1_highbd_jnt_convolve_2d_copy_avx2(const uint16_t* src,
-                                          int src_stride,
-                                          uint16_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_q4,
-                                          const int subpel_y_q4,
-                                          ConvolveParams* conv_params,
-                                          int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_jnt_convolve_2d_copy)(
     const uint16_t* src,
     int src_stride,
@@ -1024,8 +1034,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1037,8 +1047,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1049,8 +1059,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1061,8 +1071,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1074,8 +1084,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1087,8 +1097,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1099,8 +1109,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1111,8 +1121,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1124,8 +1134,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1440,8 +1450,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -1451,8 +1461,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -1462,22 +1472,23 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_2d)(const uint8_t* src,
-                                        int src_stride,
-                                        uint8_t* dst,
-                                        int dst_stride,
-                                        int w,
-                                        int h,
-                                        InterpFilterParams* filter_params_x,
-                                        InterpFilterParams* filter_params_y,
-                                        const int subpel_x_q4,
-                                        const int subpel_y_q4,
-                                        ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_2d)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_2d_copy_c(const uint8_t* src,
                                 int src_stride,
@@ -1485,8 +1496,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -1496,8 +1507,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1507,8 +1518,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1519,8 +1530,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params);
@@ -1531,8 +1542,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1542,8 +1553,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1553,22 +1564,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_x)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_x)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_y_c(const uint8_t* src,
                           int src_stride,
@@ -1576,8 +1588,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1587,8 +1599,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1598,22 +1610,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_y)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_y)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_selfguided_restoration_c(const uint8_t* dgd8,
                                   int width,
diff --git a/third_party/libaom/source/config/win/ia32/config/aom_config.c b/third_party/libaom/source/config/win/ia32/config/aom_config.c
index 8a54b63..9db327c 100644
--- a/third_party/libaom/source/config/win/ia32/config/aom_config.c
+++ b/third_party/libaom/source/config/win/ia32/config/aom_config.c
@@ -9,5 +9,5 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
 #include "aom/aom_codec.h"
-static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/johannkoenig/chromium/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/x86-linux.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
+static const char* const cfg = "-G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=\"/usr/local/google/home/urvang/work/chromium/src/third_party/libaom/source/libaom/build/cmake/toolchains/x86-linux.cmake\" -DCONFIG_AV1_ENCODER=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=16384 -DDECODE_WIDTH_LIMIT=16384";
 const char *aom_codec_build_config(void) {return cfg;}
diff --git a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
index 724cd0b68..d3f9eac 100644
--- a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
@@ -204,8 +204,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -215,8 +215,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -226,22 +226,23 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(const uint8_t* src,
-                                            int src_stride,
-                                            uint8_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_scale_c(const uint8_t* src,
                              int src_stride,
@@ -249,8 +250,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -262,26 +263,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_qn,
                                   const int x_step_qn,
                                   const int subpel_y_q4,
                                   const int y_step_qn,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_scale)(const uint8_t* src,
-                                          int src_stride,
-                                          uint8_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_qn,
-                                          const int x_step_qn,
-                                          const int subpel_y_q4,
-                                          const int y_step_qn,
-                                          ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_scale)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_qn,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_sr_c(const uint8_t* src,
                           int src_stride,
@@ -289,8 +291,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -300,8 +302,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -311,22 +313,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_sr)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_horiz_rs_c(const uint8_t* src,
                              int src_stride,
@@ -362,8 +365,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -373,8 +376,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -384,8 +387,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -395,8 +398,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -407,8 +410,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -418,8 +421,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -429,8 +432,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -440,8 +443,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -554,36 +557,38 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
                                       int bd);
-void av1_highbd_convolve_2d_copy_sr_sse2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
-void av1_highbd_convolve_2d_copy_sr_avx2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_copy_sr_sse2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_convolve_2d_copy_sr_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_copy_sr)(
     const uint16_t* src,
     int src_stride,
@@ -591,8 +596,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -604,28 +609,29 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
                                     const int y_step_qn,
                                     ConvolveParams* conv_params,
                                     int bd);
-void av1_highbd_convolve_2d_scale_sse4_1(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int x_step_qn,
-                                         const int subpel_y_q4,
-                                         const int y_step_qn,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_scale_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_scale)(
     const uint16_t* src,
     int src_stride,
@@ -633,8 +639,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int x_step_qn,
     const int subpel_y_q4,
@@ -648,8 +654,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -660,8 +666,8 @@
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -672,8 +678,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -685,8 +691,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -755,8 +761,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -767,8 +773,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -779,8 +785,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -792,8 +798,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -805,8 +811,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -817,8 +823,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -829,8 +835,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -842,8 +848,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -904,32 +910,33 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
-void av1_highbd_jnt_convolve_2d_sse4_1(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 void av1_highbd_jnt_convolve_2d_avx2(const uint16_t* src,
                                      int src_stride,
                                      uint16_t* dst,
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -941,49 +948,52 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
     int bd);
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
-void av1_highbd_jnt_convolve_2d_copy_sse4_1(const uint16_t* src,
-                                            int src_stride,
-                                            uint16_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params,
-                                            int bd);
-void av1_highbd_jnt_convolve_2d_copy_avx2(const uint16_t* src,
-                                          int src_stride,
-                                          uint16_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_q4,
-                                          const int subpel_y_q4,
-                                          ConvolveParams* conv_params,
-                                          int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_jnt_convolve_2d_copy)(
     const uint16_t* src,
     int src_stride,
@@ -991,8 +1001,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1004,8 +1014,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1016,8 +1026,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1028,8 +1038,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1041,8 +1051,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1054,8 +1064,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1066,8 +1076,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1078,8 +1088,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1091,8 +1101,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1407,8 +1417,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -1418,8 +1428,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -1429,22 +1439,23 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_2d)(const uint8_t* src,
-                                        int src_stride,
-                                        uint8_t* dst,
-                                        int dst_stride,
-                                        int w,
-                                        int h,
-                                        InterpFilterParams* filter_params_x,
-                                        InterpFilterParams* filter_params_y,
-                                        const int subpel_x_q4,
-                                        const int subpel_y_q4,
-                                        ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_2d)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_2d_copy_c(const uint8_t* src,
                                 int src_stride,
@@ -1452,8 +1463,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -1463,8 +1474,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1474,8 +1485,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1486,8 +1497,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params);
@@ -1498,8 +1509,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1509,8 +1520,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1520,22 +1531,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_x)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_x)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_y_c(const uint8_t* src,
                           int src_stride,
@@ -1543,8 +1555,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1554,8 +1566,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1565,22 +1577,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_y)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_y)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_selfguided_restoration_c(const uint8_t* dgd8,
                                   int width,
diff --git a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
index 961d3dd7..168825d2 100644
--- a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
@@ -204,8 +204,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -215,8 +215,8 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
@@ -226,22 +226,23 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(const uint8_t* src,
-                                            int src_stride,
-                                            uint8_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_copy_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_scale_c(const uint8_t* src,
                              int src_stride,
@@ -249,8 +250,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_qn,
                              const int x_step_qn,
                              const int subpel_y_q4,
@@ -262,26 +263,27 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_qn,
                                   const int x_step_qn,
                                   const int subpel_y_q4,
                                   const int y_step_qn,
                                   ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_scale)(const uint8_t* src,
-                                          int src_stride,
-                                          uint8_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_qn,
-                                          const int x_step_qn,
-                                          const int subpel_y_q4,
-                                          const int y_step_qn,
-                                          ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_scale)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_qn,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params);
 
 void av1_convolve_2d_sr_c(const uint8_t* src,
                           int src_stride,
@@ -289,8 +291,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -300,8 +302,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -311,22 +313,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_convolve_2d_sr)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_convolve_2d_sr)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_convolve_horiz_rs_c(const uint8_t* src,
                              int src_stride,
@@ -362,8 +365,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -373,8 +376,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -384,8 +387,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -395,8 +398,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -407,8 +410,8 @@
                          int dst_stride,
                          int w,
                          int h,
-                         InterpFilterParams* filter_params_x,
-                         InterpFilterParams* filter_params_y,
+                         const InterpFilterParams* filter_params_x,
+                         const InterpFilterParams* filter_params_y,
                          const int subpel_x_q4,
                          const int subpel_y_q4,
                          ConvolveParams* conv_params);
@@ -418,8 +421,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -429,8 +432,8 @@
                             int dst_stride,
                             int w,
                             int h,
-                            InterpFilterParams* filter_params_x,
-                            InterpFilterParams* filter_params_y,
+                            const InterpFilterParams* filter_params_x,
+                            const InterpFilterParams* filter_params_y,
                             const int subpel_x_q4,
                             const int subpel_y_q4,
                             ConvolveParams* conv_params);
@@ -440,8 +443,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params);
@@ -587,36 +590,38 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
                                       int bd);
-void av1_highbd_convolve_2d_copy_sr_sse2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
-void av1_highbd_convolve_2d_copy_sr_avx2(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int subpel_y_q4,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_copy_sr_sse2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_convolve_2d_copy_sr_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_copy_sr)(
     const uint16_t* src,
     int src_stride,
@@ -624,8 +629,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -637,28 +642,29 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int x_step_qn,
                                     const int subpel_y_q4,
                                     const int y_step_qn,
                                     ConvolveParams* conv_params,
                                     int bd);
-void av1_highbd_convolve_2d_scale_sse4_1(const uint16_t* src,
-                                         int src_stride,
-                                         uint16_t* dst,
-                                         int dst_stride,
-                                         int w,
-                                         int h,
-                                         InterpFilterParams* filter_params_x,
-                                         InterpFilterParams* filter_params_y,
-                                         const int subpel_x_q4,
-                                         const int x_step_qn,
-                                         const int subpel_y_q4,
-                                         const int y_step_qn,
-                                         ConvolveParams* conv_params,
-                                         int bd);
+void av1_highbd_convolve_2d_scale_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int x_step_qn,
+    const int subpel_y_q4,
+    const int y_step_qn,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_convolve_2d_scale)(
     const uint16_t* src,
     int src_stride,
@@ -666,8 +672,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int x_step_qn,
     const int subpel_y_q4,
@@ -681,8 +687,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -693,8 +699,8 @@
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -705,8 +711,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -718,8 +724,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -788,8 +794,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -800,8 +806,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -812,8 +818,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -825,8 +831,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -838,8 +844,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params,
@@ -850,8 +856,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -862,8 +868,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params,
@@ -875,8 +881,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -937,32 +943,33 @@
                                   int dst_stride,
                                   int w,
                                   int h,
-                                  InterpFilterParams* filter_params_x,
-                                  InterpFilterParams* filter_params_y,
+                                  const InterpFilterParams* filter_params_x,
+                                  const InterpFilterParams* filter_params_y,
                                   const int subpel_x_q4,
                                   const int subpel_y_q4,
                                   ConvolveParams* conv_params,
                                   int bd);
-void av1_highbd_jnt_convolve_2d_sse4_1(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
+void av1_highbd_jnt_convolve_2d_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 void av1_highbd_jnt_convolve_2d_avx2(const uint16_t* src,
                                      int src_stride,
                                      uint16_t* dst,
                                      int dst_stride,
                                      int w,
                                      int h,
-                                     InterpFilterParams* filter_params_x,
-                                     InterpFilterParams* filter_params_y,
+                                     const InterpFilterParams* filter_params_x,
+                                     const InterpFilterParams* filter_params_y,
                                      const int subpel_x_q4,
                                      const int subpel_y_q4,
                                      ConvolveParams* conv_params,
@@ -974,49 +981,52 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
     int bd);
 
-void av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src,
-                                       int src_stride,
-                                       uint16_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params,
-                                       int bd);
-void av1_highbd_jnt_convolve_2d_copy_sse4_1(const uint16_t* src,
-                                            int src_stride,
-                                            uint16_t* dst,
-                                            int dst_stride,
-                                            int w,
-                                            int h,
-                                            InterpFilterParams* filter_params_x,
-                                            InterpFilterParams* filter_params_y,
-                                            const int subpel_x_q4,
-                                            const int subpel_y_q4,
-                                            ConvolveParams* conv_params,
-                                            int bd);
-void av1_highbd_jnt_convolve_2d_copy_avx2(const uint16_t* src,
-                                          int src_stride,
-                                          uint16_t* dst,
-                                          int dst_stride,
-                                          int w,
-                                          int h,
-                                          InterpFilterParams* filter_params_x,
-                                          InterpFilterParams* filter_params_y,
-                                          const int subpel_x_q4,
-                                          const int subpel_y_q4,
-                                          ConvolveParams* conv_params,
-                                          int bd);
+void av1_highbd_jnt_convolve_2d_copy_c(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_sse4_1(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
+void av1_highbd_jnt_convolve_2d_copy_avx2(
+    const uint16_t* src,
+    int src_stride,
+    uint16_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params,
+    int bd);
 RTCD_EXTERN void (*av1_highbd_jnt_convolve_2d_copy)(
     const uint16_t* src,
     int src_stride,
@@ -1024,8 +1034,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1037,8 +1047,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1049,8 +1059,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1061,8 +1071,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1074,8 +1084,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1087,8 +1097,8 @@
                                  int dst_stride,
                                  int w,
                                  int h,
-                                 InterpFilterParams* filter_params_x,
-                                 InterpFilterParams* filter_params_y,
+                                 const InterpFilterParams* filter_params_x,
+                                 const InterpFilterParams* filter_params_y,
                                  const int subpel_x_q4,
                                  const int subpel_y_q4,
                                  ConvolveParams* conv_params,
@@ -1099,8 +1109,8 @@
                                       int dst_stride,
                                       int w,
                                       int h,
-                                      InterpFilterParams* filter_params_x,
-                                      InterpFilterParams* filter_params_y,
+                                      const InterpFilterParams* filter_params_x,
+                                      const InterpFilterParams* filter_params_y,
                                       const int subpel_x_q4,
                                       const int subpel_y_q4,
                                       ConvolveParams* conv_params,
@@ -1111,8 +1121,8 @@
                                     int dst_stride,
                                     int w,
                                     int h,
-                                    InterpFilterParams* filter_params_x,
-                                    InterpFilterParams* filter_params_y,
+                                    const InterpFilterParams* filter_params_x,
+                                    const InterpFilterParams* filter_params_y,
                                     const int subpel_x_q4,
                                     const int subpel_y_q4,
                                     ConvolveParams* conv_params,
@@ -1124,8 +1134,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params,
@@ -1440,8 +1450,8 @@
                            int dst_stride,
                            int w,
                            int h,
-                           InterpFilterParams* filter_params_x,
-                           InterpFilterParams* filter_params_y,
+                           const InterpFilterParams* filter_params_x,
+                           const InterpFilterParams* filter_params_y,
                            const int subpel_x_q4,
                            const int subpel_y_q4,
                            ConvolveParams* conv_params);
@@ -1451,8 +1461,8 @@
                                int dst_stride,
                                int w,
                                int h,
-                               InterpFilterParams* filter_params_x,
-                               InterpFilterParams* filter_params_y,
+                               const InterpFilterParams* filter_params_x,
+                               const InterpFilterParams* filter_params_y,
                                const int subpel_x_q4,
                                const int subpel_y_q4,
                                ConvolveParams* conv_params);
@@ -1462,22 +1472,23 @@
                               int dst_stride,
                               int w,
                               int h,
-                              InterpFilterParams* filter_params_x,
-                              InterpFilterParams* filter_params_y,
+                              const InterpFilterParams* filter_params_x,
+                              const InterpFilterParams* filter_params_y,
                               const int subpel_x_q4,
                               const int subpel_y_q4,
                               ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_2d)(const uint8_t* src,
-                                        int src_stride,
-                                        uint8_t* dst,
-                                        int dst_stride,
-                                        int w,
-                                        int h,
-                                        InterpFilterParams* filter_params_x,
-                                        InterpFilterParams* filter_params_y,
-                                        const int subpel_x_q4,
-                                        const int subpel_y_q4,
-                                        ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_2d)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_2d_copy_c(const uint8_t* src,
                                 int src_stride,
@@ -1485,8 +1496,8 @@
                                 int dst_stride,
                                 int w,
                                 int h,
-                                InterpFilterParams* filter_params_x,
-                                InterpFilterParams* filter_params_y,
+                                const InterpFilterParams* filter_params_x,
+                                const InterpFilterParams* filter_params_y,
                                 const int subpel_x_q4,
                                 const int subpel_y_q4,
                                 ConvolveParams* conv_params);
@@ -1496,8 +1507,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1507,8 +1518,8 @@
                                    int dst_stride,
                                    int w,
                                    int h,
-                                   InterpFilterParams* filter_params_x,
-                                   InterpFilterParams* filter_params_y,
+                                   const InterpFilterParams* filter_params_x,
+                                   const InterpFilterParams* filter_params_y,
                                    const int subpel_x_q4,
                                    const int subpel_y_q4,
                                    ConvolveParams* conv_params);
@@ -1519,8 +1530,8 @@
     int dst_stride,
     int w,
     int h,
-    InterpFilterParams* filter_params_x,
-    InterpFilterParams* filter_params_y,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
     const int subpel_x_q4,
     const int subpel_y_q4,
     ConvolveParams* conv_params);
@@ -1531,8 +1542,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1542,8 +1553,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1553,22 +1564,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_x)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_x)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_jnt_convolve_y_c(const uint8_t* src,
                           int src_stride,
@@ -1576,8 +1588,8 @@
                           int dst_stride,
                           int w,
                           int h,
-                          InterpFilterParams* filter_params_x,
-                          InterpFilterParams* filter_params_y,
+                          const InterpFilterParams* filter_params_x,
+                          const InterpFilterParams* filter_params_y,
                           const int subpel_x_q4,
                           const int subpel_y_q4,
                           ConvolveParams* conv_params);
@@ -1587,8 +1599,8 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
@@ -1598,22 +1610,23 @@
                              int dst_stride,
                              int w,
                              int h,
-                             InterpFilterParams* filter_params_x,
-                             InterpFilterParams* filter_params_y,
+                             const InterpFilterParams* filter_params_x,
+                             const InterpFilterParams* filter_params_y,
                              const int subpel_x_q4,
                              const int subpel_y_q4,
                              ConvolveParams* conv_params);
-RTCD_EXTERN void (*av1_jnt_convolve_y)(const uint8_t* src,
-                                       int src_stride,
-                                       uint8_t* dst,
-                                       int dst_stride,
-                                       int w,
-                                       int h,
-                                       InterpFilterParams* filter_params_x,
-                                       InterpFilterParams* filter_params_y,
-                                       const int subpel_x_q4,
-                                       const int subpel_y_q4,
-                                       ConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_jnt_convolve_y)(
+    const uint8_t* src,
+    int src_stride,
+    uint8_t* dst,
+    int dst_stride,
+    int w,
+    int h,
+    const InterpFilterParams* filter_params_x,
+    const InterpFilterParams* filter_params_y,
+    const int subpel_x_q4,
+    const int subpel_y_q4,
+    ConvolveParams* conv_params);
 
 void av1_selfguided_restoration_c(const uint8_t* dgd8,
                                   int width,
diff --git a/tools/binary_size/libsupersize/start_server.py b/tools/binary_size/libsupersize/start_server.py
index 05178d84..e956108e 100644
--- a/tools/binary_size/libsupersize/start_server.py
+++ b/tools/binary_size/libsupersize/start_server.py
@@ -47,5 +47,6 @@
   httpd = BaseHTTPServer.HTTPServer(server_addr, SupersizeHTTPRequestHandler)
 
   sa = httpd.socket.getsockname()
-  logging.warning('Server ready at http://%s:%d', sa[0], sa[1])
+  logging.warning('Server ready at http://%s:%d?data_url=data.ndjson',
+                  sa[0], sa[1])
   httpd.serve_forever()
diff --git a/tools/binary_size/libsupersize/static/index.html b/tools/binary_size/libsupersize/static/index.html
index d7c644a..f514257 100644
--- a/tools/binary_size/libsupersize/static/index.html
+++ b/tools/binary_size/libsupersize/static/index.html
@@ -225,7 +225,8 @@
     <script defer src="tree-ui.js"></script>
     <script defer async>
         if ('serviceWorker' in navigator) {
-            navigator.serviceWorker.register('sw.js');
+            navigator.serviceWorker.register('sw.js')
+                .catch(() => console.warn('ServiceWorker not loaded.'));
         }
     </script>
 </head>
@@ -288,6 +289,8 @@
             </button>
         </header>
 
+        <input type="hidden" name="data_url">
+
         <fieldset>
             <legend class="subhead">Size options</legend>
             <div class="checkbox-wrapper">
diff --git a/tools/binary_size/libsupersize/static/start-worker.js b/tools/binary_size/libsupersize/static/start-worker.js
index fb983b2..1b98f42 100644
--- a/tools/binary_size/libsupersize/static/start-worker.js
+++ b/tools/binary_size/libsupersize/static/start-worker.js
@@ -92,4 +92,4 @@
 const worker = new TreeWorker(_innerWorker);
 // Kick off the worker ASAP so it can start parsing data faster.
 // Subsequent calls will just use a worker locally.
-const treeReady = worker.loadTree('data.ndjson');
+const treeReady = worker.loadTree('from-url://');
diff --git a/tools/binary_size/libsupersize/static/tree-worker.js b/tools/binary_size/libsupersize/static/tree-worker.js
index 5c9eef2..d0ae124 100644
--- a/tools/binary_size/libsupersize/static/tree-worker.js
+++ b/tools/binary_size/libsupersize/static/tree-worker.js
@@ -37,6 +37,7 @@
 importScripts('./shared.js');
 
 const _PATH_SEP = '/';
+const _DEMO_DATA_URL = 'demo.ndjson';
 
 /** @param {FileEntry} fileEntry */
 function getSourcePath(fileEntry) {
@@ -559,6 +560,7 @@
 function parseOptions(options) {
   const params = new URLSearchParams(options);
 
+  const url = params.get('data_url');
   const groupBy = params.get('group_by') || 'source_path';
   const methodCountMode = params.has('method_count');
   const filterGeneratedFiles = params.has('generated_filter');
@@ -630,7 +632,7 @@
     return filters.every(fn => fn(symbolNode));
   }
 
-  return {groupBy, filterTest};
+  return {groupBy, filterTest, url};
 }
 
 /** @type {TreeBuilder | null} */
@@ -639,13 +641,13 @@
 
 /**
  * Assemble a tree when this worker receives a message.
- * @param {string} options Query string containing options for the builder.
+ * @param {string} groupBy Sets how the tree is grouped.
+ * @param {(symbolNode: TreeNode) => boolean} filterTest Filter function that
+ * each symbol is tested against
  * @param {(msg: TreeProgress) => void} onProgress
  * @returns {Promise<TreeProgress>}
  */
-async function buildTree(options, onProgress) {
-  const {groupBy, filterTest} = parseOptions(options);
-
+async function buildTree(groupBy, filterTest, onProgress) {
   /** @type {Meta | null} Object from the first line of the data file */
   let meta = null;
 
@@ -736,10 +738,28 @@
 }
 
 const actions = {
-  /** @param {{input:string,options:string}} data */
+  /** @param {{input:string|null,options:string}} data */
   load(data) {
-    if (data.input) fetcher.setInput(data.input);
-    return buildTree(data.options, progress => {
+    const {groupBy, filterTest, url} = parseOptions(data.options);
+    if (data.input === 'from-url://') {
+      if (url) {
+        // Display the data from the `data_url` query parameter
+        console.info('Displaying data from', url);
+        fetcher.setInput(url);
+      } else {
+        // Display starter content if nothing was specified.
+        console.info('Displaying demo data');
+        // The demo file only exists in the GCS bucket where the UI is hosted.
+        // When using `start_server`, no data is shown until the user uploads
+        // something.
+        fetcher.setInput(_DEMO_DATA_URL);
+      }
+    } else if (data.input != null) {
+      console.info('Displaying uploaded data');
+      fetcher.setInput(data.input);
+    }
+
+    return buildTree(groupBy, filterTest, progress => {
       // @ts-ignore
       self.postMessage(progress);
     });
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8228f0f..464526c 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3989,6 +3989,11 @@
   <int value="1" label="Deprecated ciphers enabled"/>
 </enum>
 
+<enum name="BooleanDetected">
+  <int value="0" label="Not detected"/>
+  <int value="1" label="Detected"/>
+</enum>
+
 <enum name="BooleanDidEvict">
   <int value="0" label="Did not evict"/>
   <int value="1" label="Did evict"/>
@@ -9533,8 +9538,11 @@
   <int value="16653985" label="NTP_SNIPPETS_THUMBNAILS"/>
   <int value="17400350" label="WEB_HISTORY_SERVICE"/>
   <int value="18300705" label="GCM_DRIVER"/>
+  <int value="18858893" label="OFFLINE_PAGES_DOWNLOAD_FILE"/>
+  <int value="19185953" label="OFFLINE_PAGES_PREFETCH"/>
   <int value="22265491" label="POLICY"/>
   <int value="24978481" label="CLOUD_PRINT"/>
+  <int value="25790702" label="APPCACHE_UPDATE_JOB"/>
   <int value="26216847" label="GAIA"/>
   <int value="27071967" label="SAFE_BROWSING"/>
   <int value="27915688" label="GAIA"/>
@@ -9543,12 +9551,14 @@
   <int value="30913825" label="SUPERVISED_USER"/>
   <int value="32585152" label="GAIA"/>
   <int value="35370363" label="SUGGESTIONS"/>
+  <int value="35380758" label="RESUMED_DOWNLOADS"/>
   <int value="35565745" label="GAIA"/>
   <int value="36859107" label="SEARCH_PROVIDER_LOGOS"/>
   <int value="39877119" label="GAIA"/>
   <int value="42848942" label="SAFE_BROWSING"/>
   <int value="43206794" label="SUPERVISED_USER"/>
   <int value="44494884" label="NTP_TILES"/>
+  <int value="44583172" label="OFFLINE_PAGES_PREFETCH_DOWNLOAD"/>
   <int value="44583821" label="SAFE_BROWSING"/>
   <int value="44606780" label="RAPPOR"/>
   <int value="46188932" label="NETWORK_TIME_TRACKER"/>
@@ -9568,11 +9578,13 @@
   <int value="67638271" label="CLOUD_PRINT"/>
   <int value="68561428" label="DATA_REDUCTION_PROXY"/>
   <int value="68745894" label="SAFE_BROWSING"/>
+  <int value="69881286" label="OMNIBOX_ANSWERS_IMAGE"/>
   <int value="70126372" label="SAFE_BROWSING"/>
   <int value="71251498" label="CLOUD_PRINT"/>
   <int value="71578042" label="CLOUD_PRINT"/>
   <int value="72354423" label="INVALIDATION"/>
   <int value="73107389" label="OMNIBOX"/>
+  <int value="73772528" label="DOWNLOAD_VIA_CONTEXT_MENU"/>
   <int value="75153841" label="SAFE_BROWSING"/>
   <int value="77597059" label="DOMAIN_RELIABILITY"/>
   <int value="78544924" label="SUPERVISED_USER"/>
@@ -9600,18 +9612,22 @@
   <int value="109200878" label="OMNIBOX"/>
   <int value="110307337" label="WEB_HISTORY_SERVICE"/>
   <int value="111712433" label="CLOUD_PRINT"/>
+  <int value="112189210" label="FAVICON_LOADER"/>
   <int value="113231892" label="UPDATE_CLIENT"/>
   <int value="115188287" label="VARIATIONS"/>
   <int value="115907811" label="SAFE_BROWSING"/>
   <int value="116426676" label="GAIA"/>
   <int value="117649486" label="SPELL_CHECKER"/>
   <int value="117782019" label="POLICY"/>
+  <int value="117963307" label="SERVICE_WORKER_WRITE_TO_CACHE_JOB"/>
   <int value="119542033" label="GCM_DRIVER"/>
   <int value="119677115" label="SUPERVISED_USER"/>
+  <int value="121842329" label="WEBAPK_ICON_HASHER"/>
   <int value="124950347" label="SAFE_BROWSING"/>
   <int value="125522256" label="SAFE_BROWSING"/>
   <int value="125596241" label="UPDATE_CLIENT"/>
   <int value="126122632" label="WEB_HISTORY_SERVICE"/>
+  <int value="129872904" label="SERVICE_WORKER_NAVIGATION_PRELOAD"/>
   <int value="131236802" label="DATA_REDUCTION_PROXY"/>
   <int value="132055347" label="CLOUD_PRINT"/>
   <int value="132553989" label="SPELL_CHECKER"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c28e1cd..770adafc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -10956,6 +10956,24 @@
   </summary>
 </histogram>
 
+<histogram name="ChildProcess.FieldTrials.CreateFromShmemSuccess"
+    enum="BooleanSuccess" expires_after="M72">
+  <owner>asvitkine@chromium.org</owner>
+  <summary>
+    Whether creating field trials from shared memory succeeded. Recorded by each
+    child process on process startup.
+  </summary>
+</histogram>
+
+<histogram name="ChildProcess.FieldTrials.CreateFromSwitchSuccess"
+    enum="BooleanSuccess" expires_after="M72">
+  <owner>asvitkine@chromium.org</owner>
+  <summary>
+    Whether creating field trials from --force-fieldtrials switch succeeded.
+    Recorded by each child process on process startup.
+  </summary>
+</histogram>
+
 <histogram name="ChildProcess.HangRendererType" enum="RendererUnresponsiveType">
   <obsolete>
     Deprecated 3/2017.
@@ -12984,8 +13002,8 @@
 </histogram>
 
 <histogram
-    name="Compositing.SurfaceAggregator.LatestInFlightSurface.
-          ManhattanDistanceToPrimary" units="surfaces">
+    name="Compositing.SurfaceAggregator.LatestInFlightSurface.ManhattanDistanceToPrimary"
+    units="surfaces">
   <owner>akaba@chromium.org</owner>
   <owner>fsamuel@chromium.org</owner>
   <summary>
@@ -12996,6 +13014,10 @@
 
 <histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.MissingSurface"
     units="quads">
+  <obsolete>
+    Deprecated 07/2018 in issue 865597 in order to avoid spurious error messages
+    on Viz process crash.
+  </obsolete>
   <owner>kylechar@chromium.org</owner>
   <summary>
     The number of SurfaceDrawQuads where the surface doesn't exist. This is
@@ -13005,6 +13027,10 @@
 
 <histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.NoActiveFrame"
     units="quads">
+  <obsolete>
+    Deprecated 07/2018 in issue 865597 in order to avoid spurious error messages
+    on Viz process crash.
+  </obsolete>
   <owner>kylechar@chromium.org</owner>
   <summary>
     The number of SurfaceDrawQuads where the surface exists but doesn't have an
@@ -13085,7 +13111,7 @@
   <summary>Tracks the reason for removing a temporary reference.</summary>
 </histogram>
 
-<histogram name="Compositing.SurfaceManager.TemporarySurfaces"
+<histogram name="Compositing.SurfaceManager.TemporaryReferences"
     units="references">
   <owner>akaba@chromium.org</owner>
   <owner>fsamuel@chromium.org</owner>
@@ -53698,6 +53724,15 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.HandshakeTimeout.PathDegradingDetected"
+    enum="BooleanDetected">
+  <owner>zhongyi@chromium.org</owner>
+  <summary>
+    Whether path degrading has been detected by the time a QUIC connection is
+    closed due to handshake timeout.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.HeadersHOLBlockedTime" units="Milliseconds">
   <obsolete>
     The experiments with head of line blocking have been completed, and the code
@@ -98197,9 +98232,9 @@
 </histogram>
 
 <histogram name="Style.AuthorStyleSheet.ParseTime" units="microseconds">
-  <owner>csharrison@chromium.org</owner>
+  <owner>futhark@chromium.org</owner>
   <summary>
-    Microseconds spent in StyleSheetContents::parseAuthorStyleSheet.
+    Microseconds spent in StyleSheetContents::ParseAuthorStyleSheet.
 
     Warning: This metric may include reports from clients with low-resolution
     clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
@@ -98210,6 +98245,9 @@
 </histogram>
 
 <histogram name="Style.LazyUsage.Percent" enum="LazyCSSParseUsage">
+  <obsolete>
+    Deprecated 07/2018, no longer used.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Tracks % of lazy rules that ended up needing to be parsed. A sheet logs
@@ -98221,6 +98259,9 @@
 </histogram>
 
 <histogram name="Style.TotalLazyRules" units="count">
+  <obsolete>
+    Deprecated 07/2018, no longer used.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Tracks the total number of rules that have parsing lazily deferred in an
@@ -98229,6 +98270,9 @@
 </histogram>
 
 <histogram name="Style.TotalLazyRules.FullUsage" units="count">
+  <obsolete>
+    Deprecated 07/2018, no longer used.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Tracks the total number of rules that have parsing lazily deferred in an
@@ -98237,9 +98281,9 @@
 </histogram>
 
 <histogram name="Style.UpdateTime" units="microseconds">
-  <owner>csharrison@chromium.org</owner>
+  <owner>futhark@chromium.org</owner>
   <summary>
-    Microseconds spent in Document::updateStyle.
+    Microseconds spent in Document::UpdateStyle.
 
     Warning: This metric may include reports from clients with low-resolution
     clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 530c68d8..c7d83bfd 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -2343,6 +2343,107 @@
   </metric>
 </event>
 
+<event name="Notification">
+  <owner>yangsharon@google.com</owner>
+  <owner>awdf@chromium.org</owner>
+  <owner>peter@chromium.org</owner>
+  <summary>
+    A notification event corresponds with the entire lifespan of a single
+    notification, and will be logged to UKM when the notification is deleted
+    from the notification database.
+  </summary>
+  <metric name="ClosedReason">
+    <summary>
+      Enum for how the notification was closed. {user, developer, unknown}
+    </summary>
+  </metric>
+  <metric name="DidReplaceAnotherNotification">
+    <summary>
+      Boolean value representing whether a tag is present and a previously shown
+      notification has been replaced. For UKM logging, we treat a replacement
+      notification as a new notification.
+    </summary>
+  </metric>
+  <metric name="DidUserOpenSettings">
+    <summary>
+      Boolean value indicating whether the user accessed the Chrome provided
+      settings from the notification.
+    </summary>
+  </metric>
+  <metric name="HasBadge">
+    <summary>
+      Boolean value representing if a badge URL was included.
+    </summary>
+  </metric>
+  <metric name="HasIcon">
+    <summary>
+      Boolean value representing if an icon URL was included.
+    </summary>
+  </metric>
+  <metric name="HasImage">
+    <summary>
+      Boolean value representing if an image URL was included.
+    </summary>
+  </metric>
+  <metric name="HasRenotify">
+    <summary>
+      Boolean value representing whether default notification indicators (sound,
+      vibration, light) should be played again if the notification is replacing
+      an older notification.
+    </summary>
+  </metric>
+  <metric name="HasTag">
+    <summary>
+      Boolean value representing if a tag is present.
+    </summary>
+  </metric>
+  <metric name="IsSilent">
+    <summary>
+      Boolean value representing  whether default notification indicators
+      (sound, vibration, light) should be suppressed.
+    </summary>
+  </metric>
+  <metric name="NumActionButtonClicks">
+    <summary>
+      Number of clicks on developer provided action buttons.
+    </summary>
+  </metric>
+  <metric name="NumActions">
+    <summary>
+      Number of developer specified actions that can be taken.
+    </summary>
+  </metric>
+  <metric name="NumClicks">
+    <summary>
+      Number of clicks, excluding action buttons. I.e. clicks on the
+      notification itself.
+    </summary>
+  </metric>
+  <metric name="RequireInteraction">
+    <summary>
+      Boolean value representing whether the notification should remain onscreen
+      indefinitely, rather than being auto-minimized to the notification center
+      (if allowed by platform).
+    </summary>
+  </metric>
+  <metric name="TimeUntilClose">
+    <summary>
+      The length of time, in ms, between when the notification was triggered and
+      when it was closed.
+    </summary>
+  </metric>
+  <metric name="TimeUntilFirstClick">
+    <summary>
+      Time, in ms, between when the notification is shown and the first click.
+    </summary>
+  </metric>
+  <metric name="TimeUntilLastClick">
+    <summary>
+      Time, in ms, between when the notification is shown and the last click.
+    </summary>
+  </metric>
+</event>
+
 <event name="OfflinePages.SavePageRequested">
   <owner>petewil@chromium.org</owner>
   <metric name="RequestedFromForeground">
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 729deda7..5fbc1c7 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -3,7 +3,7 @@
 Benchmark name,Individual owners,Component,Documentation
 angle_perftests,"jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE,
 blink_perf.bindings,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",,https://bit.ly/blink-perf-benchmarks
-blink_perf.canvas,junov@chromium.org,,https://bit.ly/blink-perf-benchmarks
+blink_perf.canvas,fserb@chromium.org,,https://bit.ly/blink-perf-benchmarks
 blink_perf.css,futhark@chromium.org,,https://bit.ly/blink-perf-benchmarks
 blink_perf.dom,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",,https://bit.ly/blink-perf-benchmarks
 blink_perf.events,hayato@chromium.org,,https://bit.ly/blink-perf-benchmarks
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index c016fe4..cd45639 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -376,7 +376,7 @@
 
 
 
-@benchmark.Info(emails=['junov@chromium.org'],
+@benchmark.Info(emails=['fserb@chromium.org'],
                 documentation_url='https://bit.ly/blink-perf-benchmarks')
 class BlinkPerfCanvas(_BlinkPerfBenchmark):
   subdir = 'canvas'
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 17c2638..b0ea4b3 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -147,7 +147,7 @@
         {
           'isolate': 'performance_webview_test_suite',
           'extra_args': [
-            '--test-shard-map-filename=pixel2_webview_7_shard_map.json',
+            '--test-shard-map-filename=android_pixel2_webview_shard_map.json',
           ],
           'num_shards': 7
         }
@@ -167,7 +167,7 @@
           'isolate': 'performance_test_suite',
           'extra_args': [
             '--run-ref-build',
-            '--test-shard-map-filename=pixel2_7_shard_map.json',
+            '--test-shard-map-filename=android_pixel2_shard_map.json',
           ],
           'num_shards': 7
         }
diff --git a/tools/perf/core/shard_maps/pixel2_7_shard_map.json b/tools/perf/core/shard_maps/android_pixel2_shard_map.json
similarity index 76%
rename from tools/perf/core/shard_maps/pixel2_7_shard_map.json
rename to tools/perf/core/shard_maps/android_pixel2_shard_map.json
index 20e8fdb..5d9804c 100644
--- a/tools/perf/core/shard_maps/pixel2_7_shard_map.json
+++ b/tools/perf/core/shard_maps/android_pixel2_shard_map.json
@@ -4,14 +4,22 @@
             "system_health.common_mobile": {},
             "v8.browsing_mobile-future": {},
             "rendering.mobile": {
-                "end": 284
+                "end": 83
             }
         }
     },
     "1": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 284
+                "begin": 83,
+                "end": 389
+            }
+        }
+    },
+    "2": {
+        "benchmarks": {
+            "rendering.mobile": {
+                "begin": 389
             },
             "blink_perf.image_decoder": {},
             "power.desktop": {},
@@ -27,24 +35,38 @@
             "dummy_benchmark.noisy_benchmark_1": {},
             "blink_perf.svg": {},
             "system_health.webview_startup": {},
-            "speedometer2-future": {},
-            "jetstream": {},
-            "smoothness.tough_pinch_zoom_cases": {}
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "power.typical_10_mobile": {},
-            "v8.runtime_stats.top_25": {},
-            "loading.mobile": {
-                "end": 53
+            "v8.browsing_mobile": {
+                "end": 11
             }
         }
     },
     "3": {
         "benchmarks": {
+            "v8.browsing_mobile": {
+                "begin": 11
+            },
+            "jetstream": {},
+            "smoothness.tough_pinch_zoom_cases": {},
+            "speedometer2-future": {},
+            "power.typical_10_mobile": {},
+            "v8.runtime_stats.top_25": {},
             "loading.mobile": {
-                "begin": 53
+                "end": 28
+            }
+        }
+    },
+    "4": {
+        "benchmarks": {
+            "loading.mobile": {
+                "begin": 28,
+                "end": 93
+            }
+        }
+    },
+    "5": {
+        "benchmarks": {
+            "loading.mobile": {
+                "begin": 93
             },
             "speedometer2": {},
             "v8.browsing_desktop-future": {},
@@ -55,11 +77,7 @@
             "memory.long_running_idle_gmail_background_tbmv2": {},
             "tab_switching.typical_25": {},
             "blink_perf.dom": {},
-            "media.mobile": {}
-        }
-    },
-    "4": {
-        "benchmarks": {
+            "media.mobile": {},
             "start_with_url.cold.startup_pages": {},
             "blink_perf.bindings": {},
             "system_health.memory_desktop": {},
@@ -75,39 +93,29 @@
             "kraken": {},
             "oortonline_tbmv2": {},
             "system_health.common_desktop": {},
-            "rasterize_and_record_micro.top_25": {
-                "end": 22
-            }
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "rasterize_and_record_micro.top_25": {
-                "begin": 22
-            },
+            "rasterize_and_record_micro.top_25": {},
             "dummy_benchmark.stable_benchmark_1": {},
             "system_health.memory_mobile": {
-                "end": 48
+                "end": 7
             }
         }
     },
     "6": {
         "benchmarks": {
             "system_health.memory_mobile": {
-                "begin": 48
+                "begin": 7
             },
             "rendering.desktop": {},
             "blink_perf.css": {},
-            "v8.browsing_mobile": {},
             "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
+        "num_stories": 1985,
+        "predicted_min_shard_time": 16140.0,
+        "predicted_min_shard_index": 4,
+        "predicted_max_shard_time": 16848.0,
+        "predicted_max_shard_index": 5
     }
 }
\ 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/android_pixel2_webview_shard_map.json
similarity index 76%
copy from tools/perf/core/shard_maps/pixel2_7_shard_map.json
copy to tools/perf/core/shard_maps/android_pixel2_webview_shard_map.json
index 20e8fdb..5d9804c 100644
--- a/tools/perf/core/shard_maps/pixel2_7_shard_map.json
+++ b/tools/perf/core/shard_maps/android_pixel2_webview_shard_map.json
@@ -4,14 +4,22 @@
             "system_health.common_mobile": {},
             "v8.browsing_mobile-future": {},
             "rendering.mobile": {
-                "end": 284
+                "end": 83
             }
         }
     },
     "1": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 284
+                "begin": 83,
+                "end": 389
+            }
+        }
+    },
+    "2": {
+        "benchmarks": {
+            "rendering.mobile": {
+                "begin": 389
             },
             "blink_perf.image_decoder": {},
             "power.desktop": {},
@@ -27,24 +35,38 @@
             "dummy_benchmark.noisy_benchmark_1": {},
             "blink_perf.svg": {},
             "system_health.webview_startup": {},
-            "speedometer2-future": {},
-            "jetstream": {},
-            "smoothness.tough_pinch_zoom_cases": {}
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "power.typical_10_mobile": {},
-            "v8.runtime_stats.top_25": {},
-            "loading.mobile": {
-                "end": 53
+            "v8.browsing_mobile": {
+                "end": 11
             }
         }
     },
     "3": {
         "benchmarks": {
+            "v8.browsing_mobile": {
+                "begin": 11
+            },
+            "jetstream": {},
+            "smoothness.tough_pinch_zoom_cases": {},
+            "speedometer2-future": {},
+            "power.typical_10_mobile": {},
+            "v8.runtime_stats.top_25": {},
             "loading.mobile": {
-                "begin": 53
+                "end": 28
+            }
+        }
+    },
+    "4": {
+        "benchmarks": {
+            "loading.mobile": {
+                "begin": 28,
+                "end": 93
+            }
+        }
+    },
+    "5": {
+        "benchmarks": {
+            "loading.mobile": {
+                "begin": 93
             },
             "speedometer2": {},
             "v8.browsing_desktop-future": {},
@@ -55,11 +77,7 @@
             "memory.long_running_idle_gmail_background_tbmv2": {},
             "tab_switching.typical_25": {},
             "blink_perf.dom": {},
-            "media.mobile": {}
-        }
-    },
-    "4": {
-        "benchmarks": {
+            "media.mobile": {},
             "start_with_url.cold.startup_pages": {},
             "blink_perf.bindings": {},
             "system_health.memory_desktop": {},
@@ -75,39 +93,29 @@
             "kraken": {},
             "oortonline_tbmv2": {},
             "system_health.common_desktop": {},
-            "rasterize_and_record_micro.top_25": {
-                "end": 22
-            }
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "rasterize_and_record_micro.top_25": {
-                "begin": 22
-            },
+            "rasterize_and_record_micro.top_25": {},
             "dummy_benchmark.stable_benchmark_1": {},
             "system_health.memory_mobile": {
-                "end": 48
+                "end": 7
             }
         }
     },
     "6": {
         "benchmarks": {
             "system_health.memory_mobile": {
-                "begin": 48
+                "begin": 7
             },
             "rendering.desktop": {},
             "blink_perf.css": {},
-            "v8.browsing_mobile": {},
             "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
+        "num_stories": 1985,
+        "predicted_min_shard_time": 16140.0,
+        "predicted_min_shard_index": 4,
+        "predicted_max_shard_time": 16848.0,
+        "predicted_max_shard_index": 5
     }
 }
\ 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
deleted file mode 100644
index 0a0467e..0000000
--- a/tools/perf/core/shard_maps/pixel2_webview_7_shard_map.json
+++ /dev/null
@@ -1,87 +0,0 @@
-{
-    "0": {
-        "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.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": {}
-    },
-    "2": {
-        "benchmarks": {}
-    },
-    "3": {
-        "benchmarks": {}
-    },
-    "4": {
-        "benchmarks": {}
-    },
-    "5": {
-        "benchmarks": {}
-    },
-    "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/core/shard_maps/timing_data/android_pixel2_story_timing.json b/tools/perf/core/shard_maps/timing_data/android_pixel2_story_timing.json
new file mode 100644
index 0000000..67ac46cf
--- /dev/null
+++ b/tools/perf/core/shard_maps/timing_data/android_pixel2_story_timing.json
@@ -0,0 +1,8014 @@
+[
+    {
+        "duration": "20.0",
+        "name": "blink_perf.bindings/append-child.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.bindings/create-element.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/document-implementation.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/dom-attribute-on-prototoype.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/first-child.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.bindings/gc-forest.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.bindings/gc-mini-tree.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.bindings/gc-tree.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/get-attribute-rare.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/get-attribute.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.bindings/get-element-by-id.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/get-elements-by-tag-name.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/id-getter.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/id-setter.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.bindings/indexed-getter.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/insert-before.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/named-property-enumerator.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.bindings/node-list-access.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/node-type.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.bindings/post-message.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/sequence-conversion-array.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/sequence-conversion-custom-iterator.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.bindings/serialize-array.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.bindings/serialize-long-string.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.bindings/serialize-map.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.bindings/serialize-nested-array.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/set-attribute-rare.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/set-attribute.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/structured-clone-json-deserialize.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/structured-clone-json-serialize.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.bindings/structured-clone-long-string-deserialize.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.bindings/structured-clone-long-string-serialize.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-array.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-same-type.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-typed.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/typed-array-set-from-typed.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/undefined-first-child.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/undefined-get-element-by-id.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/undefined-id-getter.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.canvas/createImageBitmapFromImageData.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.canvas/draw-dynamic-canvas-2d-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.canvas/draw-hw-accelerated-canvas-2d-to-sw-canvas-2d.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.canvas/draw-static-canvas-2d-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.canvas/draw-video-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.canvas/drawimage-not-pixelaligned.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.canvas/drawimage.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.canvas/getImageData.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.canvas/getImageDataColorManaged.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.canvas/putImageData.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.canvas/toBlob_duration.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.canvas/toBlob_duration_jpeg.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.canvas/transferFromImageBitmap.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.canvas/upload-canvas-2d-to-texture.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.canvas/upload-video-to-sub-texture.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.canvas/upload-video-to-texture.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.canvas/upload-webgl-to-texture.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.css/AttributeDescendantSelector.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.css/CSSPropertySetterGetter.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.css/CSSPropertySetterGetterMethods.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.css/CSSPropertyUpdateValue.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleChildClassSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleChildElementSelectors.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleElementSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleGrandChildElementSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleMultipleClassSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleMultipleQualifiedDataAttributesWithValuesSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleNestedPseudoSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStylePairOfNthChildSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStylePartialAttributeMatchingSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeWithValueSelector.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.css/ChangeStyleShallowTree.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleSingleClassSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleSingleNthChildSelector.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.css/ChangeStyleSinglePseudoSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleUniversalSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeSelector.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeWithValueSelector.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.css/ClassDescendantSelector.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.css/ClassInvalidation.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.css/FocusUpdate.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.css/LoadBootstrapBlog.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.css/LoadMaterializeStarterPage.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.css/LoadSemanticPageExample.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.css/PseudoClassSelectors.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.css/SelectorCountScaling.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.dom/addRange.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.dom/delete-in-password-field.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.dom/div-editable.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.dom/inner_html_with_selection.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.dom/long-sibling-list.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.dom/modify-element-classname.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.dom/modify-element-id.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.dom/modify-element-title.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.dom/move-down-with-hidden-elements.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.dom/move-up-with-hidden-elements.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.dom/remove_child_with_selection.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.dom/select-multiple-add.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.dom/select-single-add.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.dom/select-single-remove.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.dom/textarea-dom.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.dom/textarea-edit.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.events/EventsDispatching.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.events/EventsDispatchingInDeeplyNestedShadowTrees.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.events/EventsDispatchingInShadowTrees.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.events/hit-test-lots-of-layers.html"
+    },
+    {
+        "duration": "58.0",
+        "name": "blink_perf.image_decoder/decode-gif.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.image_decoder/decode-jpeg.html"
+    },
+    {
+        "duration": "54.0",
+        "name": "blink_perf.image_decoder/decode-lossless-webp.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.image_decoder/decode-lossy-webp.html"
+    },
+    {
+        "duration": "34.0",
+        "name": "blink_perf.image_decoder/decode-png-palette-opaque.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.image_decoder/decode-png-palette.html"
+    },
+    {
+        "duration": "57.0",
+        "name": "blink_perf.image_decoder/decode-png.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.layout/ArabicLineLayout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.layout/Shapes/MultipleShapes.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/SimpleTextPathLineLayout.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/add-remove-inline-floats.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/attach-inlines-2.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/attach-inlines.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/auto-grid-lots-of-data.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/chapter-reflow-once-random.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.layout/chapter-reflow-once.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/chapter-reflow-thrice.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/chapter-reflow-twice.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/chapter-reflow.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/character_fallback.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.layout/character_fallback_aat.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/fixed-grid-lots-of-data.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/fixed-grid-lots-of-stretched-data.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-column-nowrap.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-column-wrap.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/flexbox-deeply-nested-column-flow.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-lots-of-data.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-row-nowrap.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-row-wrap.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/flexbox-with-stretch-layout.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/floats_100_100.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/floats_100_100_nested.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.layout/floats_10_1000.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.layout/floats_20_100.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.layout/floats_20_100_nested.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/floats_2_100.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/floats_2_100_nested.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.layout/floats_50_100.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/floats_50_100_nested.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/hindi-line-layout.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/large-spanning-grid-item.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-no-colspans.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/latin-complex-text.html"
+    },
+    {
+        "duration": "55.0",
+        "name": "blink_perf.layout/latin-ebook-resize.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.layout/latin-ebook.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.layout/layers_overlap_2d.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/layers_overlap_3d.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/line-layout-line-height.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/line-layout-repeat-append.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.layout/line-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.layout/long-line-nowrap-collapse.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.layout/long-line-nowrap-spans-collapse.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.layout/long-line-nowrap.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/deeply-nested-tables.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/fixed-height-with-spanner-and-nested-tables.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-autofill.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-balanced-orphans-widows.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-balanced.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/tall-content-short-columns-realistic.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/multicol/tall-content-short-columns.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/nested-blocks-with-percent-height-and-max-height.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/nested-grid.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/nested-percent-height-tables.html"
+    },
+    {
+        "duration": "91.0",
+        "name": "blink_perf.layout/subtree-detaching.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.layout/vertical-japanese-kokoro-insert.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.layout/word-break-break-all.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.layout/word-break-break-word.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.layout/word-wrap-break-word.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.owp_storage/blob-perf-files.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.owp_storage/blob-perf-ipc.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.owp_storage/blob-perf-shm.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.owp_storage/blob-perf-tiny.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.owp_storage/idb-load-docs.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.paint/appending-text.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.paint/color-changes.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.paint/complex-content-slow-scroll.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.paint/containment-resize.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.paint/fixed-and-many-layers-scroll.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.paint/large-table-background-change-with-invisible-collapsed-borders.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.paint/large-table-background-change-with-visible-collapsed-borders.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.paint/large-table-background-change-with-zero-width-collapsed-borders.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change-with-backgrounds.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change-with-text.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.paint/large-table-repaint.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.paint/move-text-with-mask.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.paint/paint-offset-changes.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.paint/transform-changes.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/css-parser-yui.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.parser/html-parser-threaded.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.parser/html-parser.html"
+    },
+    {
+        "duration": "71.0",
+        "name": "blink_perf.parser/html5-full-render.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/iframe-append-remove.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/innerHTML-setter-siblings.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/innerHTML-setter.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-all-attribute-complex.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-all-attribute.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-all-class-deep.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-all-class-first.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-all-class-last.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-all-class.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-all-deep.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-all-first.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.parser/query-selector-all-id-deep.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-all-id-first.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.parser/query-selector-all-id-last.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-all-last.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/query-selector-deep.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-first.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-id-deep.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-id-last.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/query-selector-last.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/simple-url.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/textarea-parsing.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.parser/tiny-innerHTML.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.parser/url-parser.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.parser/xml-parser.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-attr-selectors.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-media-query.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-with-distribution.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/style-sheet-insert.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/v0-changing-classname-with-shadow-dom.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.shadow_dom/v0-changing-classname-without-shadow-dom.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.shadow_dom/v0-changing-select-with-shadow-dom.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.shadow_dom/v0-changing-select-without-shadow-dom.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/v0-content-reprojection.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v0-large-distribution-without-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v0-multiple-insertion-points.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/v0-shadow-reprojection.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v0-small-distribution-with-layout.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.shadow_dom/v1-distribution-disconnected-and-reconnected.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-distribution.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-host-child-append.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.shadow_dom/v1-large-deep-distribution.html"
+    },
+    {
+        "duration": "54.0",
+        "name": "blink_perf.shadow_dom/v1-large-deep-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-large-shallow-distribution.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-large-shallow-layout.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-re-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-assigned-nodes.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-flatten.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-re-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-assigned-nodes.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-flatten.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-slot-append.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.shadow_dom/v1-small-deep-distribution.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.shadow_dom/v1-small-deep-layout.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-small-shallow-distribution.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.shadow_dom/v1-small-shallow-layout.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.svg/AzLizardBenjiPark.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.svg/Bamboo.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/Cactus.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/Cowboy.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/Cowboy_transform.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/CrawFishGanson.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/Debian.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/DropsOnABlade.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/FlowerFromMyGarden.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/FoodLeifLodahl.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/France.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/FrancoBolloGnomeEzechi.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/GearFlowers.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/HarveyRayner.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/HereGear.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.svg/MtSaintHelens.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/Samurai.html"
+    },
+    {
+        "duration": "64.0",
+        "name": "blink_perf.svg/SierpinskiCarpet.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/SvgCubics.html"
+    },
+    {
+        "duration": "7.0",
+        "name": "blink_perf.svg/SvgHitTesting.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/SvgNestedUse.html"
+    },
+    {
+        "duration": "5.0",
+        "name": "blink_perf.svg/UnderTheSee.html"
+    },
+    {
+        "duration": "6.0",
+        "name": "blink_perf.svg/WorldIso.html"
+    },
+    {
+        "duration": "8.0",
+        "name": "blink_perf.svg/Worldcup.html"
+    },
+    {
+        "duration": "48.0",
+        "name": "dromaeo/http://dromaeo.com?dom-attr"
+    },
+    {
+        "duration": "36.0",
+        "name": "dromaeo/http://dromaeo.com?dom-modify"
+    },
+    {
+        "duration": "50.0",
+        "name": "dromaeo/http://dromaeo.com?dom-query"
+    },
+    {
+        "duration": "31.0",
+        "name": "dromaeo/http://dromaeo.com?dom-traverse"
+    },
+    {
+        "duration": "19.0",
+        "name": "dummy_benchmark.histogram_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "dummy_benchmark.noisy_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "dummy_benchmark.stable_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "282.0",
+        "name": "jetstream/http://browserbench.org/JetStream/"
+    },
+    {
+        "duration": "59.0",
+        "name": "kraken/http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "loading.mobile/58Pic"
+    },
+    {
+        "duration": "134.0",
+        "name": "loading.mobile/58Pic_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/Amazon"
+    },
+    {
+        "duration": "205.0",
+        "name": "loading.mobile/Amazon_3g"
+    },
+    {
+        "duration": "23.0",
+        "name": "loading.mobile/BOLNoticias"
+    },
+    {
+        "duration": "270.0",
+        "name": "loading.mobile/BOLNoticias_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/Baidu"
+    },
+    {
+        "duration": "161.0",
+        "name": "loading.mobile/Baidu_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/Bradesco"
+    },
+    {
+        "duration": "94.0",
+        "name": "loading.mobile/Bradesco_3g"
+    },
+    {
+        "duration": "19.0",
+        "name": "loading.mobile/Dailymotion"
+    },
+    {
+        "duration": "66.0",
+        "name": "loading.mobile/Dailymotion_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/Dawn"
+    },
+    {
+        "duration": "73.0",
+        "name": "loading.mobile/Dawn_3g"
+    },
+    {
+        "duration": "26.0",
+        "name": "loading.mobile/DevOpera"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/DevOpera_cold"
+    },
+    {
+        "duration": "132.0",
+        "name": "loading.mobile/DevOpera_cold_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/DevOpera_hot"
+    },
+    {
+        "duration": "30.0",
+        "name": "loading.mobile/DevOpera_hot_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/DevOpera_warm"
+    },
+    {
+        "duration": "26.0",
+        "name": "loading.mobile/DevOpera_warm_3g"
+    },
+    {
+        "duration": "21.0",
+        "name": "loading.mobile/Dramaq"
+    },
+    {
+        "duration": "153.0",
+        "name": "loading.mobile/Dramaq_3g"
+    },
+    {
+        "duration": "16.0",
+        "name": "loading.mobile/EnquiryIndianRail"
+    },
+    {
+        "duration": "115.0",
+        "name": "loading.mobile/EnquiryIndianRail_3g"
+    },
+    {
+        "duration": "21.0",
+        "name": "loading.mobile/Facebook"
+    },
+    {
+        "duration": "218.0",
+        "name": "loading.mobile/Facebook_3g"
+    },
+    {
+        "duration": "33.0",
+        "name": "loading.mobile/FlipBoard"
+    },
+    {
+        "duration": "18.0",
+        "name": "loading.mobile/FlipBoard_cold"
+    },
+    {
+        "duration": "353.0",
+        "name": "loading.mobile/FlipBoard_cold_3g"
+    },
+    {
+        "duration": "27.0",
+        "name": "loading.mobile/FlipBoard_hot"
+    },
+    {
+        "duration": "55.0",
+        "name": "loading.mobile/FlipBoard_hot_3g"
+    },
+    {
+        "duration": "23.0",
+        "name": "loading.mobile/FlipBoard_warm"
+    },
+    {
+        "duration": "81.0",
+        "name": "loading.mobile/FlipBoard_warm_3g"
+    },
+    {
+        "duration": "34.0",
+        "name": "loading.mobile/FlipKart"
+    },
+    {
+        "duration": "21.0",
+        "name": "loading.mobile/FlipKart_cold"
+    },
+    {
+        "duration": "63.0",
+        "name": "loading.mobile/FlipKart_cold_3g"
+    },
+    {
+        "duration": "32.0",
+        "name": "loading.mobile/FlipKart_hot"
+    },
+    {
+        "duration": "29.0",
+        "name": "loading.mobile/FlipKart_hot_3g"
+    },
+    {
+        "duration": "25.0",
+        "name": "loading.mobile/FlipKart_warm"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/FlipKart_warm_3g"
+    },
+    {
+        "duration": "18.0",
+        "name": "loading.mobile/FranceTVInfo"
+    },
+    {
+        "duration": "213.0",
+        "name": "loading.mobile/FranceTVInfo_3g"
+    },
+    {
+        "duration": "143.0",
+        "name": "loading.mobile/G1_3g"
+    },
+    {
+        "duration": "22.0",
+        "name": "loading.mobile/GSShop"
+    },
+    {
+        "duration": "147.0",
+        "name": "loading.mobile/GSShop_3g"
+    },
+    {
+        "duration": "15.0",
+        "name": "loading.mobile/GoogleBrazil"
+    },
+    {
+        "duration": "207.0",
+        "name": "loading.mobile/GoogleBrazil_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/GoogleIndia"
+    },
+    {
+        "duration": "88.0",
+        "name": "loading.mobile/GoogleIndia_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/GoogleIndonesia"
+    },
+    {
+        "duration": "191.0",
+        "name": "loading.mobile/GoogleIndonesia_3g"
+    },
+    {
+        "duration": "25.0",
+        "name": "loading.mobile/GoogleRedirectToGoogleJapan"
+    },
+    {
+        "duration": "268.0",
+        "name": "loading.mobile/GoogleRedirectToGoogleJapan_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/Hongkiat"
+    },
+    {
+        "duration": "232.0",
+        "name": "loading.mobile/Hongkiat_3g"
+    },
+    {
+        "duration": "22.0",
+        "name": "loading.mobile/KapanLagi"
+    },
+    {
+        "duration": "277.0",
+        "name": "loading.mobile/KapanLagi_3g"
+    },
+    {
+        "duration": "26.0",
+        "name": "loading.mobile/Kaskus"
+    },
+    {
+        "duration": "104.0",
+        "name": "loading.mobile/Kaskus_3g"
+    },
+    {
+        "duration": "19.0",
+        "name": "loading.mobile/LocalMoxie"
+    },
+    {
+        "duration": "69.0",
+        "name": "loading.mobile/LocalMoxie_3g"
+    },
+    {
+        "duration": "16.0",
+        "name": "loading.mobile/Locanto"
+    },
+    {
+        "duration": "78.0",
+        "name": "loading.mobile/Locanto_3g"
+    },
+    {
+        "duration": "18.0",
+        "name": "loading.mobile/OLX"
+    },
+    {
+        "duration": "228.0",
+        "name": "loading.mobile/OLX_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/QQNews"
+    },
+    {
+        "duration": "223.0",
+        "name": "loading.mobile/QQNews_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/SlideShare"
+    },
+    {
+        "duration": "193.0",
+        "name": "loading.mobile/SlideShare_3g"
+    },
+    {
+        "duration": "21.0",
+        "name": "loading.mobile/Suumo"
+    },
+    {
+        "duration": "16.0",
+        "name": "loading.mobile/Suumo_cold"
+    },
+    {
+        "duration": "32.0",
+        "name": "loading.mobile/Suumo_cold_3g"
+    },
+    {
+        "duration": "21.0",
+        "name": "loading.mobile/Suumo_hot"
+    },
+    {
+        "duration": "28.0",
+        "name": "loading.mobile/Suumo_hot_3g"
+    },
+    {
+        "duration": "18.0",
+        "name": "loading.mobile/Suumo_warm"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/Suumo_warm_3g"
+    },
+    {
+        "duration": "18.0",
+        "name": "loading.mobile/Thairath"
+    },
+    {
+        "duration": "105.0",
+        "name": "loading.mobile/Thairath_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/TheStar"
+    },
+    {
+        "duration": "86.0",
+        "name": "loading.mobile/TheStar_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/TribunNews"
+    },
+    {
+        "duration": "106.0",
+        "name": "loading.mobile/TribunNews_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/Twitter"
+    },
+    {
+        "duration": "122.0",
+        "name": "loading.mobile/Twitter_3g"
+    },
+    {
+        "duration": "27.0",
+        "name": "loading.mobile/VoiceMemos"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/VoiceMemos_cold"
+    },
+    {
+        "duration": "152.0",
+        "name": "loading.mobile/VoiceMemos_cold_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/VoiceMemos_hot"
+    },
+    {
+        "duration": "29.0",
+        "name": "loading.mobile/VoiceMemos_hot_3g"
+    },
+    {
+        "duration": "20.0",
+        "name": "loading.mobile/VoiceMemos_warm"
+    },
+    {
+        "duration": "26.0",
+        "name": "loading.mobile/VoiceMemos_warm_3g"
+    },
+    {
+        "duration": "15.0",
+        "name": "loading.mobile/Wikipedia"
+    },
+    {
+        "duration": "165.0",
+        "name": "loading.mobile/Wikipedia_3g"
+    },
+    {
+        "duration": "24.0",
+        "name": "loading.mobile/YahooNews"
+    },
+    {
+        "duration": "72.0",
+        "name": "loading.mobile/YahooNews_3g"
+    },
+    {
+        "duration": "17.0",
+        "name": "loading.mobile/Youtube"
+    },
+    {
+        "duration": "85.0",
+        "name": "loading.mobile/Youtube_3g"
+    },
+    {
+        "duration": "21.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4"
+    },
+    {
+        "duration": "23.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4,h264_video.mp4"
+    },
+    {
+        "duration": "23.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4,h264_video.mp4&waitForPageLoaded=true"
+    },
+    {
+        "duration": "22.0",
+        "name": "media.mobile/mse.html?media=h264_video.mp4"
+    },
+    {
+        "duration": "34.0",
+        "name": "media.mobile/video.html?src=crowd.ogg&type=audio"
+    },
+    {
+        "duration": "32.0",
+        "name": "media.mobile/video.html?src=crowd1080_vp9.webm"
+    },
+    {
+        "duration": "19.0",
+        "name": "media.mobile/video.html?src=crowd1080_vp9.webm&seek"
+    },
+    {
+        "duration": "31.0",
+        "name": "media.mobile/video.html?src=crowd720_vp9.webm"
+    },
+    {
+        "duration": "34.0",
+        "name": "media.mobile/video.html?src=tulip2.m4a&type=audio"
+    },
+    {
+        "duration": "34.0",
+        "name": "media.mobile/video.html?src=tulip2.mp3&type=audio"
+    },
+    {
+        "duration": "14.0",
+        "name": "media.mobile/video.html?src=tulip2.mp3&type=audio&seek"
+    },
+    {
+        "duration": "43.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4"
+    },
+    {
+        "duration": "43.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4&busyjs"
+    },
+    {
+        "duration": "17.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4&seek"
+    },
+    {
+        "duration": "35.0",
+        "name": "media.mobile/video.html?src=tulip2.ogg&type=audio"
+    },
+    {
+        "duration": "14.0",
+        "name": "media.mobile/video.html?src=tulip2.ogg&type=audio&seek"
+    },
+    {
+        "duration": "44.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm"
+    },
+    {
+        "duration": "28.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm&background"
+    },
+    {
+        "duration": "19.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm&seek"
+    },
+    {
+        "duration": "67.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm_Regular-3G"
+    },
+    {
+        "duration": "35.0",
+        "name": "media.mobile/video.html?src=tulip2.wav&type=audio"
+    },
+    {
+        "duration": "15.0",
+        "name": "media.mobile/video.html?src=tulip2.wav&type=audio&seek"
+    },
+    {
+        "duration": "314.0",
+        "name": "memory.long_running_idle_gmail_background_tbmv2/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "267.0",
+        "name": "memory.long_running_idle_gmail_tbmv2/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "20.0",
+        "name": "memory.top_10_mobile/after_http_en_m_wikipedia_org_wiki_Science"
+    },
+    {
+        "duration": "19.0",
+        "name": "memory.top_10_mobile/after_http_m_intl_taobao_com_group_purchase_html"
+    },
+    {
+        "duration": "20.0",
+        "name": "memory.top_10_mobile/after_http_m_youtube_com_results_q_science"
+    },
+    {
+        "duration": "19.0",
+        "name": "memory.top_10_mobile/after_http_search_yahoo_com_search__ylt_p_google"
+    },
+    {
+        "duration": "20.0",
+        "name": "memory.top_10_mobile/after_http_www_amazon_com_gp_aw_s_k_nexus"
+    },
+    {
+        "duration": "19.0",
+        "name": "memory.top_10_mobile/after_http_www_baidu_com_s_word_google"
+    },
+    {
+        "duration": "19.0",
+        "name": "memory.top_10_mobile/after_http_yandex_ru_touchsearch_text_science"
+    },
+    {
+        "duration": "20.0",
+        "name": "memory.top_10_mobile/after_https_m_facebook_com_rihanna"
+    },
+    {
+        "duration": "19.0",
+        "name": "memory.top_10_mobile/after_https_mobile_twitter_com_justinbieber_skip_interstitial_true"
+    },
+    {
+        "duration": "20.0",
+        "name": "memory.top_10_mobile/after_https_www_google_co_uk_hl_en_q_science"
+    },
+    {
+        "duration": "22.0",
+        "name": "memory.top_10_mobile/http_en_m_wikipedia_org_wiki_Science"
+    },
+    {
+        "duration": "21.0",
+        "name": "memory.top_10_mobile/http_m_intl_taobao_com_group_purchase_html"
+    },
+    {
+        "duration": "22.0",
+        "name": "memory.top_10_mobile/http_m_youtube_com_results_q_science"
+    },
+    {
+        "duration": "21.0",
+        "name": "memory.top_10_mobile/http_search_yahoo_com_search__ylt_p_google"
+    },
+    {
+        "duration": "21.0",
+        "name": "memory.top_10_mobile/http_www_amazon_com_gp_aw_s_k_nexus"
+    },
+    {
+        "duration": "22.0",
+        "name": "memory.top_10_mobile/http_www_baidu_com_s_word_google"
+    },
+    {
+        "duration": "22.0",
+        "name": "memory.top_10_mobile/http_yandex_ru_touchsearch_text_science"
+    },
+    {
+        "duration": "21.0",
+        "name": "memory.top_10_mobile/https_m_facebook_com_rihanna"
+    },
+    {
+        "duration": "22.0",
+        "name": "memory.top_10_mobile/https_mobile_twitter_com_justinbieber_skip_interstitial_true"
+    },
+    {
+        "duration": "23.0",
+        "name": "memory.top_10_mobile/https_www_google_co_uk_hl_en_q_science"
+    },
+    {
+        "duration": "61.0",
+        "name": "octane/http://chromium.github.io/octane/index.html?auto=1"
+    },
+    {
+        "duration": "21.0",
+        "name": "oortonline_tbmv2/http://oortonline.gl/#run"
+    },
+    {
+        "duration": "26.0",
+        "name": "power.idle_platform/IdleStory_10s"
+    },
+    {
+        "duration": "136.0",
+        "name": "power.idle_platform/IdleStory_120s"
+    },
+    {
+        "duration": "75.0",
+        "name": "power.idle_platform/IdleStory_60s"
+    },
+    {
+        "duration": "63.0",
+        "name": "power.typical_10_mobile/http://de.m.wikipedia.org/wiki/K%C3%B6lner_Dom"
+    },
+    {
+        "duration": "65.0",
+        "name": "power.typical_10_mobile/http://m.chiebukuro.yahoo.co.jp/detail/q10136829180"
+    },
+    {
+        "duration": "57.0",
+        "name": "power.typical_10_mobile/http://m.ebay.com/itm/351157205404"
+    },
+    {
+        "duration": "68.0",
+        "name": "power.typical_10_mobile/http://m.facebook.com/barackobama"
+    },
+    {
+        "duration": "63.0",
+        "name": "power.typical_10_mobile/http://m.huffpost.com/us/entry/6004486"
+    },
+    {
+        "duration": "62.0",
+        "name": "power.typical_10_mobile/http://m.ynet.co.il"
+    },
+    {
+        "duration": "63.0",
+        "name": "power.typical_10_mobile/http://siriuslymeg.tumblr.com/"
+    },
+    {
+        "duration": "58.0",
+        "name": "power.typical_10_mobile/http://wapbaike.baidu.com/"
+    },
+    {
+        "duration": "59.0",
+        "name": "power.typical_10_mobile/http://www.cnn.com/2014/03/31/showbiz/tv/himym-finale/index.html"
+    },
+    {
+        "duration": "64.0",
+        "name": "power.typical_10_mobile/http://www.rg.ru/2014/10/21/cska-site.html"
+    },
+    {
+        "duration": "63.0",
+        "name": "power.typical_10_mobile/https://en.wikipedia.org/wiki/File:Rotating_earth_(large).gif"
+    },
+    {
+        "duration": "16.0",
+        "name": "rasterize_and_record_micro.partial_invalidation/800_relpos_divs.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/amazon.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/blogger.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/booking.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/cnn.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/ebay.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/espn.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/facebook.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/gmail.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/google.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googlecalendar.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googledocs.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleimagesearch.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleplus.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/linkedin.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/pinterest.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/techcrunch.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/twitter.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/weather.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/wordpress.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahooanswers.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html"
+    },
+    {
+        "duration": "130.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html"
+    },
+    {
+        "duration": "87.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoosports.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/youtube.html"
+    },
+    {
+        "duration": "48.0",
+        "name": "rendering.mobile/accu_weather_2018"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/accu_weather_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/accu_weather_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/amazon_2018"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/amazon_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/amazon_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/amazon_mobile_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/amazon_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/amazon_pinch"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/amazon_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/analog_clock_svg"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/androidpolice_mobile"
+    },
+    {
+        "duration": "59.0",
+        "name": "rendering.mobile/androidpolice_mobile_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/androidpolice_mobile_sync_scroll"
+    },
+    {
+        "duration": "60.0",
+        "name": "rendering.mobile/androidpolice_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/animometer_webgl"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/aquarium"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/background_color_animation"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/background_color_animation_with_gradient"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/baidu_mobile"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/baidu_mobile_2018"
+    },
+    {
+        "duration": "18.0",
+        "name": "rendering.mobile/baidu_mobile_sync_scroll"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/baidu_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/balls_css_key_frame_animations"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/balls_css_transition_2_properties"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/balls_css_transition_40_properties"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/balls_css_transition_all_properties"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/balls_javascript_canvas"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/balls_javascript_css"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/balls_svg_animations"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/basic_stream"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/bing_mobile"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/bing_mobile_2018"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/bing_mobile_sync_scroll"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/bing_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "6.0",
+        "name": "rendering.mobile/blob"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/blogspot"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/blogspot_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/blogspot_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/blogspot_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/blogspot_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/blogspot_mobile"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/blogspot_mobile_2018"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/blogspot_mobile_sync_scroll"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/blogspot_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/boingboing_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/boingboing_mobile_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/booking.com"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/booking.com_2018"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/booking.com_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/booking.com_desktop_gpu_raster"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/booking.com_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/booking.com_mobile"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/booking.com_mobile_2018"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/booking.com_mobile_sync_scroll"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/booking.com_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/booking_pinch"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/booking_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/bouncing_balls_15"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/bouncing_balls_shadow"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/bouncing_clipped_rectangles"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/bouncing_gradient_circles"
+    },
+    {
+        "duration": "18.0",
+        "name": "rendering.mobile/bouncing_png_images"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/bouncing_svg_images"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_05000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_10000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_15000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_20000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_30000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/canvas_40000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/canvas_50000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/canvas_60000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/canvas_75000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/canvas_90000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/canvas_animation_no_clear"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/canvas_arcs"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/canvas_font_cycler"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/canvas_lines"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/canvas_to_blob"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile_sync_scroll"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/card_expansion"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/card_expansion_animated"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/card_expansion_images_text"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/card_flying"
+    },
+    {
+        "duration": "15.0",
+        "name": "rendering.mobile/cats_unscaled"
+    },
+    {
+        "duration": "14.0",
+        "name": "rendering.mobile/cats_viewport_width"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/cc_poster_circle"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/cc_scroll_200_layer_grid"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/cc_scroll_text_only"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/chip_tune"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/cnn_2018"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/cnn_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "47.0",
+        "name": "rendering.mobile/cnn_article_mobile"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/cnn_article_mobile_2018"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/cnn_article_mobile_sync_scroll"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/cnn_article_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/cnn_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/cnn_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/cnn_mobile_2018"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/cnn_mobile_sync_scroll"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/cnn_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/cnn_pathological"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/cnn_pinch"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/cnn_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/compositor_heavy_animation"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/coordinated_animation"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/crafty_mind"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_animations_many_keyframes"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_animations_simultaneous_inline_style"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_animations_simultaneous_new_element"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_animations_simultaneous_style_element"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_animations_simultaneous_updating_class"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/css_animations_staggered_infinite_iterations"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_animations_staggered_inline_style"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/css_animations_staggered_new_element"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_animations_staggered_style_element"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_animations_staggered_updating_class"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_animations_triggered_inline_style"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/css_animations_triggered_new_element"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_animations_triggered_style_element"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_animations_triggered_updating_class"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_transitions_inline_style"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_new_element"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_staggered_inline_style"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_staggered_new_element"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_staggered_style_element"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_staggered_updating_class"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_transitions_style_element"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_transitions_triggered_inline_style"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_transitions_triggered_new_element"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_transitions_triggered_style_element"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_transitions_triggered_updating_class"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_transitions_updating_class"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_value_type_color"
+    },
+    {
+        "duration": "91.0",
+        "name": "rendering.mobile/css_value_type_filter"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_value_type_length"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_value_type_length_complex"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_value_type_length_simple"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_value_type_path"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/css_value_type_shadow"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/css_value_type_transform_complex"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/css_value_type_transform_simple"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/cuteoverload_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/deviantart_mobile"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/deviantart_mobile_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/deviantart_mobile_sync_scroll"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/deviantart_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/digg_mobile_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/digg_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/dynamic_cube_map"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/earth"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/ebay"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/ebay_2018"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/ebay_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/ebay_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/ebay_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/ebay_mobile"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/ebay_mobile_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/ebay_mobile_sync_scroll"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/ebay_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/ebay_pinch"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/ebay_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/ebay_scroll"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/ebay_scroll_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/effect_games"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/espn"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/espn_2018"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/espn_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "15.0",
+        "name": "rendering.mobile/espn_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/espn_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/espn_mobile_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/espn_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/espn_pathological"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/espn_pinch"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/espn_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/extra_large_texture_uploads"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/facebook"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/facebook_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/facebook_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/facebook_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/facebook_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/facebook_mobile"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/facebook_mobile_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/facebook_mobile_sync_scroll"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/facebook_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/facebook_pinch"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/facebook_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/fill_shapes"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/filter_terrain_svg"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/flickr_scroll"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/flickr_scroll_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/font_wipe"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/forecast.io_mobile_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/forecast.io_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/geo_apis"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/gmail"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/gmail_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/gmail_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/gmail_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/gmail_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/gmail_pinch"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/gmail_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/google_calendar"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/google_calendar_2018"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/google_calendar_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/google_calendar_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/google_calendar_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/google_calendar_pinch"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/google_calendar_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/google_docs"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/google_docs_2018"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/google_docs_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/google_docs_desktop_gpu_raster"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/google_docs_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/google_image_pinch"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/google_image_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/google_image_search"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/google_image_search_2018"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/google_image_search_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_image_search_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/google_image_search_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/google_image_search_mobile_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/google_image_search_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/google_news_ios"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/google_news_mobile"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/google_news_mobile_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/google_news_mobile_sync_scroll"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/google_news_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/google_plus"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/google_plus_2018"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/google_plus_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/google_plus_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_plus_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/google_plus_mobile"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/google_plus_mobile_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/google_plus_mobile_sync_scroll"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_plus_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/google_search_pinch"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/google_search_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/google_web_search"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/google_web_search_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/google_web_search_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/google_web_search_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/google_web_search_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/google_web_search_mobile"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/google_web_search_mobile_2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/google_web_search_mobile_sync_scroll"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/google_web_search_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/gsp.ro_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/gsp.ro_mobile_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/gsp.ro_mobile_sync_scroll"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/gsp.ro_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/guardian_pathological"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/guimark_vector_chart"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/gws_boogie_expansion"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/gws_google_expansion"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/hakim"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/horizontal_vertical_expansion"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/idle_power_animated_gif"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/idle_power_blank"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/idle_power_css_animation"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/idle_power_request_animation_frame"
+    },
+    {
+        "duration": "113.0",
+        "name": "rendering.mobile/idle_power_set_timeout_long"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/idle_power_set_timetout"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/ie_chalkboard"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/ie_pirate_mark"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/infinite_scrolling"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/jarro_doverson"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/js_full_screen_invalidation"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/js_poster_circle"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/js_scroll_200_layer_grid"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/js_scroll_text_only"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/kevs_3d"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/keyframed_animations"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/large_texture_uploads"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/latimes_pathological"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/linkedin"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/linkedin_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/linkedin_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/linkedin_desktop_gpu_raster"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/linkedin_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/linkedin_mobile"
+    },
+    {
+        "duration": "55.0",
+        "name": "rendering.mobile/linkedin_mobile_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/linkedin_mobile_sync_scroll"
+    },
+    {
+        "duration": "49.0",
+        "name": "rendering.mobile/linkedin_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/linkedin_pathological"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/linkedin_pinch"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/linkedin_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/list_animation_simple"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/list_recycle_transform"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/man_in_blue"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/many_images"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/many_planets_deep"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/maps_perf_test"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/mask_transition_animation"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/masonry"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/medium_texture_uploads"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/megi_dish"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/microsoft_asteroid_belt"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/microsoft_fireflies"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/microsoft_fish_ie_tank"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/microsoft_snow"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/microsoft_speed_reading"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/microsoft_tweet_map"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/microsoft_video_city"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/microsoft_worker_fountains"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/mix_10k"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_difference"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_hue"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_propagating_isolation"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_screen"
+    },
+    {
+        "duration": "18.0",
+        "name": "rendering.mobile/mlb_mobile"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/mlb_mobile_2018"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/mlb_mobile_sync_scroll"
+    },
+    {
+        "duration": "46.0",
+        "name": "rendering.mobile/mlb_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/mobile_news_sandbox"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/motion_mark_canvas_fill_shapes"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/motion_mark_canvas_stroke_shapes"
+    },
+    {
+        "duration": "74.0",
+        "name": "rendering.mobile/motion_mark_focus"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/new_tilings"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/no_op_raf"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/no_op_scroll"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/no_op_settimeout"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/no_op_touch_handler"
+    },
+    {
+        "duration": "7.0",
+        "name": "rendering.mobile/nvidia_vertex_buffer_object"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/nyc_gov_scroll"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/nyc_gov_scroll_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/nytimes_mobile"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/nytimes_mobile_2018"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/nytimes_scroll"
+    },
+    {
+        "duration": "47.0",
+        "name": "rendering.mobile/nytimes_scroll_2018"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/overlay_background_color_css_transitions_page"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/parallax_effect"
+    },
+    {
+        "duration": "6.0",
+        "name": "rendering.mobile/particles"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/pbs_pathological"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/physical_simulation"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/pinterest"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/pinterest_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/pinterest_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/pinterest_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/pinterest_mobile"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/pinterest_mobile_2018"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/pinterest_mobile_sync_scroll"
+    },
+    {
+        "duration": "15.0",
+        "name": "rendering.mobile/pinterest_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/put_get_image_data"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/raf"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/raf_animation"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/raf_canvas"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/raf_touch_animation"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/recode_pathological"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/reddit_mobile"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/reddit_mobile_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/runway"
+    },
+    {
+        "duration": "6.0",
+        "name": "rendering.mobile/san_angeles"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/second_batch_js_heavy"
+    },
+    {
+        "duration": "15.0",
+        "name": "rendering.mobile/second_batch_js_light"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/second_batch_js_medium"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/sfgate_mobile"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/sfgate_mobile_2018"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/sfgate_mobile_sync_scroll"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/sfgate_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/silk_finance"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/simple_text_page"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/simple_touch_drag"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/slashdot_mobile"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/slashdot_mobile_2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/slide_drawer"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/small_texture_uploads"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/smash_cat"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/spielzeugz"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/sticky_using_webkit"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/stress_hidey_bars"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/stroke_shapes"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/svg_icon_raster"
+    },
+    {
+        "duration": "15.0",
+        "name": "rendering.mobile/swipe_action"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/swipe_to_dismiss"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/sync_scroll_offset"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/techcrunch"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/techcrunch_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/techcrunch_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/techcrunch_desktop_gpu_raster"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/techcrunch_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/techcrunch_mobile"
+    },
+    {
+        "duration": "46.0",
+        "name": "rendering.mobile/techcrunch_mobile_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/techcrunch_mobile_sync_scroll"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/techcrunch_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_05000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_10000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_15000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/text_20000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/text_30000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/text_40000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/text_50000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/text_60000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/text_75000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_90000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_05000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_10000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_15000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_20000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_30000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_40000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_50000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_60000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_75000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/text_constant_full_page_raster_90000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_05000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_10000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_15000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/text_hover_20000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "rendering.mobile/text_hover_30000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/text_hover_40000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "18.0",
+        "name": "rendering.mobile/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/text_hover_50000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/text_hover_60000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/text_hover_75000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/text_hover_90000_pixels_per_second_desktop_gpu_raster"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/theverge_article_mobile"
+    },
+    {
+        "duration": "47.0",
+        "name": "rendering.mobile/theverge_article_mobile_2018"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/theverge_article_mobile_sync_scroll"
+    },
+    {
+        "duration": "47.0",
+        "name": "rendering.mobile/theverge_article_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/theverge_mobile"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/theverge_mobile_2018"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/theverge_mobile_sync_scroll"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/theverge_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/toggle_drawer"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/touch_handler_scrolling"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/transform_transitions"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/transform_transitions_js_block"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/twitch_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/twitch_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/twitch_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/twitter"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/twitter_2018"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/twitter_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/twitter_desktop_gpu_raster"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/twitter_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/twitter_mobile_2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/twitter_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/twitter_pinch"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/twitter_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/update_history_state"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/usatoday_mobile"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/usatoday_mobile_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/usatoday_mobile_sync_scroll"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/usatoday_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/vertical_expansion"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/weather.com"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/weather.com_desktop_gpu_raster"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/weather_pinch"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/weather_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animation_value_type_color"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animation_value_type_length_3d"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/web_animation_value_type_length_complex"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animation_value_type_length_simple"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/web_animation_value_type_path"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/web_animation_value_type_shadow"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animation_value_type_transform_complex"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animation_value_type_transform_simple"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/web_animations_many_keyframes"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animations_set_current_time"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/web_animations_simultaneous"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/web_animations_staggered_chaining"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/web_animations_staggered_infinite_iterations"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/web_animations_staggered_triggering_page"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/wikipedia"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/wikipedia_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/wikipedia_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/wikipedia_delayed_scroll_start"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/wikipedia_delayed_scroll_start_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/wikipedia_delayed_scroll_start_sync_scroll"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/wikipedia_delayed_scroll_start_sync_scroll_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/wikipedia_desktop_gpu_raster"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/wikipedia_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/wikipedia_mobile"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/wikipedia_mobile_2018"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/wikipedia_mobile_sync_scroll"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/wikipedia_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/wordpress"
+    },
+    {
+        "duration": "43.0",
+        "name": "rendering.mobile/wordpress_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/wordpress_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/wordpress_desktop_gpu_raster"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/wordpress_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/wordpress_mobile"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/wordpress_mobile_2018"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/wordpress_mobile_sync_scroll"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/wordpress_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/worldjournal_mobile"
+    },
+    {
+        "duration": "45.0",
+        "name": "rendering.mobile/worldjournal_mobile_2018"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/worldjournal_mobile_sync_scroll"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/worldjournal_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/wow_wiki_pathological"
+    },
+    {
+        "duration": "48.0",
+        "name": "rendering.mobile/wowwiki_mobile"
+    },
+    {
+        "duration": "71.0",
+        "name": "rendering.mobile/wowwiki_mobile_2018"
+    },
+    {
+        "duration": "46.0",
+        "name": "rendering.mobile/wowwiki_mobile_sync_scroll"
+    },
+    {
+        "duration": "61.0",
+        "name": "rendering.mobile/wowwiki_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/wsj_mobile"
+    },
+    {
+        "duration": "55.0",
+        "name": "rendering.mobile/wsj_mobile_2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/wsj_mobile_sync_scroll"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/wsj_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/yahoo_answers"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/yahoo_answers_2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/yahoo_answers_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/yahoo_answers_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/yahoo_answers_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/yahoo_answers_mobile"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/yahoo_answers_mobile_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/yahoo_answers_mobile_sync_scroll"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/yahoo_answers_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/yahoo_games"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/yahoo_games_desktop_gpu_raster"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/yahoo_games_pinch"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/yahoo_games_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/yahoo_news"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/yahoo_news_2018"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/yahoo_news_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/yahoo_news_desktop_gpu_raster"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/yahoo_news_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/yahoo_news_mobile"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/yahoo_news_mobile_2018"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/yahoo_news_mobile_sync_scroll"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/yahoo_news_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/yahoo_news_pinch"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/yahoo_news_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/yahoo_sports"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/yahoo_sports_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/yahoo_sports_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/yahoo_sports_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/yahoo_sports_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/yahoo_sports_pathological"
+    },
+    {
+        "duration": "56.0",
+        "name": "rendering.mobile/yahoo_sports_pinch"
+    },
+    {
+        "duration": "52.0",
+        "name": "rendering.mobile/yahoo_sports_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/youtube"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/youtube_2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/youtube_2018_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/youtube_desktop_gpu_raster"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/youtube_desktop_gpu_raster_2018"
+    },
+    {
+        "duration": "18.0",
+        "name": "rendering.mobile/youtube_mobile"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/youtube_mobile_2018"
+    },
+    {
+        "duration": "16.0",
+        "name": "rendering.mobile/youtube_mobile_sync_scroll"
+    },
+    {
+        "duration": "17.0",
+        "name": "rendering.mobile/youtube_mobile_sync_scroll_2018"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/youtube_pinch"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/youtube_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/yuv_decoding"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/yuv_decoding_gpu_rasterization_and_decoding"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/zdnet_pathological"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/zoom_in_animation"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/raf"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/raf_animation"
+    },
+    {
+        "duration": "18.0",
+        "name": "scheduler.tough_scheduling_cases/raf_canvas"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/raf_touch_animation"
+    },
+    {
+        "duration": "12.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js_heavy"
+    },
+    {
+        "duration": "12.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js_light"
+    },
+    {
+        "duration": "12.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js_medium"
+    },
+    {
+        "duration": "24.0",
+        "name": "scheduler.tough_scheduling_cases/simple_text_page"
+    },
+    {
+        "duration": "14.0",
+        "name": "scheduler.tough_scheduling_cases/simple_touch_drag"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/sync_scroll_offset"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/touch_handler_scrolling"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.polymer/core_scroll_header_panel"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_button"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_calculator"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_checkbox"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_fab"
+    },
+    {
+        "duration": "43.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_icon_button"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_shadow"
+    },
+    {
+        "duration": "56.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_tabs"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.polymer/paper_toggle_button"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/blogspot"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/booking.com"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/ebay"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/espn"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/facebook"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/gmail"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_calendar"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_docs"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_image_search"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_plus"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_web_search"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/linkedin"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/techcrunch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/twitter"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/weather.com"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/wikipedia"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/wordpress"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_answers"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_games"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_news"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_sports"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/youtube"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/Analog_Clock_SVG"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/Filter_Terrain_SVG"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/IE_PirateMark"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/MotionMark_Focus"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/analog_clock_svg"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/filter_terrain_svg"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/ie_pirate_mark"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/motion_mark_focus"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/GUIMark_Vector_Chart_Test"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/IE_Chalkboard"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Fill_Shapes"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Stroke_Shapes"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/guimark_vector_chart"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/ie_chalkboard"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/motion_mark_canvas_fill_shapes"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/motion_mark_canvas_stroke_shapes"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Blogger"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/ESPN"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Facebook"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/LinkedIn"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Twitter"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Weather.com"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/amazon_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/blogspot_pinch"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/booking_pinch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/cnn_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/ebay_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/espn_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/facebook_pinch"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/gmail_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/google_calendar_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/google_image_pinch"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/google_search_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://booking.com"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://games.yahoo.com"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://news.yahoo.com"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://sports.yahoo.com/"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.amazon.com"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.cnn.com"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.ebay.com"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.youtube.com"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/#hl=en&q=barack+obama"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/calendar/"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/search?q=cats&tbm=isch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/linkedin_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/twitter_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/weather_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/yahoo_games_pinch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/yahoo_news_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/yahoo_sports_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/youtube_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases/yuv_decoding"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.image_decoding_cases/yuv_decoding"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_mobile_sites_smooth/androidpolice"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.key_mobile_sites_smooth/baidu"
+    },
+    {
+        "duration": "12.0",
+        "name": "smoothness.key_mobile_sites_smooth/bing"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_mobile_sites_smooth/blogspot"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.key_mobile_sites_smooth/booking.com"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_mobile_sites_smooth/capitolvolkswagen"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_mobile_sites_smooth/cnn"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.key_mobile_sites_smooth/cnn_article"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/deviantart"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_mobile_sites_smooth/ebay"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_mobile_sites_smooth/facebook"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_news"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_plus"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_web_search"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_mobile_sites_smooth/gsp.ro"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_mobile_sites_smooth/linkedin"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.key_mobile_sites_smooth/mlb"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_mobile_sites_smooth/pinterest"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/sfgate"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.key_mobile_sites_smooth/techcrunch"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_mobile_sites_smooth/theverge"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_mobile_sites_smooth/theverge_article"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_mobile_sites_smooth/usatoday"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/wikipedia"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/wikipedia_delayed_scroll_start"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/wordpress"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_mobile_sites_smooth/worldjournal"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.key_mobile_sites_smooth/wowwiki"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_mobile_sites_smooth/wsj"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_mobile_sites_smooth/yahoo_answers"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_mobile_sites_smooth/yahoo_news"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.key_mobile_sites_smooth/youtube"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.key_silk_cases/basic_stream"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_silk_cases/card_expansion"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/card_expansion_animated"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/card_expansion_images_text"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_silk_cases/card_flying"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/coordinated_animation"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_silk_cases/font_wipe"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_silk_cases/google_news_ios"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/gws_boogie_expansion"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/gws_google_expansion"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/horizontal_vertical_expansion"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/infinite_scrolling"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_silk_cases/list_animation_simple"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.key_silk_cases/list_recycle_transform"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/mask_transition_animation"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/masonry"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_silk_cases/mobile_news_sandbox"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/parallax_effect"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.key_silk_cases/physical_simulation"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/silk_finance"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_silk_cases/sticky_using_webkit"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_silk_cases/stress_hidey_bars"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_silk_cases/svg_icon_raster"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.key_silk_cases/swipe_action"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_silk_cases/swipe_to_dismiss"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.key_silk_cases/toggle_drawer"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/update_history_state"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.key_silk_cases/vertical_expansion"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.key_silk_cases/zoom_in_animation"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.maps/maps_perf_test"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.pathological_mobile_sites/cnn_pathological"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.pathological_mobile_sites/espn_pathological"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.pathological_mobile_sites/guardian_pathological"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.pathological_mobile_sites/http://edition.cnn.com"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.pathological_mobile_sites/http://m.espn.go.com/nhl/rankings"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.pathological_mobile_sites/http://recode.net"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.pathological_mobile_sites/http://sports.yahoo.com/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.latimes.com"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.pbs.org/newshour/bb/much-really-cost-live-city-like-seattle/#the-rundown"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.theguardian.com/politics/2015/mar/09/ed-balls-tory-spending-plans-nhs-charging"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.zdnet.com"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.pathological_mobile_sites/https://www.linkedin.com/in/linustorvalds"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.pathological_mobile_sites/latimes_pathological"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.pathological_mobile_sites/linkedin_pathological"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.pathological_mobile_sites/pbs_pathological"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.pathological_mobile_sites/recode_pathological"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.pathological_mobile_sites/wow_wiki_pathological"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.pathological_mobile_sites/yahoo_sports_pathological"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.pathological_mobile_sites/zdnet_pathological"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.simple_mobile_sites/ebay_scroll"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.simple_mobile_sites/flickr_scroll"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.simple_mobile_sites/http://m.nytimes.com/"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.simple_mobile_sites/http://www.ebay.co.uk/"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.simple_mobile_sites/http://www.nyc.gov"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.simple_mobile_sites/https://www.flickr.com/"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.simple_mobile_sites/nyc_gov_scroll"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.simple_mobile_sites/nytimes_scroll"
+    },
+    {
+        "duration": "12.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/amazon"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/androidpolice"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/baidu"
+    },
+    {
+        "duration": "12.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/bing"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/blogspot"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/booking.com"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/capitolvolkswagen"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cnn"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cnn_article"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/deviantart"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/ebay"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/espn"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/facebook"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/forecast.io"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_news"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_plus"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_web_search"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/gsp.ro"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/linkedin"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/mlb"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/pinterest"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/sfgate"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/techcrunch"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/theverge"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/theverge_article"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/twitter"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/usatoday"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wikipedia"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wikipedia_delayed_scroll_start"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wordpress"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/worldjournal"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wowwiki"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wsj"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/yahoo_answers"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/yahoo_news"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/youtube"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.top_25_smooth/blogspot"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.top_25_smooth/booking.com"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.top_25_smooth/ebay"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.top_25_smooth/espn"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.top_25_smooth/facebook"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.top_25_smooth/gmail"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.top_25_smooth/google_calendar"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.top_25_smooth/google_docs"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.top_25_smooth/google_image_search"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.top_25_smooth/google_plus"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.top_25_smooth/google_web_search"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.top_25_smooth/linkedin"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.top_25_smooth/pinterest"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.top_25_smooth/techcrunch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.top_25_smooth/twitter"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.top_25_smooth/weather.com"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.top_25_smooth/wikipedia"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.top_25_smooth/wordpress"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.top_25_smooth/yahoo_answers"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.top_25_smooth/yahoo_games"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.top_25_smooth/yahoo_news"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.top_25_smooth/yahoo_sports"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.top_25_smooth/youtube"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swiffy72.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swiffy72.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swiffy72.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swiffy72.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swiffy72.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/balls_css_key_frame_animations"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/balls_css_keyframe_animations.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_2_properties"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_2_properties.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_40_properties"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_40_properties.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_all_properties"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_all_properties.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_canvas"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_canvas.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_css"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_css.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.tough_animation_cases/balls_svg_animations"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/balls_svg_animations.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/compositor_heavy_animation.html?N=0200"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_many_keyframes"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_many_keyframes.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_inline_style"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_new_element"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_style_element"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_updating_class"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_infinite_iterations"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_infinite_iterations.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_inline_style"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_new_element"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_style_element"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_updating_class"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_triggered_inline_style"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_triggered_new_element"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_animations_triggered_style_element"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_animations_triggered_updating_class"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_inline_style"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_new_element"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_inline_style"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_new_element"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_style_element"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_updating_class"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_style_element"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_triggered_inline_style"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_triggered_new_element"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_triggered_style_element"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_triggered_updating_class"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_updating_class"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_color"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_filter"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_filter.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_complex"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_simple"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_path"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_shadow"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_complex"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_simple"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/keyframed_animations"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/keyframed_animations.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_difference"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_difference.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_hue"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_hue.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_propagating_isolation"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_screen"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_screen.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_propagating_isolation.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/overlay_background_color_css_transitions.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_animation_cases/overlay_background_color_css_transitions_page"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/transform_transition_js_block.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/transform_transitions"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/transform_transitions.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/transform_transitions_js_block"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_color"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_length_3d"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_length_complex"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_length_simple"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_path"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_shadow"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_transform_complex"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animation_value_type_transform_simple"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_many_keyframes"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_many_keyframes.html?N=0316"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animations_set_current_time"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animations_set_current_time_in_raf.html?N=0316"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/web_animations_simultaneous"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_animation_cases/web_animations_simultaneous.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_chaining"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_chaining.html?N=0316"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_infinite_iterations"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_infinite_iterations.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_triggering.html?N=0316"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_triggering_page"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/../../../chrome/test/data/perf/canvas_bench/many_images.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_balls_15"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_balls_shadow"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_clipped_rectangles"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_gradient_circles"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_png_images"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_canvas_cases/bouncing_svg_images"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/canvas_animation_no_clear"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/canvas_arcs"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/canvas_font_cycler"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/canvas_lines"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/canvas_to_blob"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/chip_tune"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/crafty_mind"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/effect_games"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/fill_shapes"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/geo_apis"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/hakim"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://geoapis.appspot.com/agdnZW9hcGlzchMLEgtFeGFtcGxlQ29kZRjh1wIM"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://hakim.se/experiments/html5/magnetic/02/"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/TweetMap/Default.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/VideoCity/Default.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/WorkerFountains/Default.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/AsteroidBelt/Default.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/FishIETank/Default.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/LetItSnow/"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/SpeedReading/Default.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://jarrodoverson.com/static/demos/particleSystem/"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://mix10k.visitmix.com/Entry/Details/169"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://runway.countlessprojects.com/prototype/performance_test.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://spielzeugz.de/html5/liquid-particles.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://themaninblue.com/experiment/AnimationBenchmark/canvas/"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://www.chiptune.com/starfield/starfield.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://www.craftymind.com/factory/guimark2/HTML5ChartingTest.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://www.effectgames.com/demos/canvascycle/"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://www.kevs3d.co.uk/dev/canvask3d/k3d_test.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/http://www.megidish.net/awjs/"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/http://www.smashcat.org/av/canvas_test/"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/jarro_doverson"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/kevs_3d"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/man_in_blue"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/many_images"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/megi_dish"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_asteroid_belt"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_fish_ie_tank"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_snow"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_speed_reading"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_tweet_map"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_video_city"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/microsoft_worker_fountains"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/mix_10k"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/put_get_image_data"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/runway"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/smash_cat"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/spielzeugz"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/stroke_shapes"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-animation-no-clear.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-font-cycler.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=image_with_shadow&back=image"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=text&back=white&ball_count=15"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas_toBlob.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_clipped_rectangles.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_gradient_circles.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_png_images.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_svg_images.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_arcs.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_lines.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/fill_shapes.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/put_get_image_data.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/stroke_shapes.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_filters_cases/analog_clock_svg"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_filters_cases/filter_terrain_svg"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_filters_cases/ie_pirate_mark"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_filters_cases/motion_mark_focus"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_image_decode_cases/cats_unscaled"
+    },
+    {
+        "duration": "11.0",
+        "name": "smoothness.tough_image_decode_cases/cats_viewport_width"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-unscaled.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-viewport-width.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_path_rendering_cases/guimark_vector_chart"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_path_rendering_cases/ie_chalkboard"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_path_rendering_cases/motion_mark_canvas_fill_shapes"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_path_rendering_cases/motion_mark_canvas_stroke_shapes"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_pinch_zoom_cases/amazon_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_pinch_zoom_cases/blogspot_pinch"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_pinch_zoom_cases/booking_pinch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_pinch_zoom_cases/cnn_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_pinch_zoom_cases/ebay_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_pinch_zoom_cases/espn_pinch"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_pinch_zoom_cases/facebook_pinch"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_pinch_zoom_cases/gmail_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_pinch_zoom_cases/google_calendar_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_pinch_zoom_cases/google_image_pinch"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_pinch_zoom_cases/google_search_pinch"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_pinch_zoom_cases/linkedin_pinch"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_pinch_zoom_cases/twitter_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_pinch_zoom_cases/weather_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_pinch_zoom_cases/yahoo_games_pinch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_pinch_zoom_cases/yahoo_news_pinch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_pinch_zoom_cases/yahoo_sports_pinch"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_pinch_zoom_cases/youtube_pinch"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_texture_upload_cases/background_color_animation"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_texture_upload_cases/background_color_animation_with_gradient"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_texture_upload_cases/extra_large_texture_uploads"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_texture_upload_cases/large_texture_uploads"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_texture_upload_cases/medium_texture_uploads"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_texture_upload_cases/small_texture_uploads"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swf.webglbeta.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swf.webglbeta.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swf.webglbeta.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swf.webglbeta.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swf.webglbeta.html"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/animometer_webgl"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/aquarium"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/aquarium_20k"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/blob"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/dynamic_cube_map"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/earth"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/many_planets_deep"
+    },
+    {
+        "duration": "9.0",
+        "name": "smoothness.tough_webgl_cases/nvidia_vertex_buffer_object"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/particles"
+    },
+    {
+        "duration": "4.0",
+        "name": "smoothness.tough_webgl_cases/san_angeles"
+    },
+    {
+        "duration": "36.0",
+        "name": "speedometer-future/http://browserbench.org/Speedometer/"
+    },
+    {
+        "duration": "36.0",
+        "name": "speedometer/http://browserbench.org/Speedometer/"
+    },
+    {
+        "duration": "60.0",
+        "name": "speedometer2-future/Speedometer2"
+    },
+    {
+        "duration": "59.0",
+        "name": "speedometer2/Speedometer2"
+    },
+    {
+        "duration": "31.0",
+        "name": "start_with_url.cold.startup_pages/about:blank"
+    },
+    {
+        "duration": "30.0",
+        "name": "start_with_url.cold.startup_pages/http://bbc.co.uk"
+    },
+    {
+        "duration": "29.0",
+        "name": "start_with_url.warm.startup_pages/about:blank"
+    },
+    {
+        "duration": "30.0",
+        "name": "start_with_url.warm.startup_pages/http://bbc.co.uk"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/background:media:imgur"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.common_mobile/background:news:nytimes"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/background:search:google"
+    },
+    {
+        "duration": "36.0",
+        "name": "system_health.common_mobile/background:social:facebook"
+    },
+    {
+        "duration": "36.0",
+        "name": "system_health.common_mobile/background:tools:gmail"
+    },
+    {
+        "duration": "88.0",
+        "name": "system_health.common_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.common_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "98.0",
+        "name": "system_health.common_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "63.0",
+        "name": "system_health.common_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "92.0",
+        "name": "system_health.common_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "112.0",
+        "name": "system_health.common_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "111.0",
+        "name": "system_health.common_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "75.0",
+        "name": "system_health.common_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "67.0",
+        "name": "system_health.common_mobile/browse:news:qq"
+    },
+    {
+        "duration": "61.0",
+        "name": "system_health.common_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "153.0",
+        "name": "system_health.common_mobile/browse:news:toi"
+    },
+    {
+        "duration": "69.0",
+        "name": "system_health.common_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "86.0",
+        "name": "system_health.common_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "82.0",
+        "name": "system_health.common_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "42.0",
+        "name": "system_health.common_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "87.0",
+        "name": "system_health.common_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "223.0",
+        "name": "system_health.common_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "92.0",
+        "name": "system_health.common_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "106.0",
+        "name": "system_health.common_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "132.0",
+        "name": "system_health.common_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "65.0",
+        "name": "system_health.common_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "91.0",
+        "name": "system_health.common_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "58.0",
+        "name": "system_health.common_mobile/browse:tools:maps"
+    },
+    {
+        "duration": "22.0",
+        "name": "system_health.common_mobile/load:chrome:blank"
+    },
+    {
+        "duration": "27.0",
+        "name": "system_health.common_mobile/load:games:bubbles"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.common_mobile/load:games:lazors"
+    },
+    {
+        "duration": "37.0",
+        "name": "system_health.common_mobile/load:games:spychase"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.common_mobile/load:media:dailymotion"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:media:facebook_photos"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:media:google_images"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.common_mobile/load:media:imgur"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:media:soundcloud"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:media:youtube"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.common_mobile/load:news:cnn"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.common_mobile/load:news:irctc"
+    },
+    {
+        "duration": "29.0",
+        "name": "system_health.common_mobile/load:news:nytimes"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:news:qq"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:news:reddit"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.common_mobile/load:news:washingtonpost"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:news:wikipedia"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.common_mobile/load:search:baidu"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.common_mobile/load:search:ebay"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.common_mobile/load:search:google"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:search:taobao"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.common_mobile/load:search:yahoo"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.common_mobile/load:search:yandex"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.common_mobile/load:social:twitter"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.common_mobile/load:tools:docs"
+    },
+    {
+        "duration": "27.0",
+        "name": "system_health.common_mobile/load:tools:drive"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.common_mobile/load:tools:dropbox"
+    },
+    {
+        "duration": "35.0",
+        "name": "system_health.common_mobile/load:tools:gmail"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.common_mobile/load:tools:stackoverflow"
+    },
+    {
+        "duration": "30.0",
+        "name": "system_health.common_mobile/load:tools:weather"
+    },
+    {
+        "duration": "136.0",
+        "name": "system_health.common_mobile/long_running:tools:gmail-background"
+    },
+    {
+        "duration": "134.0",
+        "name": "system_health.common_mobile/long_running:tools:gmail-foreground"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.memory_mobile/background:media:imgur"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.memory_mobile/background:news:nytimes"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.memory_mobile/background:search:google"
+    },
+    {
+        "duration": "27.0",
+        "name": "system_health.memory_mobile/background:social:facebook"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/background:tools:gmail"
+    },
+    {
+        "duration": "77.0",
+        "name": "system_health.memory_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "75.0",
+        "name": "system_health.memory_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "46.0",
+        "name": "system_health.memory_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "70.0",
+        "name": "system_health.memory_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "81.0",
+        "name": "system_health.memory_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "57.0",
+        "name": "system_health.memory_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "52.0",
+        "name": "system_health.memory_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.memory_mobile/browse:news:qq"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.memory_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "69.0",
+        "name": "system_health.memory_mobile/browse:news:toi"
+    },
+    {
+        "duration": "48.0",
+        "name": "system_health.memory_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "52.0",
+        "name": "system_health.memory_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "53.0",
+        "name": "system_health.memory_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "61.0",
+        "name": "system_health.memory_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "76.0",
+        "name": "system_health.memory_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "72.0",
+        "name": "system_health.memory_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "71.0",
+        "name": "system_health.memory_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "71.0",
+        "name": "system_health.memory_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.memory_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "56.0",
+        "name": "system_health.memory_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "45.0",
+        "name": "system_health.memory_mobile/browse:tools:maps"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.memory_mobile/load:chrome:blank"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:games:bubbles"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:games:lazors"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.memory_mobile/load:games:spychase"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.memory_mobile/load:media:dailymotion"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:media:facebook_photos"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:media:google_images"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:media:imgur"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:media:soundcloud"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:media:youtube"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.memory_mobile/load:news:cnn"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:news:irctc"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.memory_mobile/load:news:nytimes"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:news:qq"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:news:reddit"
+    },
+    {
+        "duration": "25.0",
+        "name": "system_health.memory_mobile/load:news:washingtonpost"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:news:wikipedia"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:search:baidu"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:search:ebay"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:search:google"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:search:taobao"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.memory_mobile/load:search:yahoo"
+    },
+    {
+        "duration": "22.0",
+        "name": "system_health.memory_mobile/load:search:yandex"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:social:twitter"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:tools:docs"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:tools:drive"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.memory_mobile/load:tools:dropbox"
+    },
+    {
+        "duration": "24.0",
+        "name": "system_health.memory_mobile/load:tools:stackoverflow"
+    },
+    {
+        "duration": "26.0",
+        "name": "system_health.memory_mobile/load:tools:weather"
+    },
+    {
+        "duration": "292.0",
+        "name": "system_health.memory_mobile/long_running:tools:gmail-background"
+    },
+    {
+        "duration": "252.0",
+        "name": "system_health.memory_mobile/long_running:tools:gmail-foreground"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.key_idle_power_cases/animated-gif.html"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.key_idle_power_cases/blank.html"
+    },
+    {
+        "duration": "37.0",
+        "name": "thread_times.key_idle_power_cases/css-animation.html"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_animated_gif"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_blank"
+    },
+    {
+        "duration": "37.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_css_animation"
+    },
+    {
+        "duration": "39.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_request_animation_frame"
+    },
+    {
+        "duration": "109.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_set_timeout_long"
+    },
+    {
+        "duration": "38.0",
+        "name": "thread_times.key_idle_power_cases/idle_power_set_timetout"
+    },
+    {
+        "duration": "38.0",
+        "name": "thread_times.key_idle_power_cases/request-animation-frame.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "thread_times.key_idle_power_cases/set-timeout.html"
+    },
+    {
+        "duration": "108.0",
+        "name": "thread_times.key_idle_power_cases/set-timeout.html (Long Idle)"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.key_noop_cases/no_op_raf"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.key_noop_cases/no_op_raf.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_noop_cases/no_op_scroll"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_noop_cases/no_op_scroll.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.key_noop_cases/no_op_settimeout"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.key_noop_cases/no_op_settimeout.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_noop_cases/no_op_touch_handler"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_noop_cases/no_op_touch_handler.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/card_expansion"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/card_expansion_animated"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/card_expansion_images_text"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/card_flying"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/coordinated_animation"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/font_wipe"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/font_wipe.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/google_news_ios"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/gws_boogie_expansion"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/gws_google_expansion"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/horizontal_vertical_expansion"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.key_silk_cases/http://groupcloned.com/test/plain/list-recycle-transform.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.key_silk_cases/http://groupcloned.com/test/plain/sticky-using-webkit-backface-visibility.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "thread_times.key_silk_cases/http://jsbin.com/UVIgUTa/38/quiet"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/3yDKh/15/show/"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/3yDKh/16/show/"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/R8DX9/4/show/"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/TLXLu/3/show/"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/bNp2h/3/show/"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/cKB9D/7/show/"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/jx5De/14/show/"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/rF9Gh/7/show/"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/ugkd4/10/show/"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/vBQHH/11/show/"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/xLuvC/1/show/"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?scroll"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?swipe"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.key_silk_cases/http://wiltzius.github.io/shape-shifter/"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/http://www.google.com/#q=google"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.key_silk_cases/https://www.google.com/search?hl=en&q=define%3Aboogie"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?stress_hidey_bars"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?toggle_drawer"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.key_silk_cases/infinite_scrolling"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.key_silk_cases/infinite_scrolling.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.key_silk_cases/list_animation_simple"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.key_silk_cases/list_animation_simple.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.key_silk_cases/list_recycle_transform"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/mask_transition_animation"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.key_silk_cases/mobile_news_sandbox"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.key_silk_cases/parallax_effect"
+    },
+    {
+        "duration": "14.0",
+        "name": "thread_times.key_silk_cases/physical_simulation"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/pushState.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.key_silk_cases/silk_finance"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.key_silk_cases/silk_finance.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.key_silk_cases/sticky_using_webkit"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.key_silk_cases/stress_hidey_bars"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.key_silk_cases/svg_icon_raster"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/swipe_to_dismiss"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/toggle_drawer"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/update_history_state"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/vertical_expansion"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.key_silk_cases/zoom_in_animation"
+    },
+    {
+        "duration": "39.0",
+        "name": "thread_times.simple_mobile_sites/ebay_scroll"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.simple_mobile_sites/flickr_scroll"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.simple_mobile_sites/http://m.nytimes.com/"
+    },
+    {
+        "duration": "40.0",
+        "name": "thread_times.simple_mobile_sites/http://www.ebay.co.uk/"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.simple_mobile_sites/http://www.nyc.gov"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.simple_mobile_sites/https://www.flickr.com/"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.simple_mobile_sites/nyc_gov_scroll"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.simple_mobile_sites/nytimes_scroll"
+    },
+    {
+        "duration": "28.0",
+        "name": "thread_times.tough_compositor_cases/cc_poster_circle"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_compositor_cases/cc_scroll_200_layer_grid"
+    },
+    {
+        "duration": "35.0",
+        "name": "thread_times.tough_compositor_cases/cc_scroll_text_only"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/beqojupo/1/quiet?JS_FULL_SCREEN_INVALIDATION"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/covoqi/1/quiet?NEW_TILINGS"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/falefice/1/quiet?CC_POSTER_CIRCLE"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/giqafofe/1/quiet?JS_POSTER_CIRCLE"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/jevibahi/4/quiet?JS_SCROLL_200_LAYER_GRID"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/pixavefe/1/quiet?CC_SCROLL_TEXT_ONLY"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/wixadinu/2/quiet?JS_SCROLL_TEXT_ONLY"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/yakagevo/1/quiet?CC_SCROLL_200_LAYER_GRID"
+    },
+    {
+        "duration": "37.0",
+        "name": "thread_times.tough_compositor_cases/js_full_screen_invalidation"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_compositor_cases/js_poster_circle"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_compositor_cases/js_scroll_200_layer_grid"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_compositor_cases/js_scroll_text_only"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.tough_compositor_cases/new_tilings"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "28.0",
+        "name": "thread_times.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "19.0",
+        "name": "thread_times.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "18.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "17.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "16.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "15.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "14.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "13.0",
+        "name": "tracing.tracing_with_background_memory_infra/Facebook"
+    },
+    {
+        "duration": "13.0",
+        "name": "tracing.tracing_with_background_memory_infra/Wikipedia"
+    },
+    {
+        "duration": "11.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.amazon.com"
+    },
+    {
+        "duration": "11.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.ask.com/"
+    },
+    {
+        "duration": "10.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.bing.com/"
+    },
+    {
+        "duration": "11.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.yahoo.com/"
+    },
+    {
+        "duration": "14.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.youtube.com"
+    },
+    {
+        "duration": "19.0",
+        "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/#hl=en&q=barack+obama"
+    },
+    {
+        "duration": "14.0",
+        "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/calendar/"
+    },
+    {
+        "duration": "98.0",
+        "name": "v8.browsing_mobile-future/browse:chrome:newtab"
+    },
+    {
+        "duration": "38.0",
+        "name": "v8.browsing_mobile-future/browse:chrome:omnibox"
+    },
+    {
+        "duration": "119.0",
+        "name": "v8.browsing_mobile-future/browse:media:facebook_photos"
+    },
+    {
+        "duration": "77.0",
+        "name": "v8.browsing_mobile-future/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "118.0",
+        "name": "v8.browsing_mobile-future/browse:media:imgur"
+    },
+    {
+        "duration": "133.0",
+        "name": "v8.browsing_mobile-future/browse:media:youtube"
+    },
+    {
+        "duration": "169.0",
+        "name": "v8.browsing_mobile-future/browse:news:cnn"
+    },
+    {
+        "duration": "91.0",
+        "name": "v8.browsing_mobile-future/browse:news:cricbuzz"
+    },
+    {
+        "duration": "80.0",
+        "name": "v8.browsing_mobile-future/browse:news:qq"
+    },
+    {
+        "duration": "72.0",
+        "name": "v8.browsing_mobile-future/browse:news:reddit"
+    },
+    {
+        "duration": "241.0",
+        "name": "v8.browsing_mobile-future/browse:news:toi"
+    },
+    {
+        "duration": "85.0",
+        "name": "v8.browsing_mobile-future/browse:news:washingtonpost"
+    },
+    {
+        "duration": "121.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:amazon"
+    },
+    {
+        "duration": "108.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:avito"
+    },
+    {
+        "duration": "52.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:lazada"
+    },
+    {
+        "duration": "114.0",
+        "name": "v8.browsing_mobile-future/browse:social:facebook"
+    },
+    {
+        "duration": "320.0",
+        "name": "v8.browsing_mobile-future/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "117.0",
+        "name": "v8.browsing_mobile-future/browse:social:instagram"
+    },
+    {
+        "duration": "141.0",
+        "name": "v8.browsing_mobile-future/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "165.0",
+        "name": "v8.browsing_mobile-future/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "75.0",
+        "name": "v8.browsing_mobile-future/browse:social:twitter"
+    },
+    {
+        "duration": "121.0",
+        "name": "v8.browsing_mobile-future/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "77.0",
+        "name": "v8.browsing_mobile-future/browse:tools:maps"
+    },
+    {
+        "duration": "100.0",
+        "name": "v8.browsing_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "39.0",
+        "name": "v8.browsing_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "121.0",
+        "name": "v8.browsing_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "78.0",
+        "name": "v8.browsing_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "121.0",
+        "name": "v8.browsing_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "131.0",
+        "name": "v8.browsing_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "169.0",
+        "name": "v8.browsing_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "90.0",
+        "name": "v8.browsing_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "82.0",
+        "name": "v8.browsing_mobile/browse:news:qq"
+    },
+    {
+        "duration": "73.0",
+        "name": "v8.browsing_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "237.0",
+        "name": "v8.browsing_mobile/browse:news:toi"
+    },
+    {
+        "duration": "88.0",
+        "name": "v8.browsing_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "129.0",
+        "name": "v8.browsing_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "107.0",
+        "name": "v8.browsing_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "53.0",
+        "name": "v8.browsing_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "113.0",
+        "name": "v8.browsing_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "323.0",
+        "name": "v8.browsing_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "113.0",
+        "name": "v8.browsing_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "145.0",
+        "name": "v8.browsing_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "167.0",
+        "name": "v8.browsing_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "76.0",
+        "name": "v8.browsing_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "121.0",
+        "name": "v8.browsing_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "77.0",
+        "name": "v8.browsing_mobile/browse:tools:maps"
+    },
+    {
+        "duration": "9.0",
+        "name": "wasm/AsmJsZenGarden"
+    },
+    {
+        "duration": "21.0",
+        "name": "wasm/WasmSpaceBuggy"
+    },
+    {
+        "duration": "9.0",
+        "name": "wasm/WasmStylizedRenderer"
+    },
+    {
+        "duration": "9.0",
+        "name": "wasm/WasmSunTemple"
+    },
+    {
+        "duration": "17.0",
+        "name": "wasm/WasmTanks"
+    },
+    {
+        "duration": "9.0",
+        "name": "wasm/WasmZenGarden"
+    },
+    {
+        "duration": "22.0",
+        "name": "webrtc/10s_datachannel_transfer"
+    },
+    {
+        "duration": "27.0",
+        "name": "webrtc/canvas_capture_peer_connection"
+    },
+    {
+        "duration": "36.0",
+        "name": "webrtc/codec_constraints_h264"
+    },
+    {
+        "duration": "36.0",
+        "name": "webrtc/codec_constraints_vp8"
+    },
+    {
+        "duration": "36.0",
+        "name": "webrtc/codec_constraints_vp9"
+    },
+    {
+        "duration": "23.0",
+        "name": "webrtc/hd_local_stream_10s"
+    },
+    {
+        "duration": "45.0",
+        "name": "webrtc/multiple_peerconnections"
+    },
+    {
+        "duration": "68.0",
+        "name": "webrtc/pause_play_peerconnections"
+    }
+]
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 35bd151..eb60ca9 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -277,10 +277,6 @@
     compositor()->SetVisible(false);
 }
 
-gfx::Size WindowTreeHost::GetCompositorSizeInPixels() const {
-  return GetBoundsInPixels().size();
-}
-
 std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents(
     base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
   // TODO(joedow): Remove the simple hook class/logic once this flag is removed.
@@ -363,8 +359,7 @@
 
 void WindowTreeHost::InitCompositor() {
   DCHECK(!compositor_->root_layer());
-  compositor_->SetScaleAndSize(device_scale_factor_,
-                               GetCompositorSizeInPixels(),
+  compositor_->SetScaleAndSize(device_scale_factor_, GetBoundsInPixels().size(),
                                window()->GetLocalSurfaceId());
   compositor_->SetRootLayer(window()->layer());
 
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h
index f4fa860..77c28cf 100644
--- a/ui/aura/window_tree_host.h
+++ b/ui/aura/window_tree_host.h
@@ -197,7 +197,6 @@
       const gfx::Rect& bounds_in_pixels,
       const viz::LocalSurfaceId& local_surface_id = viz::LocalSurfaceId()) = 0;
   virtual gfx::Rect GetBoundsInPixels() const = 0;
-  virtual gfx::Size GetCompositorSizeInPixels() const;
 
   // Sets the OS capture to the root window.
   virtual void SetCapture() = 0;
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
index 3253f63..334bc9c 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_mac.mm
+++ b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -100,17 +100,18 @@
   DCHECK(url);
   DCHECK(title);
 
-  NSArray* urlArray = nil;
-  NSArray* titleArray = nil;
-  if (ClipboardUtil::URLsAndTitlesFromPasteboard(pasteboard_->get(), &urlArray,
-                                                 &titleArray)) {
-    *url = GURL(base::SysNSStringToUTF8([urlArray firstObject]));
-    *title = base::SysNSStringToUTF16([titleArray firstObject]);
+  if (ui::PopulateURLAndTitleFromPasteboard(url, title, pasteboard_->get(),
+                                            false)) {
     return true;
   }
 
-  // If there are no URLS, try to convert a filename to a URL if the policy
+  // If there are no URLs, try to convert a filename to a URL if the policy
   // allows it. The title remains blank.
+  //
+  // This could be done in the call to PopulateURLAndTitleFromPasteboard above
+  // if |true| were passed in as the last parameter, but that function strips
+  // the trailing slashes off of paths and always returns the last path element
+  // as the title whereas no path conversion nor title is wanted.
   base::FilePath path;
   if (policy != OSExchangeData::DO_NOT_CONVERT_FILENAMES &&
       GetFilename(&path)) {
diff --git a/ui/events/cocoa/events_mac.mm b/ui/events/cocoa/events_mac.mm
index ebeb04ea..c60c04c7 100644
--- a/ui/events/cocoa/events_mac.mm
+++ b/ui/events/cocoa/events_mac.mm
@@ -63,7 +63,6 @@
     case NSEventTypeRotate:
     case NSEventTypeBeginGesture:
     case NSEventTypeEndGesture:
-      NOTIMPLEMENTED() << type;
       break;
     default:
       NOTIMPLEMENTED() << type;
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 31cca78..c29ed3e 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -1069,6 +1069,18 @@
       cached_bounds_and_offset_valid_(false),
       strike_thickness_factor_(kLineThicknessFactor) {}
 
+bool RenderText::IsHomogeneous() const {
+  if (colors().breaks().size() > 1 || baselines().breaks().size() > 1 ||
+      font_size_overrides().breaks().size() > 1 ||
+      weights().breaks().size() > 1)
+    return false;
+  for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) {
+    if (styles()[style].breaks().size() > 1)
+      return false;
+  }
+  return true;
+}
+
 SelectionModel RenderText::GetAdjacentSelectionModel(
     const SelectionModel& current,
     BreakType break_type,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 76c0db0..50eaca5 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -565,6 +565,9 @@
   const std::vector<BreakList<bool> >& styles() const { return styles_; }
   SkScalar strike_thickness_factor() const { return strike_thickness_factor_; }
 
+  // Whether all the BreakLists have only one break.
+  bool IsHomogeneous() const;
+
   const std::vector<internal::Line>& lines() const { return lines_; }
   void set_lines(std::vector<internal::Line>* lines) { lines_.swap(*lines); }
 
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 17ec8623..b3774d7 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -186,8 +186,8 @@
   return run_break;
 }
 
-// Find the longest sequence of characters from 0 and up to |length| that
-// have at least one common UScriptCode value. Writes the common script value to
+// Find the longest sequence of characters from 0 and up to |length| that have
+// at least one common UScriptCode value. Writes the common script value to
 // |script| and returns the length of the sequence. Takes the characters' script
 // extensions into account. http://www.unicode.org/reports/tr24/#ScriptX
 //
@@ -477,7 +477,7 @@
         last_segment.char_range.set_end(segment.char_range.end());
         last_segment.x_range.set_end(SkScalarToFloat(text_x_) +
                                      segment.width());
-        if (run.common.is_rtl &&
+        if (run.font_params.is_rtl &&
             last_segment.char_range.end() == run.range.end())
           UpdateRTLSegmentRanges();
         line->size.set_width(line->size.width() + segment.width());
@@ -490,20 +490,20 @@
     line->size.set_width(line->size.width() + segment.width());
 
     SkPaint paint;
-    paint.setTypeface(run.common.skia_face);
-    paint.setTextSize(SkIntToScalar(run.common.font_size));
-    paint.setAntiAlias(run.common.render_params.antialiasing);
+    paint.setTypeface(run.font_params.skia_face);
+    paint.setTextSize(SkIntToScalar(run.font_params.font_size));
+    paint.setAntiAlias(run.font_params.render_params.antialiasing);
     SkPaint::FontMetrics metrics;
     paint.getFontMetrics(&metrics);
 
     // max_descent_ is y-down, fDescent is y-down, baseline_offset is y-down
-    max_descent_ =
-        std::max(max_descent_, metrics.fDescent + run.common.baseline_offset);
+    max_descent_ = std::max(max_descent_,
+                            metrics.fDescent + run.font_params.baseline_offset);
     // max_ascent_ is y-up, fAscent is y-down, baseline_offset is y-down
-    max_ascent_ =
-        std::max(max_ascent_, -(metrics.fAscent + run.common.baseline_offset));
+    max_ascent_ = std::max(
+        max_ascent_, -(metrics.fAscent + run.font_params.baseline_offset));
 
-    if (run.common.is_rtl) {
+    if (run.font_params.is_rtl) {
       rtl_segments_.push_back(
           SegmentHandle(lines_.size() - 1, line->segments.size() - 1));
       // If this is the last segment of an RTL run, reprocess the text-space x
@@ -670,16 +670,15 @@
 }
 #endif
 
-TextRunHarfBuzz::CommonParams::CommonParams(const Font& template_font)
+TextRunHarfBuzz::FontParams::FontParams(const Font& template_font)
     : font(template_font) {}
-TextRunHarfBuzz::CommonParams::~CommonParams() = default;
-TextRunHarfBuzz::CommonParams::CommonParams(
-    const TextRunHarfBuzz::CommonParams& other) = default;
-TextRunHarfBuzz::CommonParams& TextRunHarfBuzz::CommonParams::operator=(
-    const TextRunHarfBuzz::CommonParams& other) = default;
+TextRunHarfBuzz::FontParams::~FontParams() = default;
+TextRunHarfBuzz::FontParams::FontParams(
+    const TextRunHarfBuzz::FontParams& other) = default;
+TextRunHarfBuzz::FontParams& TextRunHarfBuzz::FontParams::operator=(
+    const TextRunHarfBuzz::FontParams& other) = default;
 
-bool TextRunHarfBuzz::CommonParams::operator==(
-    const CommonParams& other) const {
+bool TextRunHarfBuzz::FontParams::operator==(const FontParams& other) const {
   // Empirically, |script| and |weight| are the highest entropy members.
   return script == other.script && weight == other.weight &&
          skia_face == other.skia_face && render_params == other.render_params &&
@@ -691,7 +690,7 @@
          level == other.level;
 }
 
-void TextRunHarfBuzz::CommonParams::
+void TextRunHarfBuzz::FontParams::
     ComputeRenderParamsFontSizeAndBaselineOffset() {
   render_params = font.GetFontRenderParams();
   if (font_size == 0)
@@ -720,8 +719,8 @@
   }
 }
 
-size_t TextRunHarfBuzz::CommonParams::Hash::operator()(
-    const CommonParams& key) const {
+size_t TextRunHarfBuzz::FontParams::Hash::operator()(
+    const FontParams& key) const {
   // In practice, |font|, |skia_face|, |render_params|, and |baseline_offset|
   // have not yet been set when this is called.
   return static_cast<size_t>(key.italic) << 0 ^
@@ -736,7 +735,7 @@
          static_cast<size_t>(key.script) << 24;
 }
 
-bool TextRunHarfBuzz::CommonParams::SetFontAndRenderParams(
+bool TextRunHarfBuzz::FontParams::SetFontAndRenderParams(
     const Font& new_font,
     const FontRenderParams& new_render_params) {
   sk_sp<SkTypeface> new_skia_face(
@@ -762,7 +761,7 @@
     TextRunHarfBuzz::ShapeOutput&& other) = default;
 
 TextRunHarfBuzz::TextRunHarfBuzz(const Font& template_font)
-    : common(template_font) {}
+    : font_params(template_font) {}
 
 TextRunHarfBuzz::~TextRunHarfBuzz() {}
 
@@ -777,8 +776,8 @@
   GetClusterAt(char_range.start(), &temp_range, &start_glyphs);
   GetClusterAt(char_range.end() - 1, &temp_range, &end_glyphs);
 
-  return common.is_rtl ? Range(end_glyphs.start(), start_glyphs.end())
-                       : Range(start_glyphs.start(), end_glyphs.end());
+  return font_params.is_rtl ? Range(end_glyphs.start(), start_glyphs.end())
+                            : Range(start_glyphs.start(), end_glyphs.end());
 }
 
 size_t TextRunHarfBuzz::CountMissingGlyphs() const {
@@ -798,7 +797,7 @@
     success = false;
   }
 
-  if (common.is_rtl) {
+  if (font_params.is_rtl) {
     success &=
         GetClusterAtImpl(pos, range, shape.glyph_to_char.rbegin(),
                          shape.glyph_to_char.rend(), true, chars, glyphs);
@@ -816,11 +815,11 @@
                               base::UintToString(shape.glyph_to_char[i]) + ", ";
     }
     LOG(ERROR) << " TextRunHarfBuzz error, please report at crbug.com/724880:"
-               << " range: " << range.ToString() << ", rtl: " << common.is_rtl
-               << ","
-               << " level: '" << common.level << "', script: " << common.script
-               << ","
-               << " font: '" << common.font.GetActualFontNameForTesting()
+               << " range: " << range.ToString()
+               << ", rtl: " << font_params.is_rtl << ","
+               << " level: '" << font_params.level
+               << "', script: " << font_params.script << ","
+               << " font: '" << font_params.font.GetActualFontNameForTesting()
                << "',"
                << " glyph_count: " << shape.glyph_count << ", pos: " << pos
                << ","
@@ -872,7 +871,7 @@
       --before;
 
     if (total > 1) {
-      if (common.is_rtl)
+      if (font_params.is_rtl)
         before = total - before - 1;
       DCHECK_GE(before, 0);
       DCHECK_LT(before, total);
@@ -899,7 +898,7 @@
   size_t right_index =
       UTF16OffsetToIndex(render_text->GetDisplayText(), char_range.end(), -1);
   DCHECK_LE(left_index, right_index);
-  if (common.is_rtl)
+  if (font_params.is_rtl)
     std::swap(left_index, right_index);
 
   const RangeF left_span = GetGraphemeBounds(render_text, left_index);
@@ -935,11 +934,11 @@
          shape.positions[glyph_range.start()].x();
 }
 
-void TextRunHarfBuzz::UpdateCommonParamsAndShape(
-    const CommonParams& new_common_params,
+void TextRunHarfBuzz::UpdateFontParamsAndShape(
+    const FontParams& new_font_params,
     const ShapeOutput& new_shape) {
   if (new_shape.missing_glyph_count < shape.missing_glyph_count) {
-    common = new_common_params;
+    font_params = new_font_params;
     shape = new_shape;
     // Note that |new_shape.glyph_to_char| is indexed from the beginning of
     // |range|, while |shape.glyph_to_char| is indexed from the beginning of
@@ -966,7 +965,7 @@
   const size_t num_runs = runs_.size();
   std::vector<UBiDiLevel> levels(num_runs);
   for (size_t i = 0; i < num_runs; ++i)
-    levels[i] = runs_[i]->common.level;
+    levels[i] = runs_[i]->font_params.level;
   visual_to_logical_.resize(num_runs);
   ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]);
   logical_to_visual_.resize(num_runs);
@@ -1004,19 +1003,19 @@
 // Input for the stateless implementation of ShapeRunWithFont.
 struct ShapeRunWithFontInput {
   ShapeRunWithFontInput(const base::string16& full_text,
-                        const TextRunHarfBuzz::CommonParams& common_params,
+                        const TextRunHarfBuzz::FontParams& font_params,
                         Range full_range,
                         bool obscured,
                         float glyph_width_for_test,
                         int glyph_spacing,
                         bool subpixel_rendering_suppressed)
-      : skia_face(common_params.skia_face),
-        render_params(common_params.render_params),
-        script(common_params.script),
-        font_size(common_params.font_size),
+      : skia_face(font_params.skia_face),
+        render_params(font_params.render_params),
+        script(font_params.script),
+        font_size(font_params.font_size),
         glyph_spacing(glyph_spacing),
         glyph_width_for_test(glyph_width_for_test),
-        is_rtl(common_params.is_rtl),
+        is_rtl(font_params.is_rtl),
         obscured(obscured),
         subpixel_rendering_suppressed(subpixel_rendering_suppressed) {
     // hb_buffer_add_utf16 will read the previous and next 5 unicode characters
@@ -1271,16 +1270,16 @@
         (end + SkScalarToFloat(run.shape.positions[i].x())) / 2;
     const size_t index = DisplayIndexToTextIndex(run.shape.glyph_to_char[i]);
     if (point_offset_relative_run < middle) {
-      return run.common.is_rtl ? SelectionModel(IndexOfAdjacentGrapheme(
-                                                    index, CURSOR_FORWARD),
-                                                CURSOR_BACKWARD)
-                               : SelectionModel(index, CURSOR_FORWARD);
+      return run.font_params.is_rtl ? SelectionModel(IndexOfAdjacentGrapheme(
+                                                         index, CURSOR_FORWARD),
+                                                     CURSOR_BACKWARD)
+                                    : SelectionModel(index, CURSOR_FORWARD);
     }
     if (point_offset_relative_run < end) {
-      return run.common.is_rtl ? SelectionModel(index, CURSOR_FORWARD)
-                               : SelectionModel(IndexOfAdjacentGrapheme(
-                                                    index, CURSOR_FORWARD),
-                                                CURSOR_BACKWARD);
+      return run.font_params.is_rtl ? SelectionModel(index, CURSOR_FORWARD)
+                                    : SelectionModel(IndexOfAdjacentGrapheme(
+                                                         index, CURSOR_FORWARD),
+                                                     CURSOR_BACKWARD);
     }
   }
 
@@ -1297,9 +1296,10 @@
   internal::TextRunList* run_list = GetRunList();
   std::vector<RenderText::FontSpan> spans;
   for (const auto& run : run_list->runs()) {
-    spans.push_back(RenderText::FontSpan(
-        run->common.font, Range(DisplayIndexToTextIndex(run->range.start()),
-                                DisplayIndexToTextIndex(run->range.end()))));
+    spans.push_back(
+        RenderText::FontSpan(run->font_params.font,
+                             Range(DisplayIndexToTextIndex(run->range.start()),
+                                   DisplayIndexToTextIndex(run->range.end()))));
   }
 
   return spans;
@@ -1332,10 +1332,11 @@
   // If cursor is enabled, extend the last glyph up to the rightmost cursor
   // position since clients expect them to be contiguous.
   if (cursor_enabled() && run_index == run_list->size() - 1 &&
-      index == (run->common.is_rtl ? run->range.start() : run->range.end() - 1))
+      index ==
+          (run->font_params.is_rtl ? run->range.start() : run->range.end() - 1))
     bounds.set_end(std::ceil(bounds.end()));
-  return run->common.is_rtl ? RangeF(bounds.end(), bounds.start()).Round()
-                            : bounds.Round();
+  return run->font_params.is_rtl ? RangeF(bounds.end(), bounds.start()).Round()
+                                 : bounds.Round();
 }
 
 base::i18n::BreakIterator* RenderTextHarfBuzz::GetGraphemeIterator() {
@@ -1375,7 +1376,7 @@
     // grapheme in the appropriate direction.
     run = run_list->runs()[run_index].get();
     size_t caret = selection.caret_pos();
-    bool forward_motion = run->common.is_rtl == (direction == CURSOR_LEFT);
+    bool forward_motion = run->font_params.is_rtl == (direction == CURSOR_LEFT);
     if (forward_motion) {
       if (caret < DisplayIndexToTextIndex(run->range.end())) {
         caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
@@ -1394,7 +1395,7 @@
       return EdgeSelectionModel(direction);
     run = run_list->runs()[run_list->visual_to_logical(visual_index)].get();
   }
-  bool forward_motion = run->common.is_rtl == (direction == CURSOR_LEFT);
+  bool forward_motion = run->font_params.is_rtl == (direction == CURSOR_LEFT);
   return forward_motion ? FirstSelectionModelInsideRun(run) :
                           LastSelectionModelInsideRun(run);
 }
@@ -1426,7 +1427,7 @@
       break;
 #else
     const bool is_forward =
-        run_list->runs()[run]->common.is_rtl == (direction == CURSOR_LEFT);
+        run_list->runs()[run]->font_params.is_rtl == (direction == CURSOR_LEFT);
     if (is_forward ? iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor))
       break;
 #endif  // defined(OS_WIN)
@@ -1543,8 +1544,11 @@
     line_breaker.FinalizeLines(&lines, &total_size_);
     if (multiline() && max_lines()) {
       // TODO(crbug.com/866720): no more than max_lines() should be rendered.
-      // Uncomment the following DCHECK when the bug is fixed.
-      // DCHECK_LE(lines.size(), max_lines());
+      // Remove the IsHomogeneous() condition for the following DCHECK when the
+      // bug is fixed.
+      if (IsHomogeneous()) {
+        DCHECK_LE(lines.size(), max_lines());
+      }
     }
     set_lines(&lines);
   }
@@ -1572,9 +1576,9 @@
         continue;
 
       const internal::TextRunHarfBuzz& run = *run_list->runs()[segment.run];
-      renderer->SetTypeface(run.common.skia_face);
-      renderer->SetTextSize(SkIntToScalar(run.common.font_size));
-      renderer->SetFontRenderParams(run.common.render_params,
+      renderer->SetTypeface(run.font_params.skia_face);
+      renderer->SetTextSize(SkIntToScalar(run.font_params.font_size));
+      renderer->SetFontRenderParams(run.font_params.render_params,
                                     subpixel_rendering_suppressed());
       Range glyphs_range = run.CharRangeToGlyphRange(segment.char_range);
       std::vector<SkPoint> positions(glyphs_range.length());
@@ -1588,7 +1592,7 @@
                                                : (glyphs_range.start() + j)];
         positions[j].offset(
             SkIntToScalar(origin.x()) + offset_x,
-            SkIntToScalar(origin.y() + run.common.baseline_offset));
+            SkIntToScalar(origin.y() + run.font_params.baseline_offset));
       }
       for (BreakList<SkColor>::const_iterator it =
                colors().GetBreak(segment.char_range.start());
@@ -1616,11 +1620,11 @@
                 ? (SkFloatToScalar(segment.width()) + preceding_segment_widths +
                    SkIntToScalar(origin.x()))
                 : positions[colored_glyphs.end() - glyphs_range.start()].x());
-        if (run.common.heavy_underline)
+        if (run.font_params.heavy_underline)
           renderer->DrawUnderline(start_x, origin.y(), end_x - start_x, 2.0);
-        else if (run.common.underline)
+        else if (run.font_params.underline)
           renderer->DrawUnderline(start_x, origin.y(), end_x - start_x);
-        if (run.common.strike)
+        if (run.font_params.strike)
           renderer->DrawStrike(start_x, origin.y(), end_x - start_x,
                                strike_thickness_factor());
       }
@@ -1666,9 +1670,9 @@
 
   for (auto iter = commonized_run_map.begin(); iter != commonized_run_map.end();
        ++iter) {
-    internal::TextRunHarfBuzz::CommonParams common_params = iter->first;
-    common_params.ComputeRenderParamsFontSizeAndBaselineOffset();
-    ShapeRuns(text, common_params, std::move(iter->second));
+    internal::TextRunHarfBuzz::FontParams font_params = iter->first;
+    font_params.ComputeRenderParamsFontSizeAndBaselineOffset();
+    ShapeRuns(text, font_params, std::move(iter->second));
   }
 
   run_list->InitIndexMap();
@@ -1702,8 +1706,8 @@
     auto run = std::make_unique<internal::TextRunHarfBuzz>(
         font_list().GetPrimaryFont());
     run->range = Range(0, text.length());
-    internal::TextRunHarfBuzz::CommonParams common_params(primary_font);
-    (*out_commonized_run_map)[common_params].push_back(run.get());
+    internal::TextRunHarfBuzz::FontParams font_params(primary_font);
+    (*out_commonized_run_map)[font_params].push_back(run.get());
     out_run_list->Add(std::move(run));
     return;
   }
@@ -1723,26 +1727,26 @@
 
   for (size_t run_break = 0; run_break < text.length();) {
     Range run_range;
-    internal::TextRunHarfBuzz::CommonParams common_params(primary_font);
+    internal::TextRunHarfBuzz::FontParams font_params(primary_font);
     run_range.set_start(run_break);
-    common_params.italic = style.style(ITALIC);
-    common_params.baseline_type = style.baseline();
-    common_params.font_size = style.font_size_override();
-    common_params.strike = style.style(STRIKE);
-    common_params.underline = style.style(UNDERLINE);
-    common_params.heavy_underline = style.style(HEAVY_UNDERLINE);
-    common_params.weight = style.weight();
+    font_params.italic = style.style(ITALIC);
+    font_params.baseline_type = style.baseline();
+    font_params.font_size = style.font_size_override();
+    font_params.strike = style.style(STRIKE);
+    font_params.underline = style.style(UNDERLINE);
+    font_params.heavy_underline = style.style(HEAVY_UNDERLINE);
+    font_params.weight = style.weight();
     int32_t script_item_break = 0;
     bidi_iterator.GetLogicalRun(run_break, &script_item_break,
-                                &common_params.level);
+                                &font_params.level);
     CHECK_GT(static_cast<size_t>(script_item_break), run_break);
-    ApplyForcedDirection(&common_params.level);
+    ApplyForcedDirection(&font_params.level);
     // Odd BiDi embedding levels correspond to RTL runs.
-    common_params.is_rtl = (common_params.level % 2) == 1;
+    font_params.is_rtl = (font_params.level % 2) == 1;
     // Find the length and script of this script run.
     script_item_break =
         ScriptInterval(text, run_break, script_item_break - run_break,
-                       &common_params.script) +
+                       &font_params.script) +
         run_break;
 
     // Find the next break and advance the iterators as needed.
@@ -1766,7 +1770,7 @@
 
     auto run = std::make_unique<internal::TextRunHarfBuzz>(
         font_list().GetPrimaryFont());
-    (*out_commonized_run_map)[common_params].push_back(run.get());
+    (*out_commonized_run_map)[font_params].push_back(run.get());
     run->range = run_range;
     out_run_list->Add(std::move(run));
   }
@@ -1777,7 +1781,7 @@
 
 void RenderTextHarfBuzz::ShapeRuns(
     const base::string16& text,
-    const internal::TextRunHarfBuzz::CommonParams& common_params,
+    const internal::TextRunHarfBuzz::FontParams& font_params,
     std::vector<internal::TextRunHarfBuzz*> runs) {
   TRACE_EVENT1("ui", "RenderTextHarfBuzz::ShapeRuns", "run_count", runs.size());
 
@@ -1785,10 +1789,10 @@
   Font best_font(primary_font);
 
   for (const Font& font : font_list().GetFonts()) {
-    internal::TextRunHarfBuzz::CommonParams test_common_params = common_params;
-    if (test_common_params.SetFontAndRenderParams(font,
-                                                  font.GetFontRenderParams())) {
-      ShapeRunsWithFont(text, test_common_params, &runs);
+    internal::TextRunHarfBuzz::FontParams test_font_params = font_params;
+    if (test_font_params.SetFontAndRenderParams(font,
+                                                font.GetFontRenderParams())) {
+      ShapeRunsWithFont(text, test_font_params, &runs);
     }
     if (runs.empty())
       return;
@@ -1802,10 +1806,10 @@
   if (GetFallbackFont(primary_font, run_text, runs.front()->range.length(),
                       &fallback_font)) {
     preferred_fallback_family = fallback_font.GetFontName();
-    internal::TextRunHarfBuzz::CommonParams test_common_params = common_params;
-    if (test_common_params.SetFontAndRenderParams(
+    internal::TextRunHarfBuzz::FontParams test_font_params = font_params;
+    if (test_font_params.SetFontAndRenderParams(
             fallback_font, fallback_font.GetFontRenderParams())) {
-      ShapeRunsWithFont(text, test_common_params, &runs);
+      ShapeRunsWithFont(text, test_font_params, &runs);
     }
     if (runs.empty())
       return;
@@ -1854,13 +1858,12 @@
 
     FontRenderParamsQuery query;
     query.families.push_back(font_name);
-    query.pixel_size = common_params.font_size;
-    query.style = common_params.italic ? Font::ITALIC : 0;
+    query.pixel_size = font_params.font_size;
+    query.style = font_params.italic ? Font::ITALIC : 0;
     FontRenderParams fallback_render_params = GetFontRenderParams(query, NULL);
-    internal::TextRunHarfBuzz::CommonParams test_common_params = common_params;
-    if (test_common_params.SetFontAndRenderParams(font,
-                                                  fallback_render_params)) {
-      ShapeRunsWithFont(text, test_common_params, &runs);
+    internal::TextRunHarfBuzz::FontParams test_font_params = font_params;
+    if (test_font_params.SetFontAndRenderParams(font, fallback_render_params)) {
+      ShapeRunsWithFont(text, test_font_params, &runs);
     }
     if (runs.empty())
       return;
@@ -1876,7 +1879,7 @@
 
 void RenderTextHarfBuzz::ShapeRunsWithFont(
     const base::string16& text,
-    const internal::TextRunHarfBuzz::CommonParams& common_params,
+    const internal::TextRunHarfBuzz::FontParams& font_params,
     std::vector<internal::TextRunHarfBuzz*>* in_out_runs) {
   // ShapeRunWithFont can be extremely slow, so use cached results if possible.
   // Only do this on the UI thread, to avoid synchronization overhead (and
@@ -1892,12 +1895,12 @@
                          run->range.length() <= kMaxRunLengthToCache;
     bool found_in_cache = false;
     const internal::ShapeRunWithFontInput cache_key(
-        text, common_params, run->range, obscured(), glyph_width_for_test_,
+        text, font_params, run->range, obscured(), glyph_width_for_test_,
         glyph_spacing(), subpixel_rendering_suppressed());
     if (can_use_cache) {
       auto found = cache.get()->Get(cache_key);
       if (found != cache.get()->end()) {
-        run->UpdateCommonParamsAndShape(common_params, found->second);
+        run->UpdateFontParamsAndShape(font_params, found->second);
         found_in_cache = true;
       }
     }
@@ -1908,7 +1911,7 @@
     if (!found_in_cache) {
       internal::TextRunHarfBuzz::ShapeOutput output;
       ShapeRunWithFont(cache_key, &output);
-      run->UpdateCommonParamsAndShape(common_params, output);
+      run->UpdateFontParamsAndShape(font_params, output);
       if (can_use_cache)
         cache.get()->Put(cache_key, output);
     }
@@ -1973,18 +1976,18 @@
 
     if (!intersection.is_empty()) {
       int style = Font::NORMAL;
-      if (run.common.italic)
+      if (run.font_params.italic)
         style |= Font::ITALIC;
-      if (run.common.underline || run.common.heavy_underline)
+      if (run.font_params.underline || run.font_params.heavy_underline)
         style |= Font::UNDERLINE;
 
       // Get range relative to the decorated text.
       DecoratedText::RangedAttribute attribute(
           Range(intersection.start() - range.GetMin(),
                 intersection.end() - range.GetMin()),
-          run.common.font.Derive(0, style, run.common.weight));
+          run.font_params.font.Derive(0, style, run.font_params.weight));
 
-      attribute.strike = run.common.strike;
+      attribute.strike = run.font_params.strike;
       decorated_text->attributes.push_back(attribute);
     }
   }
diff --git a/ui/gfx/render_text_harfbuzz.h b/ui/gfx/render_text_harfbuzz.h
index f87b5e0..46ff10e5 100644
--- a/ui/gfx/render_text_harfbuzz.h
+++ b/ui/gfx/render_text_harfbuzz.h
@@ -69,16 +69,16 @@
   // text-space (0 corresponds to |GetDisplayText()[0]|).
   SkScalar GetGlyphWidthForCharRange(const Range& char_range) const;
 
-  // Parameters that may be common to multiple text runs within a text run
+  // Font parameters that may be common to multiple text runs within a text run
   // list.
-  struct GFX_EXPORT CommonParams {
+  struct GFX_EXPORT FontParams {
     // The default constructor for Font is expensive, so always require that a
     // Font be provided.
-    explicit CommonParams(const Font& template_font);
-    ~CommonParams();
-    CommonParams(const CommonParams& other);
-    CommonParams& operator=(const CommonParams& other);
-    bool operator==(const CommonParams& other) const;
+    explicit FontParams(const Font& template_font);
+    ~FontParams();
+    FontParams(const FontParams& other);
+    FontParams& operator=(const FontParams& other);
+    bool operator==(const FontParams& other) const;
 
     // Populate |render_params|, |font_size| and |baseline_offset| based on
     // |font|.
@@ -90,7 +90,7 @@
                                 const FontRenderParams& render_params);
 
     struct Hash {
-      size_t operator()(const CommonParams& key) const;
+      size_t operator()(const FontParams& key) const;
     };
 
     Font font;
@@ -131,12 +131,12 @@
   };
 
   // If |new_shape.missing_glyph_count| is less than that of |shape|, set
-  // |common| and |shape| to the specified values.
-  void UpdateCommonParamsAndShape(const CommonParams& new_common_params,
-                                  const ShapeOutput& new_shape);
+  // |font_params| and |shape| to the specified values.
+  void UpdateFontParamsAndShape(const FontParams& new_font_params,
+                                const ShapeOutput& new_shape);
 
   Range range;
-  CommonParams common;
+  FontParams font_params;
   ShapeOutput shape;
   float preceding_run_widths = 0.0;
 
@@ -254,35 +254,34 @@
       const internal::TextRunHarfBuzz* run);
 
   using CommonizedRunsMap =
-      std::unordered_map<internal::TextRunHarfBuzz::CommonParams,
+      std::unordered_map<internal::TextRunHarfBuzz::FontParams,
                          std::vector<internal::TextRunHarfBuzz*>,
-                         internal::TextRunHarfBuzz::CommonParams::Hash>;
+                         internal::TextRunHarfBuzz::FontParams::Hash>;
 
   // Break the text into logical runs in |out_run_list|. Populate
   // |out_commonized_run_map| such that each run is present in the vector
-  // corresponding to its CommonParams.
+  // corresponding to its FontParams.
   void ItemizeTextToRuns(const base::string16& string,
                          internal::TextRunList* out_run_list,
                          CommonizedRunsMap* out_commonized_run_map);
 
   // Shape the glyphs needed for each run in |runs| within |text|. This method
-  // will apply a number of fonts to |base_common_params| and assign to each
-  // run's CommonParams and ShapeOutput the parameters and resulting shape that
+  // will apply a number of fonts to |base_font_params| and assign to each
+  // run's FontParams and ShapeOutput the parameters and resulting shape that
   // had the smallest number of missing glyphs.
-  void ShapeRuns(
-      const base::string16& text,
-      const internal::TextRunHarfBuzz::CommonParams& base_common_params,
-      std::vector<internal::TextRunHarfBuzz*> runs);
+  void ShapeRuns(const base::string16& text,
+                 const internal::TextRunHarfBuzz::FontParams& base_font_params,
+                 std::vector<internal::TextRunHarfBuzz*> runs);
 
   // Shape the glyphs for |in_out_runs| within |text| using the parameters
-  // specified by |common_params|. If, for any run in |*in_out_runs|, the
+  // specified by |font_params|. If, for any run in |*in_out_runs|, the
   // resulting shaping has fewer missing glyphs than the existing shape, then
-  // write |common_params| and the resulting ShapeOutput to that run. Remove all
+  // write |font_params| and the resulting ShapeOutput to that run. Remove all
   // runs with no missing glyphs from |in_out_runs| (the caller, ShapeRuns, will
   // terminate when no runs with missing glyphs remain).
   void ShapeRunsWithFont(
       const base::string16& text,
-      const internal::TextRunHarfBuzz::CommonParams& base_common_params,
+      const internal::TextRunHarfBuzz::FontParams& font_params,
       std::vector<internal::TextRunHarfBuzz*>* in_out_runs);
 
   // Itemize |text| into runs in |out_run_list|, shape the runs, and populate
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 4981554..6b63ba258 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -411,7 +411,7 @@
       const internal::TextRunHarfBuzz& run = *run_list->runs()[logical_index];
       if (run.range.length() == 1) {
         result.append(base::StringPrintf("[%d]", run.range.start()));
-      } else if (run.common.is_rtl) {
+      } else if (run.font_params.is_rtl) {
         result.append(base::StringPrintf("[%d<-%d]", run.range.end() - 1,
                                          run.range.start()));
       } else {
@@ -553,12 +553,12 @@
                         const Font& font,
                         const FontRenderParams& render_params,
                         internal::TextRunHarfBuzz* run) {
-    internal::TextRunHarfBuzz::CommonParams common_params = run->common;
-    common_params.ComputeRenderParamsFontSizeAndBaselineOffset();
-    common_params.SetFontAndRenderParams(font, render_params);
+    internal::TextRunHarfBuzz::FontParams font_params = run->font_params;
+    font_params.ComputeRenderParamsFontSizeAndBaselineOffset();
+    font_params.SetFontAndRenderParams(font, render_params);
     run->shape.missing_glyph_count = static_cast<size_t>(-1);
     std::vector<internal::TextRunHarfBuzz*> runs = {run};
-    GetRenderTextHarfBuzz()->ShapeRunsWithFont(text, common_params, &runs);
+    GetRenderTextHarfBuzz()->ShapeRunsWithFont(text, font_params, &runs);
     return runs.empty();
   }
 
@@ -3886,7 +3886,7 @@
   for (size_t i = 0; i < arraysize(cases); ++i) {
     std::copy(cases[i].glyph_to_char, cases[i].glyph_to_char + 4,
               run.shape.glyph_to_char.begin());
-    run.common.is_rtl = cases[i].is_rtl;
+    run.font_params.is_rtl = cases[i].is_rtl;
 
     for (size_t j = 0; j < 4; ++j) {
       SCOPED_TRACE(base::StringPrintf("Case %" PRIuS ", char %" PRIuS, i, j));
@@ -3985,7 +3985,7 @@
   for (size_t i = 0; i < arraysize(cases); ++i) {
     std::copy(cases[i].glyph_to_char, cases[i].glyph_to_char + 2,
               run.shape.glyph_to_char.begin());
-    run.common.is_rtl = cases[i].is_rtl;
+    run.font_params.is_rtl = cases[i].is_rtl;
     for (int j = 0; j < 2; ++j)
       run.shape.positions[j].set(j * 10, 0);
 
@@ -4678,7 +4678,9 @@
   // On Linux, whether subpixel AA is supported is determined by the platform
   // FontConfig. Force it into a particular style after computing runs. Other
   // platforms use a known default FontRenderParams from a static local.
-  GetHarfBuzzRunList()->runs()[0]->common.render_params.subpixel_rendering =
+  GetHarfBuzzRunList()
+      ->runs()[0]
+      ->font_params.render_params.subpixel_rendering =
       FontRenderParams::SUBPIXEL_RENDERING_RGB;
   DrawVisualText();
 #endif
@@ -4691,7 +4693,9 @@
   // SUBPIXEL_RENDERING_RGB set above should now take effect. But, after
   // checking, apply the override anyway to be explicit that it is suppressed.
   EXPECT_FALSE(GetRendererPaint().isLCDRenderText());
-  GetHarfBuzzRunList()->runs()[0]->common.render_params.subpixel_rendering =
+  GetHarfBuzzRunList()
+      ->runs()[0]
+      ->font_params.render_params.subpixel_rendering =
       FontRenderParams::SUBPIXEL_RENDERING_RGB;
   DrawVisualText();
 #endif
@@ -5402,10 +5406,12 @@
   const internal::TextRunList* run_list = GetHarfBuzzRunList();
   ASSERT_EQ(3U, run_list->size());
 
-  EXPECT_EQ(default_font_size, run_list->runs()[0].get()->common.font_size);
+  EXPECT_EQ(default_font_size,
+            run_list->runs()[0].get()->font_params.font_size);
   EXPECT_EQ(test_font_size_override,
-            run_list->runs()[1].get()->common.font_size);
-  EXPECT_EQ(default_font_size, run_list->runs()[2].get()->common.font_size);
+            run_list->runs()[1].get()->font_params.font_size);
+  EXPECT_EQ(default_font_size,
+            run_list->runs()[2].get()->font_params.font_size);
 }
 
 // Prefix for test instantiations intentionally left blank since each test
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm
index 1951f09ba..0497adc 100644
--- a/ui/gl/gl_image_io_surface.mm
+++ b/ui/gl/gl_image_io_surface.mm
@@ -418,10 +418,23 @@
         base::trace_event::MemoryDumpManager::kInvalidTracingProcessId;
   }
 
-  auto guid = GetGenericSharedGpuMemoryGUIDForTracing(process_tracing_id,
-                                                      io_surface_id_);
-  pmd->CreateSharedGlobalAllocatorDump(guid);
-  pmd->AddOwnershipEdge(dump->guid(), guid);
+  // Create an edge using the GMB GenericSharedMemoryId if the image is not
+  // anonymous. Otherwise, add another nested node to account for the anonymous
+  // IOSurface.
+  if (io_surface_id_.is_valid()) {
+    auto guid = GetGenericSharedGpuMemoryGUIDForTracing(process_tracing_id,
+                                                        io_surface_id_);
+    pmd->CreateSharedGlobalAllocatorDump(guid);
+    pmd->AddOwnershipEdge(dump->guid(), guid);
+  } else {
+    std::string anonymous_dump_name = dump_name + "/anonymous-iosurface";
+    base::trace_event::MemoryAllocatorDump* anonymous_dump =
+        pmd->CreateAllocatorDump(anonymous_dump_name);
+    anonymous_dump->AddScalar(
+        base::trace_event::MemoryAllocatorDump::kNameSize,
+        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+        static_cast<uint64_t>(size_bytes));
+  }
 }
 
 bool GLImageIOSurface::EmulatingRGB() const {
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index 71dcc39..682070d1 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -130,7 +130,15 @@
   // FBO. Otherwise returns 0.
   virtual unsigned int GetBackingFramebufferObject();
 
-  using SwapCompletionCallback = base::Callback<void(gfx::SwapResult)>;
+  // The SwapCompletionCallback is used to receive notification about the
+  // completion of the swap operation from |SwapBuffersAsync|,
+  // |PostSubBufferAsync|, |CommitOverlayPlanesAsync|, etc. If a null gpu fence
+  // is returned, then the swap is guaranteed to have already completed. If a
+  // non-null gpu fence is returned, then the swap operation may still be in
+  // progress when this callback is invoked, and the signaling of the gpu fence
+  // will mark the completion of the swap operation.
+  using SwapCompletionCallback =
+      base::Callback<void(gfx::SwapResult, std::unique_ptr<gfx::GpuFence>)>;
   // Swaps front and back buffers. This has no effect for off-screen
   // contexts. On some platforms, we want to send SwapBufferAck only after the
   // surface is displayed on screen. The callback can be used to delay sending
diff --git a/ui/gl/gpu_timing.cc b/ui/gl/gpu_timing.cc
index 9ebbc2e3..dbaf95e1 100644
--- a/ui/gl/gpu_timing.cc
+++ b/ui/gl/gpu_timing.cc
@@ -414,7 +414,7 @@
   if (timestamp_bit_count_gl_ == -1) {
     DCHECK(timer_type_ != GPUTiming::kTimerTypeEXT);
     timestamp_bit_count_gl_ = QueryTimestampBits();
-    force_time_elapsed_query_ = (timestamp_bit_count_gl_ == 0);
+    force_time_elapsed_query_ |= (timestamp_bit_count_gl_ == 0);
   }
 
   if (force_time_elapsed_query_) {
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js
index c00909fc..aea9c15 100644
--- a/ui/login/display_manager.js
+++ b/ui/login/display_manager.js
@@ -8,6 +8,7 @@
 
 // TODO(xiyuan): Find a better to share those constants.
 /** @const */ var SCREEN_OOBE_WELCOME = 'connect';
+/** @const */ var SCREEN_OOBE_NETWORK = 'network-selection';
 /** @const */ var SCREEN_OOBE_HID_DETECTION = 'hid-detection';
 /** @const */ var SCREEN_OOBE_EULA = 'eula';
 /** @const */ var SCREEN_OOBE_ENABLE_DEBUGGING = 'debugging';
@@ -137,8 +138,8 @@
    * @const
    */
   var SCREEN_GROUPS = [[
-    SCREEN_OOBE_WELCOME, SCREEN_OOBE_EULA, SCREEN_OOBE_UPDATE,
-    SCREEN_OOBE_AUTO_ENROLLMENT_CHECK
+    SCREEN_OOBE_WELCOME, SCREEN_OOBE_NETWORK, SCREEN_OOBE_EULA,
+    SCREEN_OOBE_UPDATE, SCREEN_OOBE_AUTO_ENROLLMENT_CHECK
   ]];
   /**
    * Group of screens (screen IDs) where factory-reset screen invocation is
@@ -148,6 +149,7 @@
    */
   var RESET_AVAILABLE_SCREEN_GROUP = [
     SCREEN_OOBE_WELCOME,
+    SCREEN_OOBE_NETWORK,
     SCREEN_OOBE_EULA,
     SCREEN_OOBE_UPDATE,
     SCREEN_OOBE_ENROLLMENT,
@@ -180,6 +182,7 @@
   var ENABLE_DEBUGGING_AVAILABLE_SCREEN_GROUP = [
     SCREEN_OOBE_HID_DETECTION,
     SCREEN_OOBE_WELCOME,
+    SCREEN_OOBE_NETWORK,
     SCREEN_OOBE_EULA,
     SCREEN_OOBE_UPDATE,
     SCREEN_TERMS_OF_SERVICE
@@ -450,6 +453,7 @@
           chrome.send('toggleEnrollmentScreen');
         } else if (
             currentStepId == SCREEN_OOBE_WELCOME ||
+            currentStepId == SCREEN_OOBE_NETWORK ||
             currentStepId == SCREEN_OOBE_EULA) {
           // In this case update check will be skipped and OOBE will
           // proceed straight to enrollment screen when EULA is accepted.
diff --git a/ui/ozone/demo/gl_renderer.cc b/ui/ozone/demo/gl_renderer.cc
index 73e3d84..a9aca9f0 100644
--- a/ui/ozone/demo/gl_renderer.cc
+++ b/ui/ozone/demo/gl_renderer.cc
@@ -7,6 +7,7 @@
 #include "base/location.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
+#include "ui/gfx/gpu_fence.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface.h"
@@ -37,7 +38,7 @@
   }
 
   // Schedule the initial render.
-  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK);
+  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK, nullptr);
   return true;
 }
 
@@ -58,12 +59,18 @@
                                base::Bind(&GlRenderer::OnPresentation,
                                           weak_ptr_factory_.GetWeakPtr()));
   } else {
-    PostRenderFrameTask(surface_->SwapBuffers(base::Bind(
-        &GlRenderer::OnPresentation, weak_ptr_factory_.GetWeakPtr())));
+    PostRenderFrameTask(
+        surface_->SwapBuffers(base::Bind(&GlRenderer::OnPresentation,
+                                         weak_ptr_factory_.GetWeakPtr())),
+        nullptr);
   }
 }
 
-void GlRenderer::PostRenderFrameTask(gfx::SwapResult result) {
+void GlRenderer::PostRenderFrameTask(gfx::SwapResult result,
+                                     std::unique_ptr<gfx::GpuFence> gpu_fence) {
+  if (gpu_fence)
+    gpu_fence->Wait();
+
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&GlRenderer::RenderFrame, weak_ptr_factory_.GetWeakPtr()));
diff --git a/ui/ozone/demo/gl_renderer.h b/ui/ozone/demo/gl_renderer.h
index 34bb9d0..9837b12 100644
--- a/ui/ozone/demo/gl_renderer.h
+++ b/ui/ozone/demo/gl_renderer.h
@@ -12,6 +12,7 @@
 #include "ui/ozone/demo/renderer_base.h"
 
 namespace gfx {
+class GpuFence;
 struct PresentationFeedback;
 }  // namespace gfx
 
@@ -34,7 +35,8 @@
 
  private:
   void RenderFrame();
-  void PostRenderFrameTask(gfx::SwapResult result);
+  void PostRenderFrameTask(gfx::SwapResult result,
+                           std::unique_ptr<gfx::GpuFence> gpu_fence);
   void OnPresentation(const gfx::PresentationFeedback& feedback);
 
   scoped_refptr<gl::GLSurface> surface_;
diff --git a/ui/ozone/demo/skia/skia_gl_renderer.cc b/ui/ozone/demo/skia/skia_gl_renderer.cc
index 681f673..9bbb1357 100644
--- a/ui/ozone/demo/skia/skia_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_gl_renderer.cc
@@ -13,6 +13,7 @@
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "ui/gfx/gpu_fence.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_implementation.h"
@@ -71,7 +72,7 @@
   gr_context_ = GrContext::MakeGL(std::move(native_interface), options);
   DCHECK(gr_context_);
 
-  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK);
+  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK, nullptr);
   return true;
 }
 
@@ -111,12 +112,19 @@
         base::BindRepeating(&SkiaGlRenderer::OnPresentation,
                             weak_ptr_factory_.GetWeakPtr()));
   } else {
-    PostRenderFrameTask(gl_surface_->SwapBuffers(base::BindRepeating(
-        &SkiaGlRenderer::OnPresentation, weak_ptr_factory_.GetWeakPtr())));
+    PostRenderFrameTask(
+        gl_surface_->SwapBuffers(base::BindRepeating(
+            &SkiaGlRenderer::OnPresentation, weak_ptr_factory_.GetWeakPtr())),
+        nullptr);
   }
 }
 
-void SkiaGlRenderer::PostRenderFrameTask(gfx::SwapResult result) {
+void SkiaGlRenderer::PostRenderFrameTask(
+    gfx::SwapResult result,
+    std::unique_ptr<gfx::GpuFence> gpu_fence) {
+  if (gpu_fence)
+    gpu_fence->Wait();
+
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindRepeating(&SkiaGlRenderer::RenderFrame,
                                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/ui/ozone/demo/skia/skia_gl_renderer.h b/ui/ozone/demo/skia/skia_gl_renderer.h
index 8e9613a..7bb6772 100644
--- a/ui/ozone/demo/skia/skia_gl_renderer.h
+++ b/ui/ozone/demo/skia/skia_gl_renderer.h
@@ -19,6 +19,7 @@
 #include "ui/ozone/demo/renderer_base.h"
 
 namespace gfx {
+class GpuFence;
 struct PresentationFeedback;
 }  // namespace gfx
 
@@ -42,7 +43,8 @@
 
  protected:
   virtual void RenderFrame();
-  virtual void PostRenderFrameTask(gfx::SwapResult result);
+  virtual void PostRenderFrameTask(gfx::SwapResult result,
+                                   std::unique_ptr<gfx::GpuFence>);
 
   void Draw(SkCanvas* canvas, float fraction);
   void StartDDLRenderThreadIfNecessary(SkSurface* sk_surface);
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index c418c58d..b609232 100644
--- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -264,7 +264,9 @@
       base::DoNothing());
 }
 
-void SurfacelessSkiaGlRenderer::PostRenderFrameTask(gfx::SwapResult result) {
+void SurfacelessSkiaGlRenderer::PostRenderFrameTask(
+    gfx::SwapResult result,
+    std::unique_ptr<gfx::GpuFence> gpu_fence) {
   switch (result) {
     case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
       for (size_t i = 0; i < arraysize(buffers_); ++i) {
@@ -275,7 +277,7 @@
       }
       FALLTHROUGH;  // We want to render a new frame anyways.
     case gfx::SwapResult::SWAP_ACK:
-      SkiaGlRenderer::PostRenderFrameTask(result);
+      SkiaGlRenderer::PostRenderFrameTask(result, std::move(gpu_fence));
       break;
     case gfx::SwapResult::SWAP_FAILED:
       LOG(FATAL) << "Failed to swap buffers";
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h
index a34f4da2..a569273 100644
--- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h
+++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h
@@ -27,7 +27,8 @@
  private:
   // SkiaGlRenderer:
   void RenderFrame() override;
-  void PostRenderFrameTask(gfx::SwapResult result) override;
+  void PostRenderFrameTask(gfx::SwapResult result,
+                           std::unique_ptr<gfx::GpuFence>) override;
 
   class BufferWrapper;
 
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc
index 53188cd4..94794ba 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -191,7 +191,7 @@
     surface_->SetUsePlaneGpuFences();
 
   // Schedule the initial render.
-  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK);
+  PostRenderFrameTask(gfx::SwapResult::SWAP_ACK, nullptr);
   return true;
 }
 
@@ -271,7 +271,12 @@
       base::Bind([](const gfx::PresentationFeedback&) {}));
 }
 
-void SurfacelessGlRenderer::PostRenderFrameTask(gfx::SwapResult result) {
+void SurfacelessGlRenderer::PostRenderFrameTask(
+    gfx::SwapResult result,
+    std::unique_ptr<gfx::GpuFence> gpu_fence) {
+  if (gpu_fence)
+    gpu_fence->Wait();
+
   switch (result) {
     case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
       for (size_t i = 0; i < base::size(buffers_); ++i) {
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.h b/ui/ozone/demo/surfaceless_gl_renderer.h
index 8fee49c..9029a92 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.h
+++ b/ui/ozone/demo/surfaceless_gl_renderer.h
@@ -30,7 +30,8 @@
 
  private:
   void RenderFrame();
-  void PostRenderFrameTask(gfx::SwapResult result);
+  void PostRenderFrameTask(gfx::SwapResult result,
+                           std::unique_ptr<gfx::GpuFence> gpu_fence);
   void OnPresentation(const gfx::PresentationFeedback& feedback);
 
   class BufferWrapper {
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc
index be4c02c..8588a55 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc
@@ -69,7 +69,7 @@
           widget(), 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE,
           gfx::Rect(GetSize()), gfx::RectF(1, 1), /* enable_blend */ false,
           /* gpu_fence */ nullptr)) {
-    completion_callback.Run(gfx::SwapResult::SWAP_FAILED);
+    completion_callback.Run(gfx::SwapResult::SWAP_FAILED, nullptr);
     // Notify the caller, the buffer is never presented on a screen.
     presentation_callback.Run(gfx::PresentationFeedback::Failure());
     return;
diff --git a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 281c3736..4c0ff77 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -115,7 +115,7 @@
   TRACE_EVENT0("drm", "GbmSurfaceless::SwapBuffersAsync");
   // If last swap failed, don't try to schedule new ones.
   if (!last_swap_buffers_result_) {
-    completion_callback.Run(gfx::SwapResult::SWAP_FAILED);
+    completion_callback.Run(gfx::SwapResult::SWAP_FAILED, nullptr);
     // Notify the caller, the buffer is never presented on a screen.
     presentation_callback.Run(gfx::PresentationFeedback::Failure());
     return;
@@ -150,7 +150,7 @@
   // implemented in GL drivers.
   EGLSyncKHR fence = InsertFence(has_implicit_external_sync_);
   if (!fence) {
-    completion_callback.Run(gfx::SwapResult::SWAP_FAILED);
+    completion_callback.Run(gfx::SwapResult::SWAP_FAILED, nullptr);
     // Notify the caller, the buffer is never presented on a screen.
     presentation_callback.Run(gfx::PresentationFeedback::Failure());
     return;
@@ -279,7 +279,7 @@
   submitted_frame_->overlays.clear();
 
   gfx::SwapResult result = submitted_frame_->swap_result;
-  std::move(submitted_frame_->completion_callback).Run(result);
+  std::move(submitted_frame_->completion_callback).Run(result, nullptr);
   std::move(submitted_frame_->presentation_callback).Run(feedback);
   submitted_frame_.reset();
 
diff --git a/ui/views/view_properties.cc b/ui/views/view_properties.cc
index 994fe8c..40547e6e 100644
--- a/ui/views/view_properties.cc
+++ b/ui/views/view_properties.cc
@@ -9,8 +9,10 @@
 #include "ui/views/bubble/bubble_dialog_delegate.h"
 
 #if !defined(USE_AURA)
-// aura_constants.cc also declared the bool ClassProperty type.
+// aura_constants.cc also declared the bool and int[32_t]
+// ClassProperty type.
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, bool);
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, int);
 #endif
 
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Insets*);