diff --git a/DEPS b/DEPS
index 938c8ad..0114232 100644
--- a/DEPS
+++ b/DEPS
@@ -41,6 +41,10 @@
   # purposes.
   'checkout_configuration': 'default',
 
+  # By default, do not check out android sdk sources. This can be overridden
+  # e.g. with custom_vars.
+  'checkout_android_sdk_sources': False,
+
   # Check out and download nacl by default. This can be disabled e.g. with
   # custom_vars.
   'checkout_nacl': True,
@@ -102,11 +106,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '1119ce641315de5b76b71df390444f5810319d19',
+  'swiftshader_revision': '9151a3c4279123986fa2fa02a3e094d5da2d874d',
   # 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': '87b67f842fe53c3d5db553b6c1965f4588fecbfc',
+  'pdfium_revision': 'e6d4559a1b6c2eb0eb433b9db70745e3be3d8465',
   # 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.
@@ -142,7 +146,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': '60096370137d978b562ac9589eb417c329461989',
+  'catapult_revision': '19b3dfed02a8f360cf04e8758eeb4696a682b2a2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -159,6 +163,34 @@
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
   'feed_revision': '3a782b5dac6c8f2f927613d3f37b8cad72f934b2',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_build-tools_version
+  # and whatever else without interference from each other.
+  'android_sdk_build-tools_version': 'version:27.0.3-cr0',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_emulator_version
+  # and whatever else without interference from each other.
+  'android_sdk_emulator_version': 'version:27.1.12-cr0',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_extras_version
+  # and whatever else without interference from each other.
+  'android_sdk_extras_version': 'version:47.0.0-cr0',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_platform-tools_version
+  # and whatever else without interference from each other.
+  'android_sdk_platform-tools_version': 'version:27.0.1-cr0',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_platforms_version
+  # and whatever else without interference from each other.
+  'android_sdk_platforms_version': 'version:android-27-cr0',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_sources_version
+  # and whatever else without interference from each other.
+  'android_sdk_sources_version': 'version:android-27-cr1',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling android_sdk_tools_version
+  # and whatever else without interference from each other.
+  'android_sdk_tools_version': 'version:26.1.1-cr0',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -332,6 +364,48 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/android_sdk/public': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_sdk/public/build-tools',
+              'version': Var('android_sdk_build-tools_version'),
+          },
+          {
+              'package': 'chromium/third_party/android_sdk/public/emulator',
+              'version': Var('android_sdk_emulator_version'),
+          },
+          {
+              'package': 'chromium/third_party/android_sdk/public/extras',
+              'version': Var('android_sdk_extras_version'),
+          },
+          {
+              'package': 'chromium/third_party/android_sdk/public/platform-tools',
+              'version': Var('android_sdk_platform-tools_version'),
+          },
+          {
+              'package': 'chromium/third_party/android_sdk/public/platforms',
+              'version': Var('android_sdk_platforms_version'),
+          },
+          {
+              'package': 'chromium/third_party/android_sdk/public/tools',
+              'version': Var('android_sdk_tools_version'),
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/android_sdk/sources': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_sdk/sources',
+              'version': Var('android_sdk_sources_version'),
+          },
+      ],
+      'condition': 'checkout_android_sdk_sources',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/angle':
     Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
 
@@ -436,7 +510,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7e9e2c82bdf1a5d2cb0374841777b732cf940348',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b1c21a5af2ec8d77cd9f221473d2b724534b904e',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -471,7 +545,7 @@
   },
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '272be0ac4cae282d827732759c300fd2c5077827',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '5af686b3cfa25ee98bb9a88008ff04257d560764',
 
   'src/third_party/flac':
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '7d0f5b3a173ffe98db08057d1f52b7787569e0a6',
@@ -664,7 +738,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'd636fe53af525c30f3bbd7224e7e56d447d0eb3d',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'be5df6080154e58db88fa3640e127efd18c04bde',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'b03c65468b06d097f27235d93d76bfc45f490ede',
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
index c611d18..e214471 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -80,4 +80,22 @@
     // WebResourceRequest.isRedirect
     public static final String WEB_RESOURCE_REQUEST_IS_REDIRECT =
             "WEB_RESOURCE_REQUEST_IS_REDIRECT";
+
+    // WebResourceError.getDescription
+    public static final String WEB_RESOURCE_ERROR_GET_DESCRIPTION =
+            "WEB_RESOURCE_ERROR_GET_DESCRIPTION";
+
+    // WebResourceError.getErrorCode
+    public static final String WEB_RESOURCE_ERROR_GET_CODE = "WEB_RESOURCE_ERROR_GET_CODE";
+
+    // SafeBrowsingResponse.backToSafety
+    public static final String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY =
+            "SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY";
+
+    // SafeBrowsingResponse.proceed
+    public static final String SAFE_BROWSING_RESPONSE_PROCEED = "SAFE_BROWSING_RESPONSE_PROCEED";
+
+    // SafeBrowsingResponse.showInterstitial
+    public static final String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL =
+            "SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL";
 }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
index c684b4c..22972b6 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -49,7 +49,12 @@
                     Features.RECEIVE_HTTP_ERROR,
                     Features.SAFE_BROWSING_HIT,
                     Features.SHOULD_OVERRIDE_WITH_REDIRECTS,
-                    Features.WEB_RESOURCE_REQUEST_IS_REDIRECT
+                    Features.WEB_RESOURCE_REQUEST_IS_REDIRECT,
+                    Features.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
+                    Features.WEB_RESOURCE_ERROR_GET_CODE,
+                    Features.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
+                    Features.SAFE_BROWSING_RESPONSE_PROCEED,
+                    Features.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL
             };
     // clang-format on
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 5f95b9a..12274a7 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -308,6 +308,8 @@
     "login/ui/login_data_dispatcher.h",
     "login/ui/login_detachable_base_model.cc",
     "login/ui/login_detachable_base_model.h",
+    "login/ui/login_expanded_public_account_view.cc",
+    "login/ui/login_expanded_public_account_view.h",
     "login/ui/login_password_view.cc",
     "login/ui/login_password_view.h",
     "login/ui/login_pin_view.cc",
@@ -787,6 +789,7 @@
     "system/unified/collapse_button.h",
     "system/unified/feature_pod_button.cc",
     "system/unified/feature_pod_button.h",
+    "system/unified/feature_pod_controller_base.cc",
     "system/unified/feature_pod_controller_base.h",
     "system/unified/feature_pods_container_view.cc",
     "system/unified/feature_pods_container_view.h",
@@ -1522,6 +1525,7 @@
     "login/ui/lock_window_unittest.cc",
     "login/ui/login_auth_user_view_unittest.cc",
     "login/ui/login_bubble_unittest.cc",
+    "login/ui/login_expanded_public_account_view_unittest.cc",
     "login/ui/login_keyboard_test_base.cc",
     "login/ui/login_keyboard_test_base.h",
     "login/ui/login_password_view_test.cc",
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index 8838299..51b265b 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -9,170 +9,6 @@
 
 namespace ash {
 
-const int kDebugModifier =
-    ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN;
-
-const AcceleratorData kAcceleratorData[] = {
-    {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME},
-    {false, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME},
-    {true, ui::VKEY_TAB, ui::EF_ALT_DOWN, CYCLE_FORWARD_MRU},
-    {true, ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
-     CYCLE_BACKWARD_MRU},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE, TOGGLE_OVERVIEW},
-    {true, ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, TOGGLE_APP_LIST},
-    {true, ui::VKEY_WLAN, ui::EF_NONE, TOGGLE_WIFI},
-    {true, ui::VKEY_KBD_BRIGHTNESS_DOWN, ui::EF_NONE, KEYBOARD_BRIGHTNESS_DOWN},
-    {true, ui::VKEY_KBD_BRIGHTNESS_UP, ui::EF_NONE, KEYBOARD_BRIGHTNESS_UP},
-    // Maximize button.
-    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_CONTROL_DOWN, TOGGLE_MIRROR_MODE},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_ALT_DOWN, SWAP_PRIMARY_DISPLAY},
-    // Cycle windows button.
-    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN, TAKE_SCREENSHOT},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-     TAKE_PARTIAL_SCREENSHOT},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
-     TAKE_WINDOW_SCREENSHOT},
-    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE, BRIGHTNESS_DOWN},
-    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_ALT_DOWN, KEYBOARD_BRIGHTNESS_DOWN},
-    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE, BRIGHTNESS_UP},
-    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_ALT_DOWN, KEYBOARD_BRIGHTNESS_UP},
-    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     MAGNIFIER_ZOOM_OUT},
-    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     MAGNIFIER_ZOOM_IN},
-    {true, ui::VKEY_L, ui::EF_COMMAND_DOWN, LOCK_SCREEN},
-    {true, ui::VKEY_L, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN, SUSPEND},
-    // The lock key on Chrome OS keyboards produces F13 scancodes.
-    {true, ui::VKEY_F13, ui::EF_NONE, LOCK_PRESSED},
-    {false, ui::VKEY_F13, ui::EF_NONE, LOCK_RELEASED},
-    // Generic keyboards can use VKEY_SLEEP to mimic ChromeOS keyboard's lock
-    // key.
-    {true, ui::VKEY_SLEEP, ui::EF_NONE, LOCK_PRESSED},
-    {false, ui::VKEY_SLEEP, ui::EF_NONE, LOCK_RELEASED},
-    {true, ui::VKEY_POWER, ui::EF_NONE, POWER_PRESSED},
-    {false, ui::VKEY_POWER, ui::EF_NONE, POWER_RELEASED},
-    {true, ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FILE_MANAGER},
-    {true, ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN, OPEN_GET_HELP},
-    {true, ui::VKEY_OEM_2, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-     OPEN_GET_HELP},
-    {true, ui::VKEY_T, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, OPEN_CROSH},
-    {true, ui::VKEY_I, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     TOUCH_HUD_MODE_CHANGE},
-    {true, ui::VKEY_I,
-     ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN,
-     TOUCH_HUD_CLEAR},
-    {true, ui::VKEY_H, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
-     TOGGLE_HIGH_CONTRAST},
-    {true, ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     TOGGLE_SPOKEN_FEEDBACK},
-    {true, ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN,
-     TOGGLE_DICTATION},
-    {true, ui::VKEY_OEM_COMMA, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     SWITCH_TO_PREVIOUS_USER},
-    {true, ui::VKEY_OEM_PERIOD, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     SWITCH_TO_NEXT_USER},
-    // Single shift release turns off caps lock.
-    {false, ui::VKEY_LSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
-    {false, ui::VKEY_SHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
-    {false, ui::VKEY_RSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
-    // Accelerators to toggle Caps Lock.
-    // The following is triggered when Search is released while Alt is still
-    // down. The key_code here is LWIN (for search) and Alt is a modifier.
-    {false, ui::VKEY_LWIN, ui::EF_ALT_DOWN, TOGGLE_CAPS_LOCK},
-    // The following is triggered when Alt is released while search is still
-    // down. The key_code here is MENU (for Alt) and Search is a modifier
-    // (EF_COMMAND_DOWN is used for Search as a modifier).
-    {false, ui::VKEY_MENU, ui::EF_COMMAND_DOWN, TOGGLE_CAPS_LOCK},
-    {true, ui::VKEY_VOLUME_MUTE, ui::EF_NONE, VOLUME_MUTE},
-    {true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN},
-    {true, ui::VKEY_VOLUME_UP, ui::EF_NONE, VOLUME_UP},
-    {true, ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, SHOW_TASK_MANAGER},
-    {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, NEXT_IME},
-    {true, ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FEEDBACK_PAGE},
-    {true, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT},
-    {true, ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-     NEW_INCOGNITO_WINDOW},
-    {true, ui::VKEY_N, ui::EF_CONTROL_DOWN, NEW_WINDOW},
-    {true, ui::VKEY_T, ui::EF_CONTROL_DOWN, NEW_TAB},
-    {true, ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
-     SCALE_UI_UP},
-    {true, ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
-     SCALE_UI_DOWN},
-    {true, ui::VKEY_0, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, SCALE_UI_RESET},
-    {true, ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
-     ROTATE_SCREEN},
-    {true, ui::VKEY_BROWSER_REFRESH,
-     ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ROTATE_WINDOW},
-    {true, ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, RESTORE_TAB},
-    {true, ui::VKEY_PRINT, ui::EF_NONE, TAKE_SCREENSHOT},
-    // On Chrome OS, Search key is mapped to LWIN. The Search key binding should
-    // act on release instead of press when using Search as a modifier key for
-    // extended keyboard shortcuts.
-    {false, ui::VKEY_LWIN, ui::EF_NONE, TOGGLE_APP_LIST},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE, TOGGLE_FULLSCREEN},
-    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_SHIFT_DOWN, TOGGLE_FULLSCREEN},
-    {true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN, UNPIN},
-    {true, ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, FOCUS_SHELF},
-    {true, ui::VKEY_HELP, ui::EF_NONE, SHOW_KEYBOARD_OVERLAY},
-    {true, ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     SHOW_KEYBOARD_OVERLAY},
-    {true, ui::VKEY_OEM_2,
-     ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
-     SHOW_KEYBOARD_OVERLAY},
-    {true, ui::VKEY_F14, ui::EF_NONE, SHOW_KEYBOARD_OVERLAY},
-    {true, ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
-     TOGGLE_MESSAGE_CENTER_BUBBLE},
-    {true, ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, SHOW_STYLUS_TOOLS},
-    {true, ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
-     TOGGLE_SYSTEM_TRAY_BUBBLE},
-    // Until we have unified settings and notifications the "hamburger"
-    // key opens quick settings.
-    {true, ui::VKEY_SETTINGS, ui::EF_NONE, TOGGLE_SYSTEM_TRAY_BUBBLE},
-    {true, ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN,
-     SHOW_IME_MENU_BUBBLE},
-    {true, ui::VKEY_1, ui::EF_ALT_DOWN, LAUNCH_APP_0},
-    {true, ui::VKEY_2, ui::EF_ALT_DOWN, LAUNCH_APP_1},
-    {true, ui::VKEY_3, ui::EF_ALT_DOWN, LAUNCH_APP_2},
-    {true, ui::VKEY_4, ui::EF_ALT_DOWN, LAUNCH_APP_3},
-    {true, ui::VKEY_5, ui::EF_ALT_DOWN, LAUNCH_APP_4},
-    {true, ui::VKEY_6, ui::EF_ALT_DOWN, LAUNCH_APP_5},
-    {true, ui::VKEY_7, ui::EF_ALT_DOWN, LAUNCH_APP_6},
-    {true, ui::VKEY_8, ui::EF_ALT_DOWN, LAUNCH_APP_7},
-    {true, ui::VKEY_9, ui::EF_ALT_DOWN, LAUNCH_LAST_APP},
-
-    // Window management shortcuts.
-    {true, ui::VKEY_OEM_4, ui::EF_ALT_DOWN, WINDOW_CYCLE_SNAP_LEFT},
-    {true, ui::VKEY_OEM_6, ui::EF_ALT_DOWN, WINDOW_CYCLE_SNAP_RIGHT},
-    {true, ui::VKEY_OEM_MINUS, ui::EF_ALT_DOWN, WINDOW_MINIMIZE},
-    {true, ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN, TOGGLE_MAXIMIZED},
-    {true, ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
-     WINDOW_POSITION_CENTER},
-    {true, ui::VKEY_BROWSER_FORWARD, ui::EF_CONTROL_DOWN, FOCUS_NEXT_PANE},
-    {true, ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN, FOCUS_PREVIOUS_PANE},
-
-    // Moving active window between displays shortcut.
-    {true, ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
-     MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS},
-
-    // Media Player shortcuts.
-    {true, ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE, MEDIA_NEXT_TRACK},
-    {true, ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE, MEDIA_PLAY_PAUSE},
-    {true, ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE, MEDIA_PREV_TRACK},
-
-    // Voice Interaction shortcuts.
-    {true, ui::VKEY_A, ui::EF_COMMAND_DOWN, START_VOICE_INTERACTION},
-    {true, ui::VKEY_ASSISTANT, ui::EF_NONE, START_VOICE_INTERACTION},
-
-    // Debugging shortcuts that need to be available to end-users in
-    // release builds.
-    {true, ui::VKEY_U, kDebugModifier, PRINT_UI_HIERARCHIES},
-
-    // TODO(yusukes): Handle VKEY_MEDIA_STOP, and
-    // VKEY_MEDIA_LAUNCH_MAIL.
-};
-
-const size_t kAcceleratorDataLength = arraysize(kAcceleratorData);
-
 // Instructions for how to deprecate and replace an Accelerator:
 //
 // 1- Replace the old deprecated accelerator from the above list with the new
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h
index 9ce4ca2e..82278e1c 100644
--- a/ash/accelerators/accelerator_table.h
+++ b/ash/accelerators/accelerator_table.h
@@ -8,11 +8,15 @@
 #include <stddef.h>
 
 #include "ash/ash_export.h"
+#include "ash/public/cpp/accelerators.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
 namespace ash {
 
+// The complete list of Ash accelerators is in ash/public/cpp/accelerators.h.
+// This file mainly keeps track of special categories of accelerator.
+//
 // There are five classes of accelerators in Ash:
 //
 // Ash (OS) reserved:
@@ -48,115 +52,6 @@
 // There are also various restrictions on accelerators allowed at the login
 // screen, when running in "forced app mode" (like a kiosk), etc. See the
 // various kActionsAllowed* below.
-//
-// Please put if/def sections at the end of the bare section and keep the list
-// within each section in alphabetical order.
-enum AcceleratorAction {
-  BRIGHTNESS_DOWN,
-  BRIGHTNESS_UP,
-  CYCLE_BACKWARD_MRU,
-  CYCLE_FORWARD_MRU,
-  DEBUG_PRINT_LAYER_HIERARCHY,
-  DEBUG_PRINT_VIEW_HIERARCHY,
-  DEBUG_PRINT_WINDOW_HIERARCHY,
-  DEBUG_SHOW_TOAST,
-  DEBUG_TOGGLE_DEVICE_SCALE_FACTOR,
-  DEBUG_TOGGLE_SHOW_DEBUG_BORDERS,
-  DEBUG_TOGGLE_SHOW_FPS_COUNTER,
-  DEBUG_TOGGLE_SHOW_PAINT_RECTS,
-  DEBUG_TOGGLE_TOUCH_PAD,
-  DEBUG_TOGGLE_TOUCH_SCREEN,
-  DEBUG_TOGGLE_TABLET_MODE,
-  DEBUG_TOGGLE_WALLPAPER_MODE,
-  DEBUG_TRIGGER_CRASH,  // Intentionally crash the ash process.
-  DEV_ADD_REMOVE_DISPLAY,
-  DEV_TOGGLE_UNIFIED_DESKTOP,
-  DISABLE_CAPS_LOCK,
-  EXIT,
-  FOCUS_NEXT_PANE,
-  FOCUS_PREVIOUS_PANE,
-  FOCUS_SHELF,
-  KEYBOARD_BRIGHTNESS_DOWN,
-  KEYBOARD_BRIGHTNESS_UP,
-  LAUNCH_APP_0,
-  LAUNCH_APP_1,
-  LAUNCH_APP_2,
-  LAUNCH_APP_3,
-  LAUNCH_APP_4,
-  LAUNCH_APP_5,
-  LAUNCH_APP_6,
-  LAUNCH_APP_7,
-  LAUNCH_LAST_APP,
-  LOCK_PRESSED,
-  LOCK_RELEASED,
-  LOCK_SCREEN,
-  MAGNIFIER_ZOOM_IN,
-  MAGNIFIER_ZOOM_OUT,
-  MEDIA_NEXT_TRACK,
-  MEDIA_PLAY_PAUSE,
-  MEDIA_PREV_TRACK,
-  MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS,
-  NEW_INCOGNITO_WINDOW,
-  NEW_TAB,
-  NEW_WINDOW,
-  NEXT_IME,
-  OPEN_CROSH,
-  OPEN_FEEDBACK_PAGE,
-  OPEN_FILE_MANAGER,
-  OPEN_GET_HELP,
-  POWER_PRESSED,
-  POWER_RELEASED,
-  PREVIOUS_IME,
-  PRINT_UI_HIERARCHIES,
-  RESTORE_TAB,
-  ROTATE_SCREEN,
-  ROTATE_WINDOW,
-  SCALE_UI_DOWN,
-  SCALE_UI_RESET,
-  SCALE_UI_UP,
-  SHOW_IME_MENU_BUBBLE,
-  SHOW_KEYBOARD_OVERLAY,
-  SHOW_STYLUS_TOOLS,
-  SHOW_TASK_MANAGER,
-  START_VOICE_INTERACTION,
-  SUSPEND,
-  SWAP_PRIMARY_DISPLAY,
-  SWITCH_IME,  // Switch to another IME depending on the accelerator.
-  SWITCH_TO_NEXT_USER,
-  SWITCH_TO_PREVIOUS_USER,
-  TAKE_PARTIAL_SCREENSHOT,
-  TAKE_SCREENSHOT,
-  TAKE_WINDOW_SCREENSHOT,
-  TOGGLE_APP_LIST,
-  TOGGLE_CAPS_LOCK,
-  TOGGLE_DICTATION,
-  TOGGLE_FULLSCREEN,
-  TOGGLE_HIGH_CONTRAST,
-  TOGGLE_MAXIMIZED,
-  TOGGLE_MESSAGE_CENTER_BUBBLE,
-  TOGGLE_MIRROR_MODE,
-  TOGGLE_OVERVIEW,
-  TOGGLE_SPOKEN_FEEDBACK,
-  TOGGLE_SYSTEM_TRAY_BUBBLE,
-  TOGGLE_WIFI,
-  TOUCH_HUD_CLEAR,
-  TOUCH_HUD_MODE_CHANGE,
-  UNPIN,
-  VOLUME_DOWN,
-  VOLUME_MUTE,
-  VOLUME_UP,
-  WINDOW_CYCLE_SNAP_LEFT,
-  WINDOW_CYCLE_SNAP_RIGHT,
-  WINDOW_MINIMIZE,
-  WINDOW_POSITION_CENTER,
-};
-
-struct AcceleratorData {
-  bool trigger_on_press;
-  ui::KeyboardCode keycode;
-  int modifiers;
-  AcceleratorAction action;
-};
 
 // Gathers the needed data to handle deprecated accelerators.
 struct DeprecatedAcceleratorData {
@@ -190,10 +85,6 @@
   DEPRECATED_USAGE_COUNT,  // Maximum value of this enum for histogram use.
 };
 
-// Accelerators handled by AcceleratorController.
-ASH_EXPORT extern const AcceleratorData kAcceleratorData[];
-ASH_EXPORT extern const size_t kAcceleratorDataLength;
-
 // The list of the deprecated accelerators.
 ASH_EXPORT extern const AcceleratorData kDeprecatedAccelerators[];
 ASH_EXPORT extern const size_t kDeprecatedAcceleratorsLength;
diff --git a/ash/app_list/app_list_presenter_impl.cc b/ash/app_list/app_list_presenter_impl.cc
index ac572bf..98f3131e 100644
--- a/ash/app_list/app_list_presenter_impl.cc
+++ b/ash/app_list/app_list_presenter_impl.cc
@@ -106,8 +106,6 @@
 
   is_visible_ = true;
   RequestPresentationTime(display_id, event_time_stamp);
-  NotifyTargetVisibilityChanged(GetTargetVisibility());
-  NotifyVisibilityChanged(GetTargetVisibility(), display_id);
 
   if (view_) {
     ScheduleAnimation();
@@ -123,6 +121,8 @@
   }
   presenter_delegate_->OnShown(display_id);
   view_delegate_->ViewShown(display_id);
+  NotifyTargetVisibilityChanged(GetTargetVisibility());
+  NotifyVisibilityChanged(GetTargetVisibility(), display_id);
 }
 
 void AppListPresenterImpl::Dismiss(base::TimeTicks event_time_stamp) {
@@ -135,8 +135,6 @@
   is_visible_ = false;
   const int64_t display_id = GetDisplayId();
   RequestPresentationTime(display_id, event_time_stamp);
-  NotifyTargetVisibilityChanged(GetTargetVisibility());
-  NotifyVisibilityChanged(GetTargetVisibility(), display_id);
   // The dismissal may have occurred in response to the app list losing
   // activation. Otherwise, our widget is currently active. When the animation
   // completes we'll hide the widget, changing activation. If a menu is shown
@@ -149,6 +147,8 @@
   view_delegate_->ViewClosing();
   presenter_delegate_->OnDismissed();
   ScheduleAnimation();
+  NotifyTargetVisibilityChanged(GetTargetVisibility());
+  NotifyVisibilityChanged(GetTargetVisibility(), display_id);
   base::RecordAction(base::UserMetricsAction("Launcher_Dismiss"));
 }
 
diff --git a/ash/components/shortcut_viewer/BUILD.gn b/ash/components/shortcut_viewer/BUILD.gn
index 6d7136e..d53553d6 100644
--- a/ash/components/shortcut_viewer/BUILD.gn
+++ b/ash/components/shortcut_viewer/BUILD.gn
@@ -51,6 +51,7 @@
     ":ksv",
     "//ash:test_support_without_content",
     "//testing/gtest",
+    "//ui/events:test_support",
     "//ui/views",
   ]
 }
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
index a388641..5db1b0d 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -24,6 +24,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
+#include "ui/base/accelerators/accelerator.h"
 #include "ui/base/default_style.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -138,12 +139,23 @@
     window->SetProperty(aura::client::kWindowIconKey,
                         new gfx::ImageSkia(*icon));
 
+    g_ksv_view->AddAccelerator(
+        ui::Accelerator(ui::VKEY_W, ui::EF_CONTROL_DOWN));
+
     g_ksv_view->GetWidget()->Show();
     g_ksv_view->search_box_view_->search_box()->RequestFocus();
   }
   return g_ksv_view->GetWidget();
 }
 
+bool KeyboardShortcutView::AcceleratorPressed(
+    const ui::Accelerator& accelerator) {
+  DCHECK_EQ(ui::VKEY_W, accelerator.key_code());
+  DCHECK_EQ(ui::EF_CONTROL_DOWN, accelerator.modifiers());
+  GetWidget()->Close();
+  return true;
+}
+
 void KeyboardShortcutView::Layout() {
   gfx::Rect content_bounds(GetContentsBounds());
   if (content_bounds.IsEmpty())
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
index f19fb7d..8ee6c6b5 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
@@ -35,6 +35,7 @@
   static views::Widget* Show(gfx::NativeWindow context);
 
   // views::View:
+  bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
   void Layout() override;
 
   // search_box::SearchBoxViewDelegate:
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
index c9addf27..ba4b796ec 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
@@ -12,6 +12,7 @@
 #include "ash/test/ash_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/widget/widget.h"
 
@@ -173,4 +174,15 @@
   widget->CloseNow();
 }
 
+// Test that the window can be closed by accelerator.
+TEST_F(KeyboardShortcutViewTest, CloseWindowByAccelerator) {
+  // Showing the widget.
+  views::Widget* widget = KeyboardShortcutView::Show(CurrentContext());
+  EXPECT_FALSE(widget->IsClosed());
+
+  ui::test::EventGenerator& event_generator = GetEventGenerator();
+  event_generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+  EXPECT_TRUE(widget->IsClosed());
+}
+
 }  // namespace keyboard_shortcut_viewer
diff --git a/ash/components/strings/ash_components_strings_zh-CN.xtb b/ash/components/strings/ash_components_strings_zh-CN.xtb
index 06f04cd..259c42a 100644
--- a/ash/components/strings/ash_components_strings_zh-CN.xtb
+++ b/ash/components/strings/ash_components_strings_zh-CN.xtb
@@ -42,6 +42,7 @@
 <translation id="2685170433750953446"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" />,然后按 <ph name="TAB" /> 键或<ph name="RIGHT" />键</translation>
 <translation id="2699509451653686398">将当前网页保存为书签</translation>
 <translation id="2750942583782703988">重新加载当前网页</translation>
+<translation id="2764005613199379871">聚焦于搜索地址栏</translation>
 <translation id="2789868185375229787">缩小网页</translation>
 <translation id="2804480015716812239">在按住 <ph name="ALT" /> 键的同时点击链接</translation>
 <translation id="2830827904629746450">将窗口固定在右侧</translation>
@@ -53,6 +54,7 @@
 <translation id="3105917916468784889">生成屏幕截图</translation>
 <translation id="3126026824346185272">Ctrl</translation>
 <translation id="3140353188828248647">将地址栏设为焦点</translation>
+<translation id="3256109297135787951">取消任务栏中某项内容的突出显示状态</translation>
 <translation id="3288816184963444640">关闭当前窗口</translation>
 <translation id="3407560819924487926">启动任务管理器</translation>
 <translation id="3422679037938588196">转到上一个相符的搜索结果</translation>
@@ -67,6 +69,7 @@
 <translation id="3720939646656082033">在新标签页中打开链接,同时切换到新标签页</translation>
 <translation id="3725795051337497754">关闭当前标签页</translation>
 <translation id="3751033133896282964">撤消上一步操作</translation>
+<translation id="3792178297143798024">打开任务栏中突出显示的内容</translation>
 <translation id="379295446891231126"><ph name="CTRL" /><ph name="SEPARATOR" /> 1 至 8</translation>
 <translation id="3837047332182291558">调亮键盘(仅适用于背光键盘)</translation>
 <translation id="3976863468609830880">点击任务栏中的最后一个图标</translation>
@@ -153,11 +156,13 @@
 <translation id="7787242579016742662">在浏览器中打开文件</translation>
 <translation id="7822267121073044318">切换到下一种语言输入法</translation>
 <translation id="7917881398263220094">停止加载当前网页</translation>
+<translation id="7952165122793773711">前往第 1 至 8 个标签页</translation>
 <translation id="8025696740288105292"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="SHIFT" /><ph name="SEPARATOR2" /><ph name="PLUS" /> 或 <ph name="MINUS" /> 键</translation>
 <translation id="8026334261755873520">清除浏览数据</translation>
 <translation id="8104889575691864804">显示应用菜单</translation>
 <translation id="8130528849632411619">转到文档开头处</translation>
 <translation id="8147954207400281792"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="K" /> 或 <ph name="E" /> 键</translation>
+<translation id="8232835244134740473">在以下窗格之间切换焦点:状态区(其中显示了您的帐号头像)、启动器、地址栏、书签栏(若显示)、打开的网页、下载内容栏(若显示)。</translation>
 <translation id="8234414138295101081">将屏幕旋转 90 度</translation>
 <translation id="8264941229485248811">显示或隐藏开发者工具检查器</translation>
 <translation id="836869401750819675">打开“下载内容”页面</translation>
diff --git a/ash/content/keyboard_overlay/keyboard_overlay_view_unittest.cc b/ash/content/keyboard_overlay/keyboard_overlay_view_unittest.cc
index 9dd7c9c..7567b24 100644
--- a/ash/content/keyboard_overlay/keyboard_overlay_view_unittest.cc
+++ b/ash/content/keyboard_overlay/keyboard_overlay_view_unittest.cc
@@ -6,9 +6,9 @@
 
 #include <algorithm>
 
-#include "ash/accelerators/accelerator_table.h"
 #include "ash/content/keyboard_overlay/keyboard_overlay_delegate.h"
 #include "ash/content/shell_content_state.h"
+#include "ash/public/cpp/accelerators.h"
 #include "ash/test/ash_test_base.h"
 #include "base/stl_util.h"
 #include "ui/web_dialogs/test/test_web_contents_handler.h"
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index 0c5ae3b..4d204643 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -19,6 +19,7 @@
 #include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_bubble.h"
 #include "ash/login/ui/login_detachable_base_model.h"
+#include "ash/login/ui/login_expanded_public_account_view.h"
 #include "ash/login/ui/login_public_account_user_view.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
@@ -220,6 +221,15 @@
   return view_->dev_channel_info_;
 }
 
+LoginExpandedPublicAccountView* LockContentsView::TestApi::expanded_view()
+    const {
+  return view_->expanded_view_;
+}
+
+views::View* LockContentsView::TestApi::main_view() const {
+  return view_->main_view_;
+}
+
 LockContentsView::UserState::UserState(AccountId account_id)
     : account_id(account_id) {}
 
@@ -276,6 +286,13 @@
   note_action_ = new NoteActionLaunchButton(initial_note_action_state);
   top_header_->AddChildView(note_action_);
 
+  // Public Session expanded view.
+  expanded_view_ = new LoginExpandedPublicAccountView(
+      base::BindRepeating(&LockContentsView::SetDisplayStyle,
+                          base::Unretained(this), DisplayStyle::kAll));
+  expanded_view_->SetVisible(false);
+  AddChildView(expanded_view_);
+
   OnLockScreenNoteStateChanged(initial_note_action_state);
   Shell::Get()->AddShellObserver(this);
 }
@@ -299,6 +316,7 @@
 void LockContentsView::Layout() {
   View::Layout();
   LayoutTopHeader();
+  LayoutPublicSessionView();
 
   if (users_list_)
     users_list_->Layout();
@@ -743,6 +761,12 @@
                            gfx::Vector2d(preferred_width, 0));
 }
 
+void LockContentsView::LayoutPublicSessionView() {
+  gfx::Rect bounds = GetContentsBounds();
+  bounds.ClampToCenteredSize(expanded_view_->GetPreferredSize());
+  expanded_view_->SetBoundsRect(bounds);
+}
+
 views::View* LockContentsView::MakeOrientationViewWithWidths(int landscape,
                                                              int portrait) {
   auto* view = new MultiSizedView(gfx::Size(landscape, kNonEmptyHeightDp),
@@ -994,7 +1018,14 @@
 }
 
 void LockContentsView::OnPublicAccountTapped() {
-  NOTIMPLEMENTED();
+  // Update expanded_view_ in case CurrentBigUserView has changed.
+  // 1. It happens when the active big user is changed. For example both
+  // primary and secondary big user are public account and user switches from
+  // primary to secondary.
+  // 2. LoginUserInfo in the big user could be changed if we get updates from
+  // OnPublicSessionDisplayNameChanged and OnPublicSessionLocalesChanged.
+  expanded_view_->UpdateForUser(CurrentBigUserView()->GetCurrentUser());
+  SetDisplayStyle(DisplayStyle::kExclusivePublicAccountExpandedView);
 }
 
 LoginBigUserView* LockContentsView::AllocateLoginBigUserView(
@@ -1117,4 +1148,13 @@
   }
 }
 
+void LockContentsView::SetDisplayStyle(DisplayStyle style) {
+  const bool show_expanded_view =
+      style == DisplayStyle::kExclusivePublicAccountExpandedView;
+  expanded_view_->SetVisible(show_expanded_view);
+  main_view_->SetVisible(!show_expanded_view);
+  top_header_->SetVisible(!show_expanded_view);
+  Layout();
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index 48b62f4..2621fd17 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -42,6 +42,7 @@
 class LoginBigUserView;
 class LoginBubble;
 class LoginDetachableBaseModel;
+class LoginExpandedPublicAccountView;
 class LoginPublicAccountUserView;
 class LoginUserView;
 class NoteActionLaunchButton;
@@ -79,11 +80,21 @@
     LoginBubble* auth_error_bubble() const;
     LoginBubble* detachable_base_error_bubble() const;
     views::View* dev_channel_info() const;
+    LoginExpandedPublicAccountView* expanded_view() const;
+    views::View* main_view() const;
 
    private:
     LockContentsView* const view_;
   };
 
+  enum class DisplayStyle {
+    // Display all the user views, top header view in LockContentsView.
+    kAll,
+    // Display only the public account expanded view, other views in
+    // LockContentsView are hidden.
+    kExclusivePublicAccountExpandedView,
+  };
+
   LockContentsView(
       mojom::TrayActionState initial_note_action_state,
       LoginDataDispatcher* data_dispatcher,
@@ -183,6 +194,9 @@
   // change contents or visibility.
   void LayoutTopHeader();
 
+  // Lay out the expanded public session view.
+  void LayoutPublicSessionView();
+
   // Creates a new view with |landscape| and |portrait| preferred sizes.
   // |landscape| and |portrait| specify the width of the preferred size; the
   // height is an arbitrary non-zero value. The correct size is chosen
@@ -282,6 +296,9 @@
                              LoginAuthUserView* opt_to_hide,
                              bool animate);
 
+  // Change the visibility of child views based on the |style|.
+  void SetDisplayStyle(DisplayStyle style);
+
   std::vector<UserState> users_;
 
   LoginDataDispatcher* const data_dispatcher_;  // Unowned.
@@ -332,6 +349,9 @@
   // state is reported as kActive by the data dispatcher).
   bool lock_screen_apps_active_ = false;
 
+  // Expanded view for public account user to select language and keyboard.
+  LoginExpandedPublicAccountView* expanded_view_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(LockContentsView);
 };
 
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index 587e4d3c..593cce908 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -17,6 +17,7 @@
 #include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_bubble.h"
 #include "ash/login/ui/login_display_style.h"
+#include "ash/login/ui/login_expanded_public_account_view.h"
 #include "ash/login/ui/login_keyboard_test_base.h"
 #include "ash/login/ui/login_pin_view.h"
 #include "ash/login/ui/login_public_account_user_view.h"
@@ -1202,4 +1203,45 @@
   EXPECT_FALSE(is_public_account(user_view0));
 }
 
+TEST_F(LockContentsViewUnitTest, ExpandedPublicSessionView) {
+  // Build lock screen with 3 users: one public account user and two regular
+  // users.
+  auto* contents = new LockContentsView(
+      mojom::TrayActionState::kNotAvailable, data_dispatcher(),
+      std::make_unique<FakeLoginDetachableBaseModel>(data_dispatcher()));
+  LockContentsView::TestApi lock_contents(contents);
+  std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
+  AddPublicAccountUsers(1);
+  AddUsers(2);
+
+  views::View* main_view = lock_contents.main_view();
+  LoginExpandedPublicAccountView* expanded_view = lock_contents.expanded_view();
+  EXPECT_TRUE(main_view->visible());
+  EXPECT_FALSE(expanded_view->visible());
+
+  LoginBigUserView* primary_big_view = lock_contents.primary_big_view();
+  AccountId primary_id =
+      primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+
+  // Open the expanded public session view.
+  ui::test::EventGenerator& generator = GetEventGenerator();
+  generator.PressKey(ui::KeyboardCode::VKEY_RETURN, 0);
+
+  EXPECT_FALSE(main_view->visible());
+  EXPECT_TRUE(expanded_view->visible());
+  EXPECT_EQ(expanded_view->current_user()->basic_user_info->account_id,
+            primary_id);
+
+  // Expect LanuchPublicSession mojo call when the submit button is clicked.
+  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  EXPECT_CALL(*client, LaunchPublicSession(primary_id, _, _));
+
+  // Click on the submit button.
+  LoginExpandedPublicAccountView::TestApi expanded_view_api(expanded_view);
+  generator.MoveMouseTo(
+      expanded_view_api.submit_button()->GetBoundsInScreen().CenterPoint());
+  generator.ClickLeftButton();
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc
new file mode 100644
index 0000000..547ad1f
--- /dev/null
+++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -0,0 +1,480 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/login/ui/login_expanded_public_account_view.h"
+
+#include "ash/login/login_screen_controller.h"
+#include "ash/login/ui/arrow_button_view.h"
+#include "ash/login/ui/login_user_view.h"
+#include "ash/resources/vector_icons/vector_icons.h"
+#include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
+#include "base/strings/utf_string_conversions.h"
+#include "mojo/common/values_struct_traits.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/styled_label.h"
+#include "ui/views/controls/styled_label_listener.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace ash {
+
+namespace {
+
+constexpr const char kLoginExpandedPublicAccountViewClassName[] =
+    "LoginExpandedPublicAccountView";
+constexpr int kExpandedViewWidthDp = 600;
+constexpr int kExpandedViewHeightDp = 324;
+
+constexpr int kTextLineHeightDp = 16;
+constexpr int kRoundRectCornerRadiusDp = 2;
+constexpr int kBorderThicknessDp = 1;
+constexpr int kRightPaneMarginDp = 28;
+constexpr int kLabelMarginDp = 20;
+constexpr int kLeftMarginForSelectionButton = 8;
+constexpr int kRightMarginForSelectionButton = 3;
+
+constexpr SkColor kPublicSessionBackgroundColor =
+    SkColorSetARGB(0xAB, 0x00, 0x00, 0x00);
+constexpr SkColor kBorderColor = SkColorSetA(SK_ColorWHITE, 0x33);
+constexpr SkColor kPublicSessionBlueColor =
+    SkColorSetARGB(0xDE, 0x7B, 0xAA, 0xF7);
+constexpr SkColor kSelectionMenuTitleColor =
+    SkColorSetARGB(0x57, 0xFF, 0xFF, 0xFF);
+constexpr SkColor kArrowButtonColor = SkColorSetARGB(0xFF, 0x42, 0x85, 0xF4);
+
+constexpr int kDropDownIconSizeDp = 16;
+constexpr int kArrowButtonSizeDp = 40;
+constexpr int kAdvancedViewButtonWidthDp = 132;
+constexpr int kAdvancedViewButtonHeightDp = 16;
+constexpr int kSelectionBoxWidthDp = 178;
+constexpr int kSelectionBoxHeightDp = 28;
+constexpr int kTopSpacingForLabelInAdvancedViewDp = 7;
+constexpr int kTopSpacingForLabelInRegularViewDp = 65;
+constexpr int kSpacingBetweenLabelsDp = 17;
+constexpr int kSpacingBetweenSelectionMenusDp = 15;
+constexpr int kSpacingBetweenSelectionTitleAndButtonDp = 3;
+constexpr int kSpacingBetweenLanguageMenuAndAdvancedViewButtonDp = 34;
+constexpr int kSpacingBetweenAdvancedViewButtonAndLabelDp = 32;
+constexpr int kTopSpacingForUserViewDp = 62;
+
+constexpr int kNonEmptyWidth = 1;
+constexpr int kNonEmptyHeight = 1;
+
+views::Label* CreateLabel(const base::string16& text, SkColor color) {
+  auto* label = new views::Label(text);
+  label->SetSubpixelRenderingEnabled(false);
+  label->SetAutoColorReadabilityEnabled(false);
+  label->SetFontList(views::Label::GetDefaultFontList().Derive(
+      0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL));
+  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  label->SetEnabledColor(color);
+  return label;
+}
+
+}  // namespace
+
+// Button with text on the left side and an icon on the right side.
+class SelectionButtonView : public views::Button {
+ public:
+  SelectionButtonView(const base::string16& text,
+                      views::ButtonListener* listener)
+      : views::Button(listener) {
+    SetPaintToLayer();
+    layer()->SetFillsBoundsOpaquely(false);
+    SetFocusBehavior(FocusBehavior::ALWAYS);
+    SetLayoutManager(std::make_unique<views::FillLayout>());
+
+    auto add_horizontal_margin = [&](int width,
+                                     views::View* parent) -> views::View* {
+      auto* margin = new NonAccessibleView();
+      margin->SetPreferredSize(gfx::Size(width, kNonEmptyHeight));
+      parent->AddChildView(margin);
+      return margin;
+    };
+
+    auto* label_container = new NonAccessibleView();
+    views::BoxLayout* label_layout = label_container->SetLayoutManager(
+        std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+    label_layout->set_main_axis_alignment(
+        views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+    AddChildView(label_container);
+
+    label_ = CreateLabel(text, SK_ColorWHITE);
+    left_margin_view_ = add_horizontal_margin(left_margin_, label_container);
+    label_container->AddChildView(label_);
+
+    auto* icon_container = new NonAccessibleView();
+    views::BoxLayout* icon_layout = icon_container->SetLayoutManager(
+        std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+    icon_layout->set_main_axis_alignment(
+        views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
+    AddChildView(icon_container);
+
+    icon_ = new views::ImageView;
+    icon_->SetVerticalAlignment(views::ImageView::CENTER);
+    icon_->SetPreferredSize(
+        gfx::Size(kDropDownIconSizeDp, kDropDownIconSizeDp));
+
+    icon_container->AddChildView(icon_);
+    right_margin_view_ = add_horizontal_margin(right_margin_, icon_container);
+  }
+
+  ~SelectionButtonView() override = default;
+
+  // Return the preferred height of this view. This overrides the default
+  // behavior in FillLayout::GetPreferredHeightForWidth which caluculates the
+  // height based on its child height.
+  int GetHeightForWidth(int w) const override {
+    return GetPreferredSize().height();
+  }
+
+  void SetMargins(int left, int right) {
+    if (left_margin_ == left && right_margin_ == right)
+      return;
+
+    left_margin_ = left;
+    right_margin_ = right;
+    left_margin_view_->SetPreferredSize(
+        gfx::Size(left_margin_, kNonEmptyHeight));
+    right_margin_view_->SetPreferredSize(
+        gfx::Size(right_margin_, kNonEmptyHeight));
+    Layout();
+  }
+
+  void SetTextColor(SkColor color) { label_->SetEnabledColor(color); }
+
+  void SetIcon(const gfx::VectorIcon& icon, SkColor color) {
+    icon_->SetImage(gfx::CreateVectorIcon(icon, color));
+  }
+
+ private:
+  int left_margin_ = 0;
+  int right_margin_ = 0;
+  views::Label* label_ = nullptr;
+  views::ImageView* icon_ = nullptr;
+  views::View* left_margin_view_ = nullptr;
+  views::View* right_margin_view_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(SelectionButtonView);
+};
+
+// Implements the right part of the expanded public session view.
+class RightPaneView : public NonAccessibleView,
+                      public views::ButtonListener,
+                      public views::StyledLabelListener {
+ public:
+  RightPaneView() {
+    SetPreferredSize(
+        gfx::Size(kExpandedViewWidthDp / 2, kExpandedViewHeightDp));
+    SetBorder(views::CreateEmptyBorder(gfx::Insets(kRightPaneMarginDp)));
+
+    // Create labels view.
+    labels_view_ = new NonAccessibleView();
+    labels_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::kVertical, gfx::Insets(), kSpacingBetweenLabelsDp));
+    AddChildView(labels_view_);
+
+    views::Label* top_label =
+        CreateLabel(l10n_util::GetStringUTF16(
+                        IDS_ASH_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING),
+                    SK_ColorWHITE);
+    top_label->SetMultiLine(true);
+    top_label->SetLineHeight(kTextLineHeightDp);
+
+    const base::string16 link = l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE);
+    size_t offset;
+    const base::string16 text = l10n_util::GetStringFUTF16(
+        IDS_ASH_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER, link, &offset);
+    views::StyledLabel* bottom_label = new views::StyledLabel(text, this);
+
+    views::StyledLabel::RangeStyleInfo style;
+    style.custom_font = bottom_label->GetDefaultFontList().Derive(
+        0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL);
+    style.override_color = SK_ColorWHITE;
+    bottom_label->AddStyleRange(gfx::Range(0, offset), style);
+
+    views::StyledLabel::RangeStyleInfo link_style =
+        views::StyledLabel::RangeStyleInfo::CreateForLink();
+    link_style.override_color = kPublicSessionBlueColor;
+    bottom_label->AddStyleRange(gfx::Range(offset, offset + link.length()),
+                                link_style);
+    bottom_label->set_auto_color_readability_enabled(false);
+
+    labels_view_->AddChildView(top_label);
+    labels_view_->AddChildView(bottom_label);
+
+    // Create button to show/hide advanced view.
+    advanced_view_button_ = new SelectionButtonView(
+        l10n_util::GetStringUTF16(
+            IDS_ASH_LOGIN_PUBLIC_SESSION_LANGUAGE_AND_INPUT),
+        this);
+    advanced_view_button_->SetTextColor(kPublicSessionBlueColor);
+    advanced_view_button_->SetIcon(kLoginScreenButtonDropdownIcon,
+                                   kPublicSessionBlueColor);
+    advanced_view_button_->SetPreferredSize(
+        gfx::Size(kAdvancedViewButtonWidthDp, kAdvancedViewButtonHeightDp));
+    AddChildView(advanced_view_button_);
+
+    // Create advanced view.
+    advanced_view_ = new NonAccessibleView();
+    advanced_view_->SetLayoutManager(
+        std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
+    AddChildView(advanced_view_);
+
+    // Creates button to open the menu.
+    auto create_menu_button =
+        [&](const base::string16& text) -> SelectionButtonView* {
+      auto* button = new SelectionButtonView(text, this);
+      button->SetPreferredSize(
+          gfx::Size(kSelectionBoxWidthDp, kSelectionBoxHeightDp));
+      button->SetMargins(kLeftMarginForSelectionButton,
+                         kRightMarginForSelectionButton);
+      button->SetBorder(views::CreateRoundedRectBorder(
+          kBorderThicknessDp, kRoundRectCornerRadiusDp, kBorderColor));
+      button->SetIcon(kLoginScreenMenuDropdownIcon, kSelectionMenuTitleColor);
+      return button;
+    };
+
+    auto create_padding = [](int amount) -> views::View* {
+      auto* padding = new NonAccessibleView();
+      padding->SetPreferredSize(gfx::Size(kNonEmptyWidth, amount));
+      return padding;
+    };
+
+    views::Label* language_title = CreateLabel(
+        l10n_util::GetStringUTF16(IDS_ASH_LOGIN_LANGUAGE_SELECTION_SELECT),
+        kSelectionMenuTitleColor);
+    language_selection_ = create_menu_button(base::string16());
+
+    views::Label* keyboard_title = CreateLabel(
+        l10n_util::GetStringUTF16(IDS_ASH_LOGIN_KEYBOARD_SELECTION_SELECT),
+        kSelectionMenuTitleColor);
+    keyboard_selection_ = create_menu_button(base::string16());
+
+    advanced_view_->AddChildView(language_title);
+    advanced_view_->AddChildView(
+        create_padding(kSpacingBetweenSelectionTitleAndButtonDp));
+    advanced_view_->AddChildView(language_selection_);
+    advanced_view_->AddChildView(
+        create_padding(kSpacingBetweenSelectionMenusDp));
+    advanced_view_->AddChildView(keyboard_title);
+    advanced_view_->AddChildView(
+        create_padding(kSpacingBetweenSelectionTitleAndButtonDp));
+    advanced_view_->AddChildView(keyboard_selection_);
+
+    submit_button_ = new ArrowButtonView(this, kArrowButtonSizeDp);
+    submit_button_->SetBackgroundColor(kArrowButtonColor);
+    AddChildView(submit_button_);
+  }
+
+  ~RightPaneView() override = default;
+
+  void Layout() override {
+    const gfx::Rect bounds = GetContentsBounds();
+    // Place the labels.
+    const int label_width = bounds.width() - kLabelMarginDp;
+    labels_view_->SetBounds(
+        bounds.x(),
+        show_advanced_view_ ? kTopSpacingForLabelInAdvancedViewDp + bounds.y()
+                            : kTopSpacingForLabelInRegularViewDp + bounds.y(),
+        label_width, labels_view_->GetHeightForWidth(label_width));
+
+    // Place the advanced_view_button_.
+    advanced_view_button_->SizeToPreferredSize();
+    advanced_view_button_->SetPosition(gfx::Point(
+        bounds.x(),
+        show_advanced_view_
+            ? labels_view_->bounds().bottom() + kSpacingBetweenLabelsDp
+            : labels_view_->bounds().bottom() +
+                  kSpacingBetweenAdvancedViewButtonAndLabelDp));
+
+    // Place the advanced view.
+    advanced_view_->SetVisible(show_advanced_view_);
+    if (show_advanced_view_) {
+      advanced_view_->SizeToPreferredSize();
+      advanced_view_->SetPosition(gfx::Point(
+          bounds.x(), advanced_view_button_->bounds().bottom() +
+                          kSpacingBetweenLanguageMenuAndAdvancedViewButtonDp));
+    }
+
+    // Place the submit button.
+    submit_button_->SizeToPreferredSize();
+    submit_button_->SetPosition(
+        gfx::Point(bounds.right() - kArrowButtonSizeDp,
+                   bounds.bottom() - kArrowButtonSizeDp));
+  }
+
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
+    if (sender == advanced_view_button_) {
+      show_advanced_view_ = !show_advanced_view_;
+      Layout();
+    } else if (sender == submit_button_) {
+      Shell::Get()->login_screen_controller()->LaunchPublicSession(
+          current_user_->basic_user_info->account_id, selected_locale_,
+          selected_keyboard_);
+    }
+
+    // TODO(crbug.com/809635): Show language and keyboard menu when clicks on
+    // language_selection_ and keyboard_selection_.
+  }
+
+  // "Learn more" is clicked to show additional information of what the device
+  // admin may monitor.
+  void StyledLabelLinkClicked(views::StyledLabel* label,
+                              const gfx::Range& range,
+                              int event_flags) override {
+    NOTIMPLEMENTED();
+  }
+
+  void UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+    DCHECK_EQ(user->basic_user_info->type,
+              user_manager::USER_TYPE_PUBLIC_ACCOUNT);
+    current_user_ = user->Clone();
+    if (selected_locale_.empty())
+      selected_locale_ = user->public_account_info->default_locale;
+
+    show_advanced_view_ = user->public_account_info->show_advanced_view;
+    Layout();
+
+    // TODO(crbug.com/809635): pre-populate keyboard list in LoginUserInfoPtr.
+  }
+
+  SelectionButtonView* advanced_view_button() { return advanced_view_button_; }
+  ArrowButtonView* submit_button() { return submit_button_; }
+  views::View* advanced_view() { return advanced_view_; }
+
+ private:
+  bool show_advanced_view_ = false;
+  mojom::LoginUserInfoPtr current_user_;
+  std::string selected_locale_;
+  std::string selected_keyboard_;
+
+  views::View* labels_view_ = nullptr;
+  SelectionButtonView* advanced_view_button_ = nullptr;
+  views::View* advanced_view_ = nullptr;
+  SelectionButtonView* language_selection_ = nullptr;
+  SelectionButtonView* keyboard_selection_ = nullptr;
+  ArrowButtonView* submit_button_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(RightPaneView);
+};
+
+LoginExpandedPublicAccountView::TestApi::TestApi(
+    LoginExpandedPublicAccountView* view)
+    : view_(view) {}
+
+LoginExpandedPublicAccountView::TestApi::~TestApi() = default;
+
+views::View* LoginExpandedPublicAccountView::TestApi::advanced_view_button() {
+  return view_->right_pane_->advanced_view_button();
+}
+
+ArrowButtonView* LoginExpandedPublicAccountView::TestApi::submit_button() {
+  return view_->right_pane_->submit_button();
+}
+
+views::View* LoginExpandedPublicAccountView::TestApi::advanced_view() {
+  return view_->right_pane_->advanced_view();
+}
+
+LoginExpandedPublicAccountView::LoginExpandedPublicAccountView(
+    const OnPublicSessionViewDismissed& on_dismissed)
+    : NonAccessibleView(kLoginExpandedPublicAccountViewClassName),
+      on_dismissed_(on_dismissed) {
+  Shell::Get()->AddPreTargetHandler(this);
+  SetLayoutManager(
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+  SetPreferredSize(gfx::Size(kExpandedViewWidthDp, kExpandedViewHeightDp));
+
+  user_view_ = new LoginUserView(
+      LoginDisplayStyle::kLarge, false /*show_dropdown*/, true /*show_domain*/,
+      base::DoNothing(), base::RepeatingClosure(), base::RepeatingClosure());
+  user_view_->SetForceOpaque(true);
+  user_view_->SetTapEnabled(false);
+
+  auto* left_pane = new NonAccessibleView();
+  AddChildView(left_pane);
+  left_pane->SetLayoutManager(
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
+  left_pane->SetPreferredSize(
+      gfx::Size(kExpandedViewWidthDp / 2, kExpandedViewHeightDp));
+
+  auto* top_spacing = new NonAccessibleView();
+  top_spacing->SetPreferredSize(
+      gfx::Size(kNonEmptyWidth, kTopSpacingForUserViewDp));
+  left_pane->AddChildView(top_spacing);
+  left_pane->AddChildView(user_view_);
+  left_pane->SetBorder(
+      views::CreateSolidSidedBorder(0, 0, 0, kBorderThicknessDp, kBorderColor));
+
+  right_pane_ = new RightPaneView();
+  AddChildView(right_pane_);
+}
+
+LoginExpandedPublicAccountView::~LoginExpandedPublicAccountView() {
+  Shell::Get()->RemovePreTargetHandler(this);
+}
+
+void LoginExpandedPublicAccountView::ProcessPressedEvent(
+    const ui::LocatedEvent* event) {
+  if (!visible())
+    return;
+
+  if (GetBoundsInScreen().Contains(event->root_location()))
+    return;
+
+  SetVisible(false);
+  on_dismissed_.Run();
+}
+
+void LoginExpandedPublicAccountView::UpdateForUser(
+    const mojom::LoginUserInfoPtr& user) {
+  user_view_->UpdateForUser(user, false /*animate*/);
+  right_pane_->UpdateForUser(user);
+}
+
+const mojom::LoginUserInfoPtr& LoginExpandedPublicAccountView::current_user()
+    const {
+  return user_view_->current_user();
+}
+
+void LoginExpandedPublicAccountView::OnPaint(gfx::Canvas* canvas) {
+  views::View::OnPaint(canvas);
+
+  cc::PaintFlags flags;
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setColor(kPublicSessionBackgroundColor);
+  flags.setAntiAlias(true);
+  canvas->DrawRoundRect(GetContentsBounds(), kRoundRectCornerRadiusDp, flags);
+}
+
+void LoginExpandedPublicAccountView::OnMouseEvent(ui::MouseEvent* event) {
+  if (event->type() == ui::ET_MOUSE_PRESSED)
+    ProcessPressedEvent(event->AsLocatedEvent());
+}
+
+void LoginExpandedPublicAccountView::OnGestureEvent(ui::GestureEvent* event) {
+  if ((event->type() == ui::ET_GESTURE_TAP ||
+       event->type() == ui::ET_GESTURE_TAP_DOWN)) {
+    ProcessPressedEvent(event->AsLocatedEvent());
+  }
+}
+
+void LoginExpandedPublicAccountView::OnKeyEvent(ui::KeyEvent* event) {
+  if (!visible() || event->type() != ui::ET_KEY_PRESSED)
+    return;
+
+  if (event->key_code() == ui::KeyboardCode::VKEY_ESCAPE) {
+    SetVisible(false);
+    on_dismissed_.Run();
+  }
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/login_expanded_public_account_view.h b/ash/login/ui/login_expanded_public_account_view.h
new file mode 100644
index 0000000..d51a7cd
--- /dev/null
+++ b/ash/login/ui/login_expanded_public_account_view.h
@@ -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.
+
+#ifndef ASH_LOGIN_UI_LOGIN_EXPANDED_PUBLIC_ACCOUNT_VIEW_H_
+#define ASH_LOGIN_UI_LOGIN_EXPANDED_PUBLIC_ACCOUNT_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/interfaces/login_user_info.mojom.h"
+#include "ui/events/event_handler.h"
+#include "ui/views/view.h"
+
+namespace ash {
+
+class ArrowButtonView;
+class LoginUserView;
+class RightPaneView;
+
+// Implements an expanded view for the public acount user to select language
+// and keyboard options.
+class ASH_EXPORT LoginExpandedPublicAccountView : public NonAccessibleView {
+ public:
+  // TestApi is used for tests to get internal implementation details.
+  class ASH_EXPORT TestApi {
+   public:
+    explicit TestApi(LoginExpandedPublicAccountView* view);
+    ~TestApi();
+
+    views::View* advanced_view_button();
+    ArrowButtonView* submit_button();
+    views::View* advanced_view();
+
+   private:
+    LoginExpandedPublicAccountView* const view_;
+  };
+
+  using OnPublicSessionViewDismissed = base::RepeatingClosure;
+  explicit LoginExpandedPublicAccountView(
+      const OnPublicSessionViewDismissed& on_dismissed);
+  ~LoginExpandedPublicAccountView() override;
+
+  void ProcessPressedEvent(const ui::LocatedEvent* event);
+  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+  const mojom::LoginUserInfoPtr& current_user() const;
+
+  // views::View:
+  void OnPaint(gfx::Canvas* canvas) override;
+
+  // ui::EventHandler:
+  void OnMouseEvent(ui::MouseEvent* event) override;
+  void OnGestureEvent(ui::GestureEvent* event) override;
+  void OnKeyEvent(ui::KeyEvent* event) override;
+
+ private:
+  LoginUserView* user_view_ = nullptr;
+  RightPaneView* right_pane_ = nullptr;
+  OnPublicSessionViewDismissed on_dismissed_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginExpandedPublicAccountView);
+};
+
+}  // namespace ash
+
+#endif  // ASH_LOGIN_UI_LOGIN_EXPANDED_PUBLIC_ACCOUNT_VIEW_H_
diff --git a/ash/login/ui/login_expanded_public_account_view_unittest.cc b/ash/login/ui/login_expanded_public_account_view_unittest.cc
new file mode 100644
index 0000000..dec28334
--- /dev/null
+++ b/ash/login/ui/login_expanded_public_account_view_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/login/ui/login_expanded_public_account_view.h"
+#include "ash/login/ui/login_test_base.h"
+#include "ash/login/ui/login_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+namespace {
+
+// Total width of the expanded view.
+constexpr int kBubbleTotalWidthDp = 600;
+// Total height of the expanded view.
+constexpr int kBubbleTotalHeightDp = 324;
+
+class LoginExpandedPublicAccountViewTest : public LoginTestBase {
+ protected:
+  LoginExpandedPublicAccountViewTest() = default;
+  ~LoginExpandedPublicAccountViewTest() override = default;
+
+  // LoginTestBase:
+  void SetUp() override {
+    LoginTestBase::SetUp();
+
+    user_ = CreatePublicAccountUser("user@domain.com");
+    view_ = new LoginExpandedPublicAccountView(base::DoNothing());
+    view_->UpdateForUser(user_);
+
+    container_ = new views::View();
+    container_->SetLayoutManager(
+        std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+    container_->AddChildView(view_);
+    SetWidget(CreateWidgetWithContent(container_));
+  }
+
+  mojom::LoginUserInfoPtr user_;
+  // Owned by test widget view hierarchy.
+  views::View* container_ = nullptr;
+  // Owned by test widget view hierarchy
+  LoginExpandedPublicAccountView* view_ = nullptr;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginExpandedPublicAccountViewTest);
+};
+
+}  // namespace
+
+// Verifies toggle advanced view will update the layout correctly.
+TEST_F(LoginExpandedPublicAccountViewTest, ToggleAdvancedView) {
+  view_->SizeToPreferredSize();
+  EXPECT_EQ(view_->width(), kBubbleTotalWidthDp);
+  EXPECT_EQ(view_->height(), kBubbleTotalHeightDp);
+
+  LoginExpandedPublicAccountView::TestApi test_api(view_);
+  EXPECT_FALSE(user_->public_account_info->show_advanced_view);
+  EXPECT_FALSE(test_api.advanced_view()->visible());
+
+  // Toggle show_advanced_view.
+  user_->public_account_info->show_advanced_view = true;
+  view_->UpdateForUser(user_);
+
+  // Advanced view is shown and the overall size does not change.
+  EXPECT_TRUE(test_api.advanced_view()->visible());
+  EXPECT_EQ(view_->width(), kBubbleTotalWidthDp);
+  EXPECT_EQ(view_->height(), kBubbleTotalHeightDp);
+
+  // Click on the show advanced button.
+  ui::test::EventGenerator& generator = GetEventGenerator();
+  generator.MoveMouseTo(
+      test_api.advanced_view_button()->GetBoundsInScreen().CenterPoint());
+  generator.ClickLeftButton();
+
+  // Advanced view is hidden and the overall size does not change.
+  EXPECT_FALSE(test_api.advanced_view()->visible());
+  EXPECT_EQ(view_->width(), kBubbleTotalWidthDp);
+  EXPECT_EQ(view_->height(), kBubbleTotalHeightDp);
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/login_public_account_user_view.cc b/ash/login/ui/login_public_account_user_view.cc
index e33e46ab..bea6ff5 100644
--- a/ash/login/ui/login_public_account_user_view.cc
+++ b/ash/login/ui/login_public_account_user_view.cc
@@ -77,7 +77,7 @@
       login_layout_util::WrapViewForPreferredSize(user_view_);
 
   auto add_padding = [&](int amount) {
-    auto* padding = new views::View();
+    auto* padding = new NonAccessibleView();
     padding->SetPreferredSize(gfx::Size(kNonEmptyWidth, amount));
     AddChildView(padding);
   };
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index ef37741..f0a6b73 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -75,7 +75,7 @@
     SkColorSetARGBMacro(0xAB, 0xFF, 0xFF, 0xFF);
 constexpr int kEnterpriseIconSizeDp = 12;
 constexpr int kBetweenEnterpriseIconAndDomainDp = 8;
-constexpr int kVerticalSpacingBetweenUserNameAndDomainDp = 17;
+constexpr int kVerticalSpacingBetweenUserNameAndDomainDp = 14;
 
 int GetImageSize(LoginDisplayStyle style) {
   switch (style) {
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h
index 45241b62..70010c87 100644
--- a/ash/login/ui/login_user_view.h
+++ b/ash/login/ui/login_user_view.h
@@ -51,6 +51,8 @@
   // Returns the width of this view for the given display style.
   static int WidthForLayoutStyle(LoginDisplayStyle style);
 
+  // Use null callbacks for |on_remove_warning_shown| and |on_remove| when
+  // |show_dropdown| arg is false.
   LoginUserView(LoginDisplayStyle style,
                 bool show_dropdown,
                 bool show_domain,
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index d1f43a4..bd05b17 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -7,6 +7,8 @@
 # C++ headers and sources that can be used outside ash.
 component("cpp") {
   sources = [
+    "accelerators.cc",
+    "accelerators.h",
     "accessibility_types.h",
     "app_list/app_list_types.cc",
     "app_list/app_list_types.h",
diff --git a/ash/public/cpp/accelerators.cc b/ash/public/cpp/accelerators.cc
new file mode 100644
index 0000000..7c59fd5
--- /dev/null
+++ b/ash/public/cpp/accelerators.cc
@@ -0,0 +1,175 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/accelerators.h"
+
+#include "base/macros.h"
+
+namespace ash {
+
+const int kDebugModifier =
+    ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN;
+
+const AcceleratorData kAcceleratorData[] = {
+    {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME},
+    {false, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME},
+    {true, ui::VKEY_TAB, ui::EF_ALT_DOWN, CYCLE_FORWARD_MRU},
+    {true, ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
+     CYCLE_BACKWARD_MRU},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE, TOGGLE_OVERVIEW},
+    {true, ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, TOGGLE_APP_LIST},
+    {true, ui::VKEY_WLAN, ui::EF_NONE, TOGGLE_WIFI},
+    {true, ui::VKEY_KBD_BRIGHTNESS_DOWN, ui::EF_NONE, KEYBOARD_BRIGHTNESS_DOWN},
+    {true, ui::VKEY_KBD_BRIGHTNESS_UP, ui::EF_NONE, KEYBOARD_BRIGHTNESS_UP},
+    // Maximize button.
+    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_CONTROL_DOWN, TOGGLE_MIRROR_MODE},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_ALT_DOWN, SWAP_PRIMARY_DISPLAY},
+    // Cycle windows button.
+    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN, TAKE_SCREENSHOT},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     TAKE_PARTIAL_SCREENSHOT},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
+     TAKE_WINDOW_SCREENSHOT},
+    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE, BRIGHTNESS_DOWN},
+    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_ALT_DOWN, KEYBOARD_BRIGHTNESS_DOWN},
+    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE, BRIGHTNESS_UP},
+    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_ALT_DOWN, KEYBOARD_BRIGHTNESS_UP},
+    {true, ui::VKEY_BRIGHTNESS_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     MAGNIFIER_ZOOM_OUT},
+    {true, ui::VKEY_BRIGHTNESS_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     MAGNIFIER_ZOOM_IN},
+    {true, ui::VKEY_L, ui::EF_COMMAND_DOWN, LOCK_SCREEN},
+    {true, ui::VKEY_L, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN, SUSPEND},
+    // The lock key on Chrome OS keyboards produces F13 scancodes.
+    {true, ui::VKEY_F13, ui::EF_NONE, LOCK_PRESSED},
+    {false, ui::VKEY_F13, ui::EF_NONE, LOCK_RELEASED},
+    // Generic keyboards can use VKEY_SLEEP to mimic ChromeOS keyboard's lock
+    // key.
+    {true, ui::VKEY_SLEEP, ui::EF_NONE, LOCK_PRESSED},
+    {false, ui::VKEY_SLEEP, ui::EF_NONE, LOCK_RELEASED},
+    {true, ui::VKEY_POWER, ui::EF_NONE, POWER_PRESSED},
+    {false, ui::VKEY_POWER, ui::EF_NONE, POWER_RELEASED},
+    {true, ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FILE_MANAGER},
+    {true, ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN, OPEN_GET_HELP},
+    {true, ui::VKEY_OEM_2, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     OPEN_GET_HELP},
+    {true, ui::VKEY_T, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, OPEN_CROSH},
+    {true, ui::VKEY_I, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     TOUCH_HUD_MODE_CHANGE},
+    {true, ui::VKEY_I,
+     ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN,
+     TOUCH_HUD_CLEAR},
+    {true, ui::VKEY_H, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
+     TOGGLE_HIGH_CONTRAST},
+    {true, ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     TOGGLE_SPOKEN_FEEDBACK},
+    {true, ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN,
+     TOGGLE_DICTATION},
+    {true, ui::VKEY_OEM_COMMA, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     SWITCH_TO_PREVIOUS_USER},
+    {true, ui::VKEY_OEM_PERIOD, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     SWITCH_TO_NEXT_USER},
+    // Single shift release turns off caps lock.
+    {false, ui::VKEY_LSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
+    {false, ui::VKEY_SHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
+    {false, ui::VKEY_RSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
+    // Accelerators to toggle Caps Lock.
+    // The following is triggered when Search is released while Alt is still
+    // down. The key_code here is LWIN (for search) and Alt is a modifier.
+    {false, ui::VKEY_LWIN, ui::EF_ALT_DOWN, TOGGLE_CAPS_LOCK},
+    // The following is triggered when Alt is released while search is still
+    // down. The key_code here is MENU (for Alt) and Search is a modifier
+    // (EF_COMMAND_DOWN is used for Search as a modifier).
+    {false, ui::VKEY_MENU, ui::EF_COMMAND_DOWN, TOGGLE_CAPS_LOCK},
+    {true, ui::VKEY_VOLUME_MUTE, ui::EF_NONE, VOLUME_MUTE},
+    {true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN},
+    {true, ui::VKEY_VOLUME_UP, ui::EF_NONE, VOLUME_UP},
+    {true, ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, SHOW_TASK_MANAGER},
+    {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, NEXT_IME},
+    {true, ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FEEDBACK_PAGE},
+    {true, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT},
+    {true, ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     NEW_INCOGNITO_WINDOW},
+    {true, ui::VKEY_N, ui::EF_CONTROL_DOWN, NEW_WINDOW},
+    {true, ui::VKEY_T, ui::EF_CONTROL_DOWN, NEW_TAB},
+    {true, ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
+     SCALE_UI_UP},
+    {true, ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
+     SCALE_UI_DOWN},
+    {true, ui::VKEY_0, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, SCALE_UI_RESET},
+    {true, ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
+     ROTATE_SCREEN},
+    {true, ui::VKEY_BROWSER_REFRESH,
+     ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ROTATE_WINDOW},
+    {true, ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, RESTORE_TAB},
+    {true, ui::VKEY_PRINT, ui::EF_NONE, TAKE_SCREENSHOT},
+    // On Chrome OS, Search key is mapped to LWIN. The Search key binding should
+    // act on release instead of press when using Search as a modifier key for
+    // extended keyboard shortcuts.
+    {false, ui::VKEY_LWIN, ui::EF_NONE, TOGGLE_APP_LIST},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE, TOGGLE_FULLSCREEN},
+    {true, ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_SHIFT_DOWN, TOGGLE_FULLSCREEN},
+    {true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN, UNPIN},
+    {true, ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, FOCUS_SHELF},
+    {true, ui::VKEY_HELP, ui::EF_NONE, SHOW_KEYBOARD_OVERLAY},
+    {true, ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     SHOW_KEYBOARD_OVERLAY},
+    {true, ui::VKEY_OEM_2,
+     ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+     SHOW_KEYBOARD_OVERLAY},
+    {true, ui::VKEY_F14, ui::EF_NONE, SHOW_KEYBOARD_OVERLAY},
+    {true, ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
+     TOGGLE_MESSAGE_CENTER_BUBBLE},
+    {true, ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, SHOW_STYLUS_TOOLS},
+    {true, ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
+     TOGGLE_SYSTEM_TRAY_BUBBLE},
+    // Until we have unified settings and notifications the "hamburger"
+    // key opens quick settings.
+    {true, ui::VKEY_SETTINGS, ui::EF_NONE, TOGGLE_SYSTEM_TRAY_BUBBLE},
+    {true, ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN,
+     SHOW_IME_MENU_BUBBLE},
+    {true, ui::VKEY_1, ui::EF_ALT_DOWN, LAUNCH_APP_0},
+    {true, ui::VKEY_2, ui::EF_ALT_DOWN, LAUNCH_APP_1},
+    {true, ui::VKEY_3, ui::EF_ALT_DOWN, LAUNCH_APP_2},
+    {true, ui::VKEY_4, ui::EF_ALT_DOWN, LAUNCH_APP_3},
+    {true, ui::VKEY_5, ui::EF_ALT_DOWN, LAUNCH_APP_4},
+    {true, ui::VKEY_6, ui::EF_ALT_DOWN, LAUNCH_APP_5},
+    {true, ui::VKEY_7, ui::EF_ALT_DOWN, LAUNCH_APP_6},
+    {true, ui::VKEY_8, ui::EF_ALT_DOWN, LAUNCH_APP_7},
+    {true, ui::VKEY_9, ui::EF_ALT_DOWN, LAUNCH_LAST_APP},
+
+    // Window management shortcuts.
+    {true, ui::VKEY_OEM_4, ui::EF_ALT_DOWN, WINDOW_CYCLE_SNAP_LEFT},
+    {true, ui::VKEY_OEM_6, ui::EF_ALT_DOWN, WINDOW_CYCLE_SNAP_RIGHT},
+    {true, ui::VKEY_OEM_MINUS, ui::EF_ALT_DOWN, WINDOW_MINIMIZE},
+    {true, ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN, TOGGLE_MAXIMIZED},
+    {true, ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
+     WINDOW_POSITION_CENTER},
+    {true, ui::VKEY_BROWSER_FORWARD, ui::EF_CONTROL_DOWN, FOCUS_NEXT_PANE},
+    {true, ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN, FOCUS_PREVIOUS_PANE},
+
+    // Moving active window between displays shortcut.
+    {true, ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
+     MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS},
+
+    // Media Player shortcuts.
+    {true, ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE, MEDIA_NEXT_TRACK},
+    {true, ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE, MEDIA_PLAY_PAUSE},
+    {true, ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE, MEDIA_PREV_TRACK},
+
+    // Voice Interaction shortcuts.
+    {true, ui::VKEY_A, ui::EF_COMMAND_DOWN, START_VOICE_INTERACTION},
+    {true, ui::VKEY_ASSISTANT, ui::EF_NONE, START_VOICE_INTERACTION},
+
+    // Debugging shortcuts that need to be available to end-users in
+    // release builds.
+    {true, ui::VKEY_U, kDebugModifier, PRINT_UI_HIERARCHIES},
+
+    // TODO(yusukes): Handle VKEY_MEDIA_STOP, and
+    // VKEY_MEDIA_LAUNCH_MAIL.
+};
+
+const size_t kAcceleratorDataLength = arraysize(kAcceleratorData);
+
+}  // namespace ash
diff --git a/ash/public/cpp/accelerators.h b/ash/public/cpp/accelerators.h
new file mode 100644
index 0000000..9882c10
--- /dev/null
+++ b/ash/public/cpp/accelerators.h
@@ -0,0 +1,134 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_ACCELERATORS_H_
+#define ASH_PUBLIC_CPP_ACCELERATORS_H_
+
+#include <stddef.h>
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace ash {
+
+// See documentation in ash/accelerators/accelerator_table.h.
+
+enum AcceleratorAction {
+  BRIGHTNESS_DOWN,
+  BRIGHTNESS_UP,
+  CYCLE_BACKWARD_MRU,
+  CYCLE_FORWARD_MRU,
+  DEBUG_PRINT_LAYER_HIERARCHY,
+  DEBUG_PRINT_VIEW_HIERARCHY,
+  DEBUG_PRINT_WINDOW_HIERARCHY,
+  DEBUG_SHOW_TOAST,
+  DEBUG_TOGGLE_DEVICE_SCALE_FACTOR,
+  DEBUG_TOGGLE_SHOW_DEBUG_BORDERS,
+  DEBUG_TOGGLE_SHOW_FPS_COUNTER,
+  DEBUG_TOGGLE_SHOW_PAINT_RECTS,
+  DEBUG_TOGGLE_TOUCH_PAD,
+  DEBUG_TOGGLE_TOUCH_SCREEN,
+  DEBUG_TOGGLE_TABLET_MODE,
+  DEBUG_TOGGLE_WALLPAPER_MODE,
+  DEBUG_TRIGGER_CRASH,  // Intentionally crash the ash process.
+  DEV_ADD_REMOVE_DISPLAY,
+  DEV_TOGGLE_UNIFIED_DESKTOP,
+  DISABLE_CAPS_LOCK,
+  EXIT,
+  FOCUS_NEXT_PANE,
+  FOCUS_PREVIOUS_PANE,
+  FOCUS_SHELF,
+  KEYBOARD_BRIGHTNESS_DOWN,
+  KEYBOARD_BRIGHTNESS_UP,
+  LAUNCH_APP_0,
+  LAUNCH_APP_1,
+  LAUNCH_APP_2,
+  LAUNCH_APP_3,
+  LAUNCH_APP_4,
+  LAUNCH_APP_5,
+  LAUNCH_APP_6,
+  LAUNCH_APP_7,
+  LAUNCH_LAST_APP,
+  LOCK_PRESSED,
+  LOCK_RELEASED,
+  LOCK_SCREEN,
+  MAGNIFIER_ZOOM_IN,
+  MAGNIFIER_ZOOM_OUT,
+  MEDIA_NEXT_TRACK,
+  MEDIA_PLAY_PAUSE,
+  MEDIA_PREV_TRACK,
+  MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS,
+  NEW_INCOGNITO_WINDOW,
+  NEW_TAB,
+  NEW_WINDOW,
+  NEXT_IME,
+  OPEN_CROSH,
+  OPEN_FEEDBACK_PAGE,
+  OPEN_FILE_MANAGER,
+  OPEN_GET_HELP,
+  POWER_PRESSED,
+  POWER_RELEASED,
+  PREVIOUS_IME,
+  PRINT_UI_HIERARCHIES,
+  RESTORE_TAB,
+  ROTATE_SCREEN,
+  ROTATE_WINDOW,
+  SCALE_UI_DOWN,
+  SCALE_UI_RESET,
+  SCALE_UI_UP,
+  SHOW_IME_MENU_BUBBLE,
+  SHOW_KEYBOARD_OVERLAY,
+  SHOW_STYLUS_TOOLS,
+  SHOW_TASK_MANAGER,
+  START_VOICE_INTERACTION,
+  SUSPEND,
+  SWAP_PRIMARY_DISPLAY,
+  SWITCH_IME,  // Switch to another IME depending on the accelerator.
+  SWITCH_TO_NEXT_USER,
+  SWITCH_TO_PREVIOUS_USER,
+  TAKE_PARTIAL_SCREENSHOT,
+  TAKE_SCREENSHOT,
+  TAKE_WINDOW_SCREENSHOT,
+  TOGGLE_APP_LIST,
+  TOGGLE_CAPS_LOCK,
+  TOGGLE_DICTATION,
+  TOGGLE_FULLSCREEN,
+  TOGGLE_HIGH_CONTRAST,
+  TOGGLE_MAXIMIZED,
+  TOGGLE_MESSAGE_CENTER_BUBBLE,
+  TOGGLE_MIRROR_MODE,
+  TOGGLE_OVERVIEW,
+  TOGGLE_SPOKEN_FEEDBACK,
+  TOGGLE_SYSTEM_TRAY_BUBBLE,
+  TOGGLE_WIFI,
+  TOUCH_HUD_CLEAR,
+  TOUCH_HUD_MODE_CHANGE,
+  UNPIN,
+  VOLUME_DOWN,
+  VOLUME_MUTE,
+  VOLUME_UP,
+  WINDOW_CYCLE_SNAP_LEFT,
+  WINDOW_CYCLE_SNAP_RIGHT,
+  WINDOW_MINIMIZE,
+  WINDOW_POSITION_CENTER,
+};
+
+struct AcceleratorData {
+  bool trigger_on_press;
+  ui::KeyboardCode keycode;
+  int modifiers;
+  AcceleratorAction action;
+};
+
+// A mask of all the modifiers used for debug accelerators.
+ASH_PUBLIC_EXPORT extern const int kDebugModifier;
+
+// Accelerators handled by AcceleratorController.
+ASH_PUBLIC_EXPORT extern const AcceleratorData kAcceleratorData[];
+ASH_PUBLIC_EXPORT extern const size_t kAcceleratorDataLength;
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ACCELERATORS_H_
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index f105cdd..5cd1b17 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -20,6 +20,8 @@
     "lock_screen_backspace.icon",
     "lock_screen_caps_lock.icon",
     "lock_screen_dropdown.icon",
+    "login_screen_button_dropdown.icon",
+    "login_screen_menu_dropdown.icon",
     "login_screen_enterprise.icon",
     "network_badge_add_other.icon",
     "network_badge_captive_portal.icon",
diff --git a/ash/resources/vector_icons/login_screen_button_dropdown.icon b/ash/resources/vector_icons/login_screen_button_dropdown.icon
new file mode 100644
index 0000000..c25a872
--- /dev/null
+++ b/ash/resources/vector_icons/login_screen_button_dropdown.icon
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+MOVE_TO, 8.35f, 11,
+LINE_TO, 16, 17.18f,
+LINE_TO, 23.65f, 11,
+LINE_TO, 26, 12.9f,
+LINE_TO, 16, 21,
+LINE_TO, 6, 12.9f,
+CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4.18f, 5.5f,
+LINE_TO, 8, 8.59f,
+R_LINE_TO, 3.83f, -3.09f,
+LINE_TO, 13, 6.45f,
+LINE_TO, 8, 10.5f,
+LINE_TO, 3, 6.45f,
+CLOSE
diff --git a/ash/resources/vector_icons/login_screen_menu_dropdown.icon b/ash/resources/vector_icons/login_screen_menu_dropdown.icon
new file mode 100644
index 0000000..432050a
--- /dev/null
+++ b/ash/resources/vector_icons/login_screen_menu_dropdown.icon
@@ -0,0 +1,15 @@
+// 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.
+
+CANVAS_DIMENSIONS, 32,
+MOVE_TO, 8, 12,
+R_LINE_TO, 8, 8,
+R_LINE_TO, 8, -8,
+CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4, 6,
+R_LINE_TO, 4, 4,
+R_LINE_TO, 4, -4,
+CLOSE
diff --git a/ash/strings/ash_strings_zh-CN.xtb b/ash/strings/ash_strings_zh-CN.xtb
index 68be1db..b5b0da1 100644
--- a/ash/strings/ash_strings_zh-CN.xtb
+++ b/ash/strings/ash_strings_zh-CN.xtb
@@ -32,6 +32,7 @@
 <translation id="1658406695958299976">抱歉,系统仍然无法验证您的密码。注意:如果您最近更改了密码,新密码将在您退出后生效。目前请在此处输入旧密码。</translation>
 <translation id="1677472565718498478">电量尚余 <ph name="TIME" /></translation>
 <translation id="1698760176351776263">IPv6 地址:<ph name="ADDRESS" /></translation>
+<translation id="170389796989115980">设备管理员或许能监控您的活动。</translation>
 <translation id="1734367976349034509">此设备是受企业管理的设备</translation>
 <translation id="1746730358044914197">输入法是由您的管理员配置的。</translation>
 <translation id="1747827819627189109">屏幕键盘已启用</translation>
@@ -46,6 +47,7 @@
 <translation id="1942830294380034169">溢出按钮</translation>
 <translation id="1951012854035635156">智能助理</translation>
 <translation id="1957803754585243749">0°</translation>
+<translation id="1957958912175573503">设置语言</translation>
 <translation id="1969011864782743497"><ph name="DEVICE_NAME" /> (USB)</translation>
 <translation id="1995660704900986789">关机</translation>
 <translation id="2012624427112548395">Ctrl+搜索键+H</translation>
@@ -81,6 +83,8 @@
 <translation id="2653659639078652383">提交</translation>
 <translation id="2675319268637823299">管理员已禁止 <ph name="USER_EMAIL" /> 使用多帐号登录功能。
     所有用户都必须先退出帐号才能继续。</translation>
+<translation id="2696763960464195425">当您退出后,系统即会移除您的信息。<ph name="LEARN_MORE" /></translation>
+<translation id="2700493154570097719">设置键盘</translation>
 <translation id="2718395828230677721">夜间模式</translation>
 <translation id="2727977024730340865">已插入低功率充电器;可能无法保证充电成功。</translation>
 <translation id="2761704814324807722">状态栏,时间为<ph name="TIME" />,<ph name="BATTERY" /></translation>
@@ -331,6 +335,7 @@
 <translation id="8673028979667498656">270°</translation>
 <translation id="8676770494376880701">已连接低功率充电器</translation>
 <translation id="8734991477317290293">当前连接的键盘可能会试图窃取您的击键操作</translation>
+<translation id="8809737090443522491">输入应用或文档的名称</translation>
 <translation id="8814190375133053267">Wi-Fi</translation>
 <translation id="8814715559352963456">将窗口移至其他桌面可能会导致出现意外行为。
 
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
index a640331f..2f9cc49 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
@@ -34,7 +34,7 @@
   return button_;
 }
 
-void BluetoothFeaturePodController::OnPressed() {
+void BluetoothFeaturePodController::OnIconPressed() {
   tray_controller_->ShowBluetoothDetailedView();
 }
 
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller.h b/ash/system/bluetooth/bluetooth_feature_pod_controller.h
index 9ec4f76..bd71d02 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller.h
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller.h
@@ -23,7 +23,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   void UpdateButton();
diff --git a/ash/system/ime/ime_feature_pod_controller.cc b/ash/system/ime/ime_feature_pod_controller.cc
index badb87c..3c3de03c0 100644
--- a/ash/system/ime/ime_feature_pod_controller.cc
+++ b/ash/system/ime/ime_feature_pod_controller.cc
@@ -52,7 +52,7 @@
   return button_;
 }
 
-void IMEFeaturePodController::OnPressed() {
+void IMEFeaturePodController::OnIconPressed() {
   tray_controller_->ShowIMEDetailedView();
 }
 
diff --git a/ash/system/ime/ime_feature_pod_controller.h b/ash/system/ime/ime_feature_pod_controller.h
index 8e2814b..8a2f487 100644
--- a/ash/system/ime/ime_feature_pod_controller.h
+++ b/ash/system/ime/ime_feature_pod_controller.h
@@ -21,7 +21,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   void Update();
diff --git a/ash/system/network/network_feature_pod_controller.cc b/ash/system/network/network_feature_pod_controller.cc
index 2012d0b..4fd92c65 100644
--- a/ash/system/network/network_feature_pod_controller.cc
+++ b/ash/system/network/network_feature_pod_controller.cc
@@ -24,7 +24,7 @@
   return button_;
 }
 
-void NetworkFeaturePodController::OnPressed() {
+void NetworkFeaturePodController::OnIconPressed() {
   tray_controller_->ShowNetworkDetailedView();
 }
 
diff --git a/ash/system/network/network_feature_pod_controller.h b/ash/system/network/network_feature_pod_controller.h
index 7d526fc4c..5104368 100644
--- a/ash/system/network/network_feature_pod_controller.h
+++ b/ash/system/network/network_feature_pod_controller.h
@@ -21,7 +21,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   // Unowned.
diff --git a/ash/system/network/vpn_feature_pod_controller.cc b/ash/system/network/vpn_feature_pod_controller.cc
index 1f404c7..9d34a26 100644
--- a/ash/system/network/vpn_feature_pod_controller.cc
+++ b/ash/system/network/vpn_feature_pod_controller.cc
@@ -53,7 +53,7 @@
   return button_;
 }
 
-void VPNFeaturePodController::OnPressed() {
+void VPNFeaturePodController::OnIconPressed() {
   tray_controller_->ShowVPNDetailedView();
 }
 
diff --git a/ash/system/network/vpn_feature_pod_controller.h b/ash/system/network/vpn_feature_pod_controller.h
index ba67534..9ae68b93 100644
--- a/ash/system/network/vpn_feature_pod_controller.h
+++ b/ash/system/network/vpn_feature_pod_controller.h
@@ -21,7 +21,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   void Update();
diff --git a/ash/system/night_light/night_light_feature_pod_controller.cc b/ash/system/night_light/night_light_feature_pod_controller.cc
index 685a65b..0e533ce 100644
--- a/ash/system/night_light/night_light_feature_pod_controller.cc
+++ b/ash/system/night_light/night_light_feature_pod_controller.cc
@@ -28,7 +28,7 @@
   return button_;
 }
 
-void NightLightFeaturePodController::OnPressed() {
+void NightLightFeaturePodController::OnIconPressed() {
   DCHECK(switches::IsNightLightEnabled());
   Shell::Get()->night_light_controller()->Toggle();
   UpdateButton();
diff --git a/ash/system/night_light/night_light_feature_pod_controller.h b/ash/system/night_light/night_light_feature_pod_controller.h
index 9b7243f..fc9534d9 100644
--- a/ash/system/night_light/night_light_feature_pod_controller.h
+++ b/ash/system/night_light/night_light_feature_pod_controller.h
@@ -18,7 +18,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   void UpdateButton();
diff --git a/ash/system/rotation/rotation_lock_feature_pod_controller.cc b/ash/system/rotation/rotation_lock_feature_pod_controller.cc
index d43535c..c24d34a2 100644
--- a/ash/system/rotation/rotation_lock_feature_pod_controller.cc
+++ b/ash/system/rotation/rotation_lock_feature_pod_controller.cc
@@ -35,7 +35,7 @@
   return button_;
 }
 
-void RotationLockFeaturePodController::OnPressed() {
+void RotationLockFeaturePodController::OnIconPressed() {
   Shell::Get()->screen_orientation_controller()->ToggleUserRotationLock();
 }
 
diff --git a/ash/system/rotation/rotation_lock_feature_pod_controller.h b/ash/system/rotation/rotation_lock_feature_pod_controller.h
index 29312880c..f98dbd42 100644
--- a/ash/system/rotation/rotation_lock_feature_pod_controller.h
+++ b/ash/system/rotation/rotation_lock_feature_pod_controller.h
@@ -24,7 +24,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
   // TabletModeObserver:
   void OnTabletModeStarted() override;
diff --git a/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc b/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
index d917dc43..1107e5b 100644
--- a/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
+++ b/ash/system/rotation/rotation_lock_feature_pod_controller_unittest.cc
@@ -85,7 +85,7 @@
   EXPECT_FALSE(button_view()->visible());
 }
 
-TEST_F(RotationLockFeaturePodControllerTest, OnPressed) {
+TEST_F(RotationLockFeaturePodControllerTest, OnIconPressed) {
   SetUpController();
   TabletModeController* tablet_mode_controller =
       Shell::Get()->tablet_mode_controller();
@@ -96,12 +96,12 @@
   ASSERT_TRUE(button_view()->visible());
   EXPECT_FALSE(button_view()->IsToggled());
 
-  controller()->OnPressed();
+  controller()->OnIconPressed();
   EXPECT_TRUE(screen_orientation_controller->rotation_locked());
   EXPECT_TRUE(button_view()->visible());
   EXPECT_TRUE(button_view()->IsToggled());
 
-  controller()->OnPressed();
+  controller()->OnIconPressed();
   EXPECT_FALSE(screen_orientation_controller->rotation_locked());
   EXPECT_TRUE(button_view()->visible());
   EXPECT_FALSE(button_view()->IsToggled());
diff --git a/ash/system/unified/accessibility_feature_pod_controller.cc b/ash/system/unified/accessibility_feature_pod_controller.cc
index 9eb6442..9e24305 100644
--- a/ash/system/unified/accessibility_feature_pod_controller.cc
+++ b/ash/system/unified/accessibility_feature_pod_controller.cc
@@ -35,7 +35,7 @@
   return button;
 }
 
-void AccessibilityFeaturePodController::OnPressed() {
+void AccessibilityFeaturePodController::OnIconPressed() {
   tray_controller_->ShowAccessibilityDetailedView();
 }
 
diff --git a/ash/system/unified/accessibility_feature_pod_controller.h b/ash/system/unified/accessibility_feature_pod_controller.h
index 61db87e1..214d97e4 100644
--- a/ash/system/unified/accessibility_feature_pod_controller.h
+++ b/ash/system/unified/accessibility_feature_pod_controller.h
@@ -23,7 +23,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
  private:
   // Unowned.
diff --git a/ash/system/unified/feature_pod_button.cc b/ash/system/unified/feature_pod_button.cc
index 835d528..263809f 100644
--- a/ash/system/unified/feature_pod_button.cc
+++ b/ash/system/unified/feature_pod_button.cc
@@ -183,7 +183,11 @@
 
 void FeaturePodButton::ButtonPressed(views::Button* sender,
                                      const ui::Event& event) {
-  controller_->OnPressed();
+  if (sender == label_button_) {
+    controller_->OnLabelPressed();
+    return;
+  }
+  controller_->OnIconPressed();
 }
 
 }  // namespace ash
diff --git a/ash/system/unified/feature_pod_controller_base.cc b/ash/system/unified/feature_pod_controller_base.cc
new file mode 100644
index 0000000..bc09852
--- /dev/null
+++ b/ash/system/unified/feature_pod_controller_base.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 "ash/system/unified/feature_pod_controller_base.h"
+
+namespace ash {
+
+void FeaturePodControllerBase::OnLabelPressed() {
+  return OnIconPressed();
+}
+
+}  // namespace ash
diff --git a/ash/system/unified/feature_pod_controller_base.h b/ash/system/unified/feature_pod_controller_base.h
index 74f42b3..675f1d1b 100644
--- a/ash/system/unified/feature_pod_controller_base.h
+++ b/ash/system/unified/feature_pod_controller_base.h
@@ -5,6 +5,8 @@
 #ifndef ASH_SYSTEM_UNIFIED_FEATURE_POD_CONTROLLER_BASE_H_
 #define ASH_SYSTEM_UNIFIED_FEATURE_POD_CONTROLLER_BASE_H_
 
+#include "ash/ash_export.h"
+
 namespace ash {
 
 class FeaturePodButton;
@@ -12,7 +14,7 @@
 // Base class for controllers of feature pod buttons.
 // To add a new feature pod button, implement this class, and add to the list in
 // UnifiedSystemTrayController::InitFeaturePods().
-class FeaturePodControllerBase {
+class ASH_EXPORT FeaturePodControllerBase {
  public:
   virtual ~FeaturePodControllerBase() {}
 
@@ -22,8 +24,14 @@
   // this).
   virtual FeaturePodButton* CreateButton() = 0;
 
-  // Called when the feature pod button is clicked.
-  virtual void OnPressed() = 0;
+  // Called when the icon of the feature pod button is clicked.
+  // If the feature pod is togglable, it is expected to toggle the feature.
+  virtual void OnIconPressed() = 0;
+
+  // Called when the label hover area of the feature pod button is clicked.
+  // If the feature pod has a detailed view, it is expected to show the detailed
+  // view. Defaults to OnIconPressed().
+  virtual void OnLabelPressed();
 };
 
 }  // namespace ash
diff --git a/ash/system/unified/feature_pods_container_view_unittest.cc b/ash/system/unified/feature_pods_container_view_unittest.cc
index 8a8a4f2..29aee9b 100644
--- a/ash/system/unified/feature_pods_container_view_unittest.cc
+++ b/ash/system/unified/feature_pods_container_view_unittest.cc
@@ -29,7 +29,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override { return nullptr; }
-  void OnPressed() override {}
+  void OnIconPressed() override {}
 
   // views::ViewObserver:
   void OnViewPreferredSizeChanged(views::View* observed_view) override {
diff --git a/ash/system/unified/quiet_mode_feature_pod_controller.cc b/ash/system/unified/quiet_mode_feature_pod_controller.cc
index 72b3e0c..b21af8a 100644
--- a/ash/system/unified/quiet_mode_feature_pod_controller.cc
+++ b/ash/system/unified/quiet_mode_feature_pod_controller.cc
@@ -31,7 +31,7 @@
   return button_;
 }
 
-void QuietModeFeaturePodController::OnPressed() {
+void QuietModeFeaturePodController::OnIconPressed() {
   MessageCenter* message_center = MessageCenter::Get();
   bool is_quiet_mode = message_center->IsQuietMode();
   message_center->SetQuietMode(!is_quiet_mode);
diff --git a/ash/system/unified/quiet_mode_feature_pod_controller.h b/ash/system/unified/quiet_mode_feature_pod_controller.h
index ed14228..3ef9375 100644
--- a/ash/system/unified/quiet_mode_feature_pod_controller.h
+++ b/ash/system/unified/quiet_mode_feature_pod_controller.h
@@ -24,7 +24,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
-  void OnPressed() override;
+  void OnIconPressed() override;
 
   // message_center::MessageCenterObserver:
   void OnQuietModeChanged(bool in_quiet_mode) override;
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 0816cca..e103a48b 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -1742,6 +1742,7 @@
 }
 
 void WallpaperController::ReloadWallpaper(bool clear_cache) {
+  current_wallpaper_.reset();
   if (clear_cache)
     wallpaper_cache_map_.clear();
 
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 48097b3..b228c52 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -1493,18 +1493,26 @@
       {wallpaper_dir_->GetPath().Append(kDefaultSmallWallpaperName)}));
 }
 
-// If clients call |ShowUserWallpaper| twice with the same account id, the
-// latter request should be prevented (See crbug.com/158383).
-TEST_F(WallpaperControllerTest, PreventReloadingSameWallpaper) {
+TEST_F(WallpaperControllerTest, ReloadWallpaper) {
   CreateAndSaveWallpapers(account_id_1);
+
+  // If |ShowUserWallpaper| is called twice with the same account id and display
+  // size, the second request shouldn't trigger a wallpaper reload
+  // (crbug.com/158383).
+  UpdateDisplay("800x600");
+  RunAllTasksUntilIdle();
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
 
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   RunAllTasksUntilIdle();
-  // No wallpaper is set for the second |ShowUserWallpaper| request.
   EXPECT_EQ(0, GetWallpaperCount());
+
+  // Rotating the display should trigger a wallpaper reload.
+  UpdateDisplay("800x600/r");
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(1, GetWallpaperCount());
 }
 
 TEST_F(WallpaperControllerTest, UpdateCustomWallpaperLayout) {
@@ -1692,49 +1700,6 @@
   controller_->RemoveObserver(&observer);
 }
 
-TEST_F(WallpaperControllerTest, WallpaperBlurDisabledByPolicy) {
-  // Simulate DEVICE policy wallpaper.
-  const WallpaperInfo info("", WALLPAPER_LAYOUT_CENTER, DEVICE,
-                           base::Time::Now());
-  const gfx::ImageSkia image = CreateImage(10, 10, kWallpaperColor);
-  controller_->ShowWallpaperImage(image, info, false /*preview_mode=*/);
-  ASSERT_FALSE(controller_->IsBlurEnabled());
-  ASSERT_FALSE(controller_->IsWallpaperBlurred());
-
-  TestWallpaperControllerObserver observer;
-  controller_->AddObserver(&observer);
-
-  SetSessionState(SessionState::ACTIVE);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::LOCKED);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::LOGIN_SECONDARY);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::LOGIN_PRIMARY);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::OOBE);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  SetSessionState(SessionState::UNKNOWN);
-  EXPECT_FALSE(controller_->IsWallpaperBlurred());
-  EXPECT_EQ(0, observer.wallpaper_blur_changed_count_);
-
-  controller_->RemoveObserver(&observer);
-}
-
 TEST_F(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
   ASSERT_TRUE(controller_->IsBlurEnabled());
   ASSERT_FALSE(controller_->IsWallpaperBlurred());
@@ -1768,6 +1733,9 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_TRUE(IsDevicePolicyWallpaper());
+  // Verify the device policy wallpaper shouldn't be blurred.
+  ASSERT_FALSE(controller_->IsBlurEnabled());
+  ASSERT_FALSE(controller_->IsWallpaperBlurred());
 
   // Verify the device policy wallpaper is replaced when session state is no
   // longer LOGIN_PRIMARY.
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc
index 5f3936d..c31061a 100644
--- a/ash/wm/overview/window_selector_controller.cc
+++ b/ash/wm/overview/window_selector_controller.cc
@@ -114,8 +114,8 @@
     if (!IsNewOverviewUi() && windows.empty())
       return false;
 
-    Shell::Get()->NotifyOverviewModeStarting();
     window_selector_.reset(new WindowSelector(this));
+    Shell::Get()->NotifyOverviewModeStarting();
     window_selector_->Init(windows, hide_windows);
     OnSelectionStarted();
   }
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 22e397f..252691b 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -57,6 +57,14 @@
 constexpr float kOneThirdPositionRatio = 0.33f;
 constexpr float kTwoThirdPositionRatio = 0.67f;
 
+// The black scrim starts to fade in when the divider is moved past the two
+// optional positions (kOneThirdPositionRatio, kTwoThirdPositionRatio) and
+// reaches to its maximum opacity (kBlackScrimOpacity) after moving
+// kBlackScrimFadeInRatio of the screen width. See https://crbug.com/827730 for
+// details.
+constexpr float kBlackScrimFadeInRatio = 0.1f;
+constexpr float kBlackScrimOpacity = 0.4f;
+
 // Toast data.
 constexpr char kAppCannotSnapToastId[] = "split_view_app_cannot_snap";
 constexpr int kAppCannotSnapToastDurationMs = 2500;
@@ -774,19 +782,21 @@
 
   // Update its opacity. The opacity increases as it gets closer to the edge of
   // the screen.
-  float opacity = 0.f;
-  const gfx::Rect work_area_bounds =
+  const int location = IsCurrentScreenOrientationLandscape()
+                           ? location_in_screen.x()
+                           : location_in_screen.y();
+  gfx::Rect work_area_bounds =
       GetDisplayWorkAreaBoundsInScreen(GetDefaultSnappedWindow());
-  if (IsCurrentScreenOrientationLandscape()) {
-    int distance_x =
-        std::min(std::abs(location_in_screen.x() - work_area_bounds.x()),
-                 std::abs(work_area_bounds.right() - location_in_screen.x()));
-    opacity = 1.f - float(distance_x) / float(work_area_bounds.width());
-  } else {
-    int distance_y =
-        std::min(std::abs(location_in_screen.y() - work_area_bounds.y()),
-                 std::abs(work_area_bounds.bottom() - location_in_screen.y()));
-    opacity = 1.f - float(distance_y) / float(work_area_bounds.height());
+  if (!IsCurrentScreenOrientationLandscape())
+    TransposeRect(&work_area_bounds);
+  float opacity = kBlackScrimOpacity;
+  const float ratio = kOneThirdPositionRatio - kBlackScrimFadeInRatio;
+  const int distance = std::min(std::abs(location - work_area_bounds.x()),
+                                std::abs(work_area_bounds.right() - location));
+  if (distance > work_area_bounds.width() * ratio) {
+    opacity -= kBlackScrimOpacity *
+               (distance - work_area_bounds.width() * ratio) /
+               (work_area_bounds.width() * kBlackScrimFadeInRatio);
   }
   black_scrim_layer_->SetOpacity(opacity);
 }
diff --git a/ash/wm/workspace/backdrop_controller.cc b/ash/wm/workspace/backdrop_controller.cc
index d561d15..1491014 100644
--- a/ash/wm/workspace/backdrop_controller.cc
+++ b/ash/wm/workspace/backdrop_controller.cc
@@ -8,16 +8,19 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_delegate.h"
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/public/cpp/app_types.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller.h"
+#include "ash/wm/overview/window_selector_controller.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace/backdrop_delegate.h"
 #include "base/auto_reset.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "ui/app_list/app_list_features.h"
+#include "ui/app_list/views/app_list_view.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -111,9 +114,26 @@
 }
 
 void BackdropController::UpdateBackdrop() {
-  // Avoid recursive calls.
-  if (in_restacking_ || force_hidden_counter_)
+  // No need to continue update for recursive calls or in overview mode.
+  WindowSelectorController* window_selector_controller =
+      Shell::Get()->window_selector_controller();
+  if (in_restacking_ || (window_selector_controller &&
+                         window_selector_controller->IsSelecting())) {
     return;
+  }
+
+  AppListControllerImpl* app_list_controller =
+      Shell::Get()->app_list_controller();
+  // Only hide the backdrop of the display that launcher is opened at.
+  if (app_list_controller->IsVisible() &&
+      container_->GetRootWindow() == app_list_controller->presenter()
+                                         ->GetView()
+                                         ->GetWidget()
+                                         ->GetNativeView()
+                                         ->GetRootWindow()) {
+    Hide();
+    return;
+  }
 
   aura::Window* window = GetTopmostWindowWithBackdrop();
   if (!window) {
@@ -141,23 +161,16 @@
 }
 
 void BackdropController::OnOverviewModeStarting() {
-  AddForceHidden();
+  Hide();
 }
 
 void BackdropController::OnOverviewModeEnded() {
-  RemoveForceHidden();
+  UpdateBackdrop();
 }
 
 void BackdropController::OnAppListVisibilityChanged(bool shown,
                                                     aura::Window* root_window) {
-  // Ignore the notification if it is not for this display.
-  if (container_->GetRootWindow() != root_window)
-    return;
-
-  if (shown)
-    AddForceHidden();
-  else
-    RemoveForceHidden();
+  UpdateBackdrop();
 }
 
 void BackdropController::OnSplitViewModeStarting() {
@@ -285,24 +298,6 @@
   backdrop_event_handler_.reset();
 }
 
-void BackdropController::AddForceHidden() {
-  force_hidden_counter_++;
-  CHECK_GE(force_hidden_counter_, 0);
-  if (force_hidden_counter_)
-    Hide();
-  else
-    UpdateBackdrop();
-}
-
-void BackdropController::RemoveForceHidden() {
-  force_hidden_counter_--;
-  CHECK_GE(force_hidden_counter_, 0);
-  if (force_hidden_counter_)
-    Hide();
-  else
-    UpdateBackdrop();
-}
-
 bool BackdropController::BackdropShouldFullscreen() {
   aura::Window* window = GetTopmostWindowWithBackdrop();
   SplitViewController* split_view_controller =
diff --git a/ash/wm/workspace/backdrop_controller.h b/ash/wm/workspace/backdrop_controller.h
index cc70f43..f4d2b9f 100644
--- a/ash/wm/workspace/backdrop_controller.h
+++ b/ash/wm/workspace/backdrop_controller.h
@@ -102,12 +102,6 @@
   // Hide the backdrop window.
   void Hide();
 
-  // Increment |force_hidden_counter_| and then update backdrop state.
-  void AddForceHidden();
-
-  // Decrement |force_hidden_counter_| and then update backdrop state.
-  void RemoveForceHidden();
-
   // Returns true if the backdrop window should be fullscreen. It should not be
   // fullscreen only if 1) split view is active and 2) there is only one snapped
   // window and 3) the snapped window is the topmost window which should have
@@ -138,10 +132,6 @@
   // If true, the |RestackOrHideWindow| might recurse.
   bool in_restacking_ = false;
 
-  // Hide the backdrop if the counter is larger than 0. The counter is
-  // maintained by overview mode, split view and app list visibility state.
-  int force_hidden_counter_ = 0;
-
   DISALLOW_COPY_AND_ASSIGN(BackdropController);
 };
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 9fc9802..b0d0d80 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1301,6 +1301,7 @@
       "debug/stack_trace_posix.cc",
       "message_loop/message_pump_libevent.cc",
       "message_loop/message_pump_libevent.h",
+      "native_library_posix.cc",
       "posix/unix_domain_socket.cc",
       "posix/unix_domain_socket.h",
       "process/kill_posix.cc",
@@ -1327,6 +1328,7 @@
       "memory/shared_memory_handle_fuchsia.cc",
       "message_loop/message_pump_fuchsia.cc",
       "message_loop/message_pump_fuchsia.h",
+      "native_library_fuchsia.cc",
       "process/kill_fuchsia.cc",
       "process/launch_fuchsia.cc",
       "process/memory_fuchsia.cc",
@@ -1455,7 +1457,7 @@
       if (is_win) {
         sources +=
             [ "allocator/partition_allocator/page_allocator_internals_win.h" ]
-      } else if (is_posix) {
+      } else if (is_posix || is_fuchsia) {
         sources +=
             [ "allocator/partition_allocator/page_allocator_internals_posix.h" ]
       }
@@ -1669,20 +1671,20 @@
     set_sources_assignment_filter(sources_assignment_filter)
   }
 
-  # Android, Fuchsia, and MacOS have their own custom shared memory handle
+  # Android and MacOS have their own custom shared memory handle
   # implementations. e.g. due to supporting both POSIX and native handles.
-  if (is_posix && !is_android && !is_fuchsia && !is_mac) {
+  if (is_posix && !is_android && !is_mac) {
     sources += [
       "memory/platform_shared_memory_region_posix.cc",
       "memory/shared_memory_handle_posix.cc",
     ]
   }
 
-  if (is_posix && !is_fuchsia && !is_mac && !is_nacl) {
+  if (is_posix && !is_mac && !is_nacl) {
     sources += [ "memory/shared_memory_posix.cc" ]
   }
 
-  if (is_posix && !is_fuchsia && !is_mac && !is_ios) {
+  if (is_posix && !is_mac && !is_ios) {
     sources += [
       "time/time_conversion_posix.cc",
       "time/time_exploded_posix.cc",
@@ -1690,8 +1692,9 @@
     ]
   }
 
-  if (is_posix && !is_mac && !is_ios && !is_android && !is_chromeos) {
-    sources += [ "power_monitor/power_monitor_device_source_posix.cc" ]
+  if ((is_posix && !is_mac && !is_ios && !is_android && !is_chromeos) ||
+      is_fuchsia) {
+    sources += [ "power_monitor/power_monitor_device_source_stub.cc" ]
   }
 
   if (!use_glib) {
@@ -2498,7 +2501,7 @@
     sources -= [ "message_loop/message_pump_glib_unittest.cc" ]
   }
 
-  if (is_posix && !is_ios && !is_fuchsia) {
+  if (is_posix && !is_ios) {
     sources += [ "message_loop/message_pump_libevent_unittest.cc" ]
     deps += [ "//base/third_party/libevent" ]
   }
diff --git a/base/native_library_fuchsia.cc b/base/native_library_fuchsia.cc
new file mode 100644
index 0000000..1d68cbd
--- /dev/null
+++ b/base/native_library_fuchsia.cc
@@ -0,0 +1,95 @@
+// 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/native_library.h"
+
+#include <fcntl.h>
+#include <fdio/io.h>
+#include <stdio.h>
+#include <zircon/dlfcn.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
+
+#include "base/base_paths_fuchsia.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/scoped_zx_handle.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/posix/safe_strerror.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+
+namespace base {
+
+std::string NativeLibraryLoadError::ToString() const {
+  return message;
+}
+
+NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path,
+                                           const NativeLibraryOptions& options,
+                                           NativeLibraryLoadError* error) {
+  std::vector<base::FilePath::StringType> components;
+  library_path.GetComponents(&components);
+  if (components.size() != 1u) {
+    NOTREACHED() << "library_path is a path, should be a filename: "
+                 << library_path.MaybeAsASCII();
+    return nullptr;
+  }
+
+  // Fuchsia libraries must live under the "lib" directory, which may be located
+  // in /system/lib or /pkg/lib depending on whether the executable is running
+  // inside a package.
+  // TODO(https://crbug.com/805057): Remove the non-package codepath when bootfs
+  // is deprecated.
+  FilePath computed_path = base::GetPackageRoot();
+  if (computed_path.empty()) {
+    CHECK(PathService::Get(DIR_EXE, &computed_path));
+  }
+  computed_path = computed_path.AppendASCII("lib").Append(components[0]);
+  base::File library(computed_path,
+                     base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!library.IsValid()) {
+    if (error) {
+      error->message = base::StringPrintf(
+          "open library: %s",
+          base::File::ErrorToString(library.error_details()).c_str());
+    }
+    return nullptr;
+  }
+
+  base::ScopedZxHandle vmo;
+  zx_status_t status =
+      fdio_get_vmo_clone(library.GetPlatformFile(), vmo.receive());
+  if (status != ZX_OK) {
+    if (error) {
+      error->message = base::StringPrintf("fdio_get_vmo_clone: %s",
+                                          zx_status_get_string(status));
+    }
+    return nullptr;
+  }
+  NativeLibrary result = dlopen_vmo(vmo.get(), RTLD_LAZY | RTLD_LOCAL);
+  return result;
+}
+
+void UnloadNativeLibrary(NativeLibrary library) {
+  // dlclose() is a no-op on Fuchsia, so do nothing here.
+}
+
+void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
+                                          StringPiece name) {
+  return dlsym(library, name.data());
+}
+
+std::string GetNativeLibraryName(StringPiece name) {
+  return base::StringPrintf("lib%s.so", name.as_string().c_str());
+}
+
+std::string GetLoadableModuleName(StringPiece name) {
+  return GetNativeLibraryName(name);
+}
+
+}  // namespace base
diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc
index 2875014..8b400171 100644
--- a/base/native_library_unittest.cc
+++ b/base/native_library_unittest.cc
@@ -77,7 +77,12 @@
   explicit TestLibrary(const NativeLibraryOptions& options)
     : library_(nullptr) {
     base::FilePath exe_path;
+
+#if !defined(OS_FUCHSIA)
+    // Libraries do not sit alongside the executable in Fuchsia. NativeLibrary
+    // is aware of this and is able to resolve library paths correctly.
     CHECK(base::PathService::Get(base::DIR_EXE, &exe_path));
+#endif
 
     library_ = LoadNativeLibraryWithOptions(
         exe_path.AppendASCII(kTestLibraryName), options, nullptr);
diff --git a/base/power_monitor/power_monitor_device_source_posix.cc b/base/power_monitor/power_monitor_device_source_stub.cc
similarity index 100%
rename from base/power_monitor/power_monitor_device_source_posix.cc
rename to base/power_monitor/power_monitor_device_source_stub.cc
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 5537bbd4..73977c8 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -178,7 +178,7 @@
     "//third_party/libxml",
   ]
 
-  if (!is_posix) {
+  if (!is_posix && !is_fuchsia) {
     sources -= [
       "scoped_locale.cc",
       "scoped_locale.h",
diff --git a/base/trace_event/cfi_backtrace_android_unittest.cc b/base/trace_event/cfi_backtrace_android_unittest.cc
index b3a0d81..3ad3d330 100644
--- a/base/trace_event/cfi_backtrace_android_unittest.cc
+++ b/base/trace_event/cfi_backtrace_android_unittest.cc
@@ -45,7 +45,8 @@
   }
 }
 
-TEST(CFIBacktraceAndroidTest, TestFindCFIRow) {
+// Flaky: https://bugs.chromium.org/p/chromium/issues/detail?id=829555
+TEST(CFIBacktraceAndroidTest, DISABLED_TestFindCFIRow) {
   auto* unwinder = CFIBacktraceAndroid::GetInitializedInstance();
   /* Input is generated from the CFI file:
   STACK CFI INIT 1000 500
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 3856800..9e38ee0 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -349,7 +349,7 @@
   is_linux = false
   is_mac = false
   is_nacl = false
-  is_posix = true
+  is_posix = false
   is_win = false
 } else if (current_os == "ios") {
   is_android = false
@@ -400,7 +400,9 @@
 # DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call
 # below.
 sources_assignment_filter = []
-if (!is_posix) {
+
+# TODO(crbug.com/812974): Clean up _posix files and remove Fuchsia here.
+if (!is_posix && !is_fuchsia) {
   sources_assignment_filter += [
     "*_posix.h",
     "*_posix.cc",
@@ -557,6 +559,10 @@
   }
 }
 
+if (is_fuchsia) {
+  default_compiler_configs += [ "//build/config/gcc:symbol_visibility_hidden" ]
+}
+
 if (is_android) {
   default_compiler_configs +=
       [ "//build/config/android:default_cygprofile_instrumentation" ]
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index ea1c7ed..0141214 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -145,12 +145,12 @@
   # other architectures.
   #
   # lld doesn't have the bug.
-  use_icf =
-      is_posix && !using_sanitizer && !(is_android && use_order_profiling) &&
-      ((use_lld && !is_nacl) ||
-       (use_gold &&
-        ((!is_android && linux_use_bundled_binutils) || is_chromeos ||
-         !(current_cpu == "x86" || current_cpu == "x64"))))
+  use_icf = (is_posix || is_fuchsia) && !using_sanitizer &&
+            !(is_android && use_order_profiling) &&
+            ((use_lld && !is_nacl) ||
+             (use_gold &&
+              ((!is_android && linux_use_bundled_binutils) || is_chromeos ||
+               !(current_cpu == "x86" || current_cpu == "x64"))))
 }
 
 # Apply the default logic for these values if they were not set explicitly.
@@ -253,7 +253,7 @@
       } else {
         cflags += [ "-fstack-protector" ]
       }
-    } else if (is_posix && !is_chromeos && !is_nacl) {
+    } else if ((is_posix && !is_chromeos && !is_nacl) || is_fuchsia) {
       # TODO(phajdan.jr): Use -fstack-protector-strong when our gcc supports it.
       # See also https://crbug.com/533294
       cflags += [ "--param=ssp-buffer-size=4" ]
@@ -308,9 +308,9 @@
     ]
   }
 
-  # Non-Mac Posix compiler flags setup.
+  # Non-Mac Posix and Fuchsia compiler flags setup.
   # -----------------------------------
-  if (is_posix && !(is_mac || is_ios)) {
+  if ((is_posix && !(is_mac || is_ios)) || is_fuchsia) {
     if (enable_profiling) {
       if (!is_debug) {
         cflags += [ "-g" ]
@@ -358,7 +358,7 @@
     }
   }
 
-  # Linux/Android common flags setup.
+  # Linux/Android/Fuchsia common flags setup.
   # ---------------------------------
   if (is_linux || is_android || is_fuchsia) {
     if (use_pic) {
@@ -402,7 +402,7 @@
     ldflags += [ "--gcc-toolchain=$_rebased_android_toolchain_root" ]
   }
 
-  if (is_posix && use_lld && !is_nacl) {
+  if ((is_posix || is_fuchsia) && use_lld && !is_nacl) {
     ldflags += [ "-fuse-ld=lld" ]
     if (current_cpu == "arm64") {
       # Reduce the page size from 65536 in order to reduce binary size slightly
@@ -658,7 +658,7 @@
   # Assign any flags set for the C compiler to asmflags so that they are sent
   # to the assembler. The Windows assembler takes different types of flags
   # so only do so for posix platforms.
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     asmflags += cflags
     asmflags += cflags_c
   }
@@ -674,7 +674,7 @@
   ldflags = []
   defines = []
 
-  if (is_posix && !(is_mac || is_ios)) {
+  if ((is_posix && !(is_mac || is_ios)) || is_fuchsia) {
     # CPU architecture. We may or may not be doing a cross compile now, so for
     # simplicity we always explicitly set the architecture.
     if (current_cpu == "x64") {
@@ -1126,7 +1126,9 @@
     configs += [ "//build/config/android:runtime_library" ]
   }
 
-  if (is_posix) {
+  # TODO(crbug.com/830987): Come up with a better name for is POSIX + Fuchsia
+  # configuration.
+  if (is_posix || is_fuchsia) {
     configs += [ "//build/config/posix:runtime_library" ]
   }
 
@@ -1561,7 +1563,7 @@
 # 2. Remove the thin_archive config, so that the .a file actually contains all
 #    .o files, instead of just references to .o files in the build directoy
 config("thin_archive") {
-  if (is_posix && !is_nacl) {
+  if ((is_posix && !is_nacl) || is_fuchsia) {
     # TODO(thomasanderson): Enable on ChromeOS builds once
     # https://crbug.com/829956 is fixed.
     if (default_toolchain != "//build/toolchain/cros:target") {
@@ -1759,7 +1761,7 @@
 }
 
 config("default_stack_frames") {
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     if (enable_frame_pointers) {
       cflags = [ "-fno-omit-frame-pointer" ]
     } else {
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn
index 00bac7b718..446b1783 100644
--- a/build/config/fuchsia/BUILD.gn
+++ b/build/config/fuchsia/BUILD.gn
@@ -7,7 +7,7 @@
 import("//build/config/sysroot.gni")
 
 assert(is_fuchsia)
-assert(is_posix)
+assert(!is_posix)
 
 config("compiler") {
   sdk_version_file = rebase_path("$fuchsia_sdk/.hash")
diff --git a/build/config/posix/BUILD.gn b/build/config/posix/BUILD.gn
index 6abfff79..c99a8c4 100644
--- a/build/config/posix/BUILD.gn
+++ b/build/config/posix/BUILD.gn
@@ -9,7 +9,9 @@
 import("//build/config/sysroot.gni")
 import("//build/toolchain/toolchain.gni")
 
-assert(is_posix)
+# TODO(crbug.com/830987): Come up with a better name for is POSIX + Fuchsia
+# configuration.
+assert(is_posix || is_fuchsia)
 
 group("posix") {
   visibility = [ "//:optimize_gn_gen" ]
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index 0b13684..a3c1d89 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -170,7 +170,7 @@
     ":deps",
   ]
 
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     ldflags = []
     if (is_asan) {
       ldflags += [ "-fsanitize=address" ]
diff --git a/build/fuchsia/runner_common.py b/build/fuchsia/runner_common.py
index 385efde..3188d3b10 100755
--- a/build/fuchsia/runner_common.py
+++ b/build/fuchsia/runner_common.py
@@ -630,8 +630,18 @@
     kernel_path = os.path.join(_TargetCpuToSdkBinPath(bootfs_data.target_cpu),
                                'zircon.bin')
 
-  kernel_args = ['devmgr.epoch=%d' % time.time(),
-                 'zircon.nodename=' + INSTANCE_ID]
+  kernel_args = [
+      'devmgr.epoch=%d' % time.time(),
+      'zircon.nodename=' + INSTANCE_ID,
+
+      # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
+      # noisy ANSI spew from the user's terminal emulator.
+      'TERM=dumb',
+
+      # Enable logging to the serial port.
+      'kernel.serial=legacy'
+  ]
+
   if bootfs_data.has_autorun:
     # See https://fuchsia.googlesource.com/zircon/+/master/docs/kernel_cmdline.md#zircon_autorun_system_command.
     kernel_args.append('zircon.autorun.system=/boot/bin/sh+/system/cr_autorun')
@@ -673,9 +683,7 @@
         '-serial', 'stdio',
         '-monitor', 'none',
 
-        # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
-        # noisy ANSI spew from the user's terminal emulator.
-        '-append', 'TERM=dumb ' + ' '.join(kernel_args)
+        '-append', ' '.join(kernel_args)
       ]
 
     # Configure the machine & CPU to emulate, based on the target architecture.
diff --git a/build/fuchsia/runner_v2/qemu_target.py b/build/fuchsia/runner_v2/qemu_target.py
index 04c2e4e5..16a903f3 100644
--- a/build/fuchsia/runner_v2/qemu_target.py
+++ b/build/fuchsia/runner_v2/qemu_target.py
@@ -56,6 +56,14 @@
         'qemu-system-' + self._GetTargetSdkArch())
     kernel_args = boot_data.GetKernelArgs(self._output_dir)
 
+    # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
+    # noisy ANSI spew from the user's terminal emulator.
+    kernel_args.append('TERM=dumb')
+
+    # Enable logging to the serial port.
+    # TODO(sergeyu): Use loglistener instead of serial port to get zircon logs.
+    kernel_args.append('kernel.serial=legacy')
+
     qemu_command = [qemu_path,
         '-m', str(self._ram_size_mb),
         '-nographic',
@@ -81,9 +89,7 @@
         '-serial', 'stdio',
         '-monitor', 'none',
 
-        # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
-        # noisy ANSI spew from the user's terminal emulator.
-        '-append', 'TERM=dumb ' + ' '.join(kernel_args)
+        '-append', ' '.join(kernel_args)
       ]
 
     # Configure the machine & CPU to emulate, based on the target architecture.
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1
index 8e9e92d..e1351328 100644
--- a/build/fuchsia/sdk.sha1
+++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@
-836b86e410e052129d3f1ded023f63ca79d3290e
+9c13ee0b7ab9f0b5c170e712f441b974b682d043
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index bc0f911..6ede004af 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -77,7 +77,7 @@
   # By appending .cr, we prevent name collisions with libraries already
   # loaded by the Android zygote.
   shlib_extension = ".cr.so"
-} else if (is_posix) {
+} else if (is_posix || is_fuchsia) {
   shlib_extension = ".so"
 } else if (is_win) {
   shlib_extension = ".dll"
@@ -86,7 +86,7 @@
 }
 
 # Prefix for shared library files.
-if (is_posix) {
+if (is_posix || is_fuchsia) {
   shlib_prefix = "lib"
 } else {
   shlib_prefix = ""
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 23f5500..6a639b1 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_export.h"
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index ddb9625..cea0c14 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/ranges.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/animation/animation_events.h"
diff --git a/cc/animation/keyframe_model_unittest.cc b/cc/animation/keyframe_model_unittest.cc
index df583614..ac13921 100644
--- a/cc/animation/keyframe_model_unittest.cc
+++ b/cc/animation/keyframe_model_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/animation/keyframe_model.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/trees/target_property.h"
diff --git a/cc/animation/scroll_offset_animations_impl.h b/cc/animation/scroll_offset_animations_impl.h
index 69341f89f..e64456e 100644
--- a/cc/animation/scroll_offset_animations_impl.h
+++ b/cc/animation/scroll_offset_animations_impl.h
@@ -6,7 +6,6 @@
 #define CC_ANIMATION_SCROLL_OFFSET_ANIMATIONS_IMPL_H_
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/animation/scroll_offset_animation_curve.h"
diff --git a/cc/animation/transform_operations_unittest.cc b/cc/animation/transform_operations_unittest.cc
index ed65e9b..ac7e528 100644
--- a/cc/animation/transform_operations_unittest.cc
+++ b/cc/animation/transform_operations_unittest.cc
@@ -9,7 +9,6 @@
 #include <limits>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "cc/test/geometry_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/animation/tween.h"
diff --git a/cc/animation/worklet_animation.cc b/cc/animation/worklet_animation.cc
index 8ad26c2a..5db8231c 100644
--- a/cc/animation/worklet_animation.cc
+++ b/cc/animation/worklet_animation.cc
@@ -4,7 +4,6 @@
 
 #include "cc/animation/worklet_animation.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/animation/scroll_timeline.h"
 
 namespace cc {
diff --git a/cc/benchmarks/invalidation_benchmark.cc b/cc/benchmarks/invalidation_benchmark.cc
index 173df8e..81ce31b 100644
--- a/cc/benchmarks/invalidation_benchmark.cc
+++ b/cc/benchmarks/invalidation_benchmark.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 #include <limits>
 
-#include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "base/values.h"
 #include "cc/layers/layer.h"
diff --git a/cc/benchmarks/micro_benchmark_controller.cc b/cc/benchmarks/micro_benchmark_controller.cc
index 57758ad..3c1b166 100644
--- a/cc/benchmarks/micro_benchmark_controller.cc
+++ b/cc/benchmarks/micro_benchmark_controller.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
diff --git a/cc/blink/web_compositor_support_impl.cc b/cc/blink/web_compositor_support_impl.cc
index c3874e45e0..04d038b 100644
--- a/cc/blink/web_compositor_support_impl.cc
+++ b/cc/blink/web_compositor_support_impl.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "cc/blink/web_content_layer_impl.h"
 #include "cc/blink/web_display_item_list_impl.h"
 #include "cc/blink/web_external_texture_layer_impl.h"
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc
index 51a8ff9..5dc2f9c 100644
--- a/cc/blink/web_content_layer_impl.cc
+++ b/cc/blink/web_content_layer_impl.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "cc/base/switches.h"
 #include "cc/blink/web_display_item_list_impl.h"
 #include "cc/layers/picture_layer.h"
diff --git a/cc/blink/web_scrollbar_layer_impl.cc b/cc/blink/web_scrollbar_layer_impl.cc
index 2a2d4e1..f501002 100644
--- a/cc/blink/web_scrollbar_layer_impl.cc
+++ b/cc/blink/web_scrollbar_layer_impl.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "cc/blink/scrollbar_impl.h"
 #include "cc/blink/web_layer_impl.h"
 #include "cc/layers/layer.h"
diff --git a/cc/input/browser_controls_offset_manager_unittest.cc b/cc/input/browser_controls_offset_manager_unittest.cc
index 7f039cd..098a701 100644
--- a/cc/input/browser_controls_offset_manager_unittest.cc
+++ b/cc/input/browser_controls_offset_manager_unittest.cc
@@ -9,7 +9,6 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "cc/input/browser_controls_offset_manager_client.h"
 #include "cc/layers/layer_impl.h"
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 909dfd1..89b4bdf6 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
diff --git a/cc/layers/layer_impl_test_properties.h b/cc/layers/layer_impl_test_properties.h
index f2cace08..0171895c 100644
--- a/cc/layers/layer_impl_test_properties.h
+++ b/cc/layers/layer_impl_test_properties.h
@@ -8,7 +8,6 @@
 #include <set>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "cc/input/overscroll_behavior.h"
 #include "cc/input/scroll_snap_data.h"
 #include "cc/layers/layer_collections.h"
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index e7573ac..3c898c8 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/animation/animation_host.h"
 #include "cc/animation/animation_id_provider.h"
diff --git a/cc/layers/nine_patch_generator.h b/cc/layers/nine_patch_generator.h
index bb0cd34..f413e4f 100644
--- a/cc/layers/nine_patch_generator.h
+++ b/cc/layers/nine_patch_generator.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/resources/ui_resource_client.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index baa05d6..1c92c7e9 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/animation/animation_host.h"
 #include "cc/layers/append_quads_data.h"
diff --git a/cc/layers/recording_source_unittest.cc b/cc/layers/recording_source_unittest.cc
index 82c424f..15b5249f 100644
--- a/cc/layers/recording_source_unittest.cc
+++ b/cc/layers/recording_source_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "cc/base/region.h"
 #include "cc/raster/raster_source.h"
 #include "cc/test/fake_content_layer_client.h"
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 892bbd7..94935c0 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <unordered_map>
 
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/animation/animation_host.h"
 #include "cc/input/scrollbar_animation_controller.h"
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index e311043c..8a123ca 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -7,7 +7,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/layers/surface_layer_impl.h"
 #include "cc/trees/layer_tree_host.h"
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
index f0fa766a..0e55c54 100644
--- a/cc/layers/texture_layer.cc
+++ b/cc/layers/texture_layer.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/synchronization/lock.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/simple_enclosed_region.h"
diff --git a/cc/layers/touch_action_region.cc b/cc/layers/touch_action_region.cc
index 9d516a0..c61b137 100644
--- a/cc/layers/touch_action_region.cc
+++ b/cc/layers/touch_action_region.cc
@@ -4,7 +4,6 @@
 
 #include "cc/layers/touch_action_region.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace cc {
diff --git a/cc/layers/ui_resource_layer.cc b/cc/layers/ui_resource_layer.cc
index b95ca27b..364e97c0 100644
--- a/cc/layers/ui_resource_layer.cc
+++ b/cc/layers/ui_resource_layer.cc
@@ -4,7 +4,6 @@
 
 #include "cc/layers/ui_resource_layer.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/layers/ui_resource_layer_impl.h"
 #include "cc/resources/scoped_ui_resource.h"
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc
index e27659a..232dab6a 100644
--- a/cc/paint/discardable_image_map.cc
+++ b/cc/paint/discardable_image_map.cc
@@ -11,7 +11,6 @@
 
 #include "base/auto_reset.h"
 #include "base/containers/adapters.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/paint/paint_filter.h"
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc
index 5757588..21e5044b 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -8,7 +8,6 @@
 
 #include <string>
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc
index 98f4e2b..5bcca13 100644
--- a/cc/paint/display_item_list_unittest.cc
+++ b/cc/paint/display_item_list_unittest.cc
@@ -8,7 +8,6 @@
 
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/paint/filter_operation.h"
diff --git a/cc/paint/paint_image_builder.h b/cc/paint/paint_image_builder.h
index b5e9671..b714235 100644
--- a/cc/paint/paint_image_builder.h
+++ b/cc/paint/paint_image_builder.h
@@ -5,7 +5,6 @@
 #ifndef CC_PAINT_PAINT_IMAGE_BUILDER_H_
 #define CC_PAINT_PAINT_IMAGE_BUILDER_H_
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
 #include "cc/paint/paint_image_generator.h"
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 626b0b7..446fc6e 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -4,7 +4,6 @@
 
 #include "cc/paint/paint_op_buffer.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/decoded_draw_image.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/image_provider.h"
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 3b0e5d0..7ab3a8c6a 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "cc/paint/paint_op_buffer.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "cc/paint/decoded_draw_image.h"
 #include "cc/paint/display_item_list.h"
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h
index 1b0bf24..c8f1c8a 100644
--- a/cc/paint/paint_recorder.h
+++ b/cc/paint/paint_recorder.h
@@ -7,7 +7,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/record_paint_canvas.h"
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc
index a53c6ed..6baee9f 100644
--- a/cc/paint/paint_shader.cc
+++ b/cc/paint/paint_shader.cc
@@ -4,7 +4,6 @@
 
 #include "cc/paint/paint_shader.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/paint_op_writer.h"
 #include "cc/paint/paint_record.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
index a39f278..c601f19 100644
--- a/cc/paint/record_paint_canvas.cc
+++ b/cc/paint/record_paint_canvas.cc
@@ -4,7 +4,6 @@
 
 #include "cc/paint/record_paint_canvas.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/paint_image_builder.h"
 #include "cc/paint/paint_record.h"
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index f9caa002..83128d5c 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -4,7 +4,6 @@
 
 #include "cc/paint/skia_paint_canvas.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/paint_recorder.h"
 #include "cc/paint/scoped_raster_flags.h"
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc
index fde06ec..ae57440 100644
--- a/cc/raster/bitmap_raster_buffer_provider.cc
+++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -10,7 +10,6 @@
 #include <algorithm>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index e720e02..5a4c95c5 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/histograms.h"
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index afdb591..7d7cec0 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/histograms.h"
diff --git a/cc/raster/playback_image_provider.cc b/cc/raster/playback_image_provider.cc
index b2ace4d..75d8ddf0 100644
--- a/cc/raster/playback_image_provider.cc
+++ b/cc/raster/playback_image_provider.cc
@@ -4,7 +4,6 @@
 
 #include "cc/raster/playback_image_provider.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/tiles/image_decode_cache.h"
 
 namespace cc {
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index d3cfcb5..25f5bc65 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -6,7 +6,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index 6ebe570..fbb8b17 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/cancelable_callback.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/cc/raster/staging_buffer_pool.cc b/cc/raster/staging_buffer_pool.cc
index 8ef7dd3e..37c39fc 100644
--- a/cc/raster/staging_buffer_pool.cc
+++ b/cc/raster/staging_buffer_pool.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/memory/memory_coordinator_client_registry.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h
index bd2d400..7c6dcf14 100644
--- a/cc/resources/resource_pool.h
+++ b/cc/resources/resource_pool.h
@@ -14,7 +14,6 @@
 #include "base/containers/circular_deque.h"
 #include "base/macros.h"
 #include "base/memory/memory_coordinator_client.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/trace_event/memory_allocator_dump_guid.h"
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index ab5dccf..17b44064 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/test/fake_layer_tree_frame_sink.h"
 #include "cc/test/fake_output_surface_client.h"
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 343dd08..352c8649 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -8,7 +8,6 @@
 
 #include "base/auto_reset.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
diff --git a/cc/test/fake_painted_scrollbar_layer.cc b/cc/test/fake_painted_scrollbar_layer.cc
index 7a852fa0..2a84559 100644
--- a/cc/test/fake_painted_scrollbar_layer.cc
+++ b/cc/test/fake_painted_scrollbar_layer.cc
@@ -5,7 +5,6 @@
 #include "cc/test/fake_painted_scrollbar_layer.h"
 
 #include "base/auto_reset.h"
-#include "base/memory/ptr_util.h"
 #include "cc/test/fake_scrollbar.h"
 
 namespace cc {
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index cb172443..ce60d89e 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -9,7 +9,6 @@
 
 #include <limits>
 
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/raster/raster_buffer.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
diff --git a/cc/test/fake_tile_task_manager.cc b/cc/test/fake_tile_task_manager.cc
index fe8c79d..6d73783 100644
--- a/cc/test/fake_tile_task_manager.cc
+++ b/cc/test/fake_tile_task_manager.cc
@@ -4,7 +4,6 @@
 
 #include "cc/test/fake_tile_task_manager.h"
 
-#include "base/memory/ptr_util.h"
 
 namespace cc {
 
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 8055a6af8..ca4067b 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -4,7 +4,6 @@
 
 #include "cc/test/layer_tree_pixel_resource_test.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/layers/layer.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index c0a31254..aaf3acb 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "cc/base/switches.h"
 #include "cc/layers/solid_color_layer.h"
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index a045c8a6..7812a1f 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -5,7 +5,6 @@
 #include "cc/test/pixel_test.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/cc/test/push_properties_counting_layer_impl.h b/cc/test/push_properties_counting_layer_impl.h
index 1112552..cd79397 100644
--- a/cc/test/push_properties_counting_layer_impl.h
+++ b/cc/test/push_properties_counting_layer_impl.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "cc/layers/layer_impl.h"
 
 namespace cc {
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 38f0743..7e5df382 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -11,7 +11,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/scheduler.h"
diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc
index 60c64503..74eb25b5 100644
--- a/cc/test/skia_common.cc
+++ b/cc/test/skia_common.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/draw_image.h"
 #include "cc/paint/paint_canvas.h"
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 30744898..94de268c 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -8,7 +8,6 @@
 
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/viz/common/gpu/context_cache_controller.h"
 #include "components/viz/common/resources/platform_color.h"
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc
index 012cbb65..060eb020 100644
--- a/cc/tiles/checker_image_tracker.cc
+++ b/cc/tiles/checker_image_tracker.cc
@@ -5,7 +5,6 @@
 #include "cc/tiles/checker_image_tracker.h"
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
diff --git a/cc/tiles/checker_image_tracker_unittest.cc b/cc/tiles/checker_image_tracker_unittest.cc
index 0c46a4b6..0b4606f 100644
--- a/cc/tiles/checker_image_tracker_unittest.cc
+++ b/cc/tiles/checker_image_tracker_unittest.cc
@@ -5,7 +5,6 @@
 #include "cc/tiles/checker_image_tracker.h"
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/paint/paint_image_builder.h"
diff --git a/cc/tiles/eviction_tile_priority_queue.cc b/cc/tiles/eviction_tile_priority_queue.cc
index 4bb198a..c09fc829 100644
--- a/cc/tiles/eviction_tile_priority_queue.cc
+++ b/cc/tiles/eviction_tile_priority_queue.cc
@@ -4,7 +4,6 @@
 
 #include "cc/tiles/eviction_tile_priority_queue.h"
 
-#include "base/memory/ptr_util.h"
 
 namespace cc {
 
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index 497c461b..3445153 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -11,7 +11,6 @@
 #include "base/hash.h"
 #include "base/memory/discardable_memory_allocator.h"
 #include "base/memory/memory_coordinator_client_registry.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/stringprintf.h"
diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc
index 6fb4812..4901cdbf 100644
--- a/cc/tiles/picture_layer_tiling.cc
+++ b/cc/tiles/picture_layer_tiling.cc
@@ -13,7 +13,6 @@
 
 #include "base/containers/flat_map.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
diff --git a/cc/tiles/picture_layer_tiling_set_unittest.cc b/cc/tiles/picture_layer_tiling_set_unittest.cc
index 7ea10ee..278f97b 100644
--- a/cc/tiles/picture_layer_tiling_set_unittest.cc
+++ b/cc/tiles/picture_layer_tiling_set_unittest.cc
@@ -7,7 +7,6 @@
 #include <map>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "cc/resources/layer_tree_resource_provider.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/test/fake_output_surface_client.h"
diff --git a/cc/tiles/raster_tile_priority_queue_all.cc b/cc/tiles/raster_tile_priority_queue_all.cc
index 96b98c5..564ddfe 100644
--- a/cc/tiles/raster_tile_priority_queue_all.cc
+++ b/cc/tiles/raster_tile_priority_queue_all.cc
@@ -4,7 +4,6 @@
 
 #include "cc/tiles/raster_tile_priority_queue_all.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/tiles/tiling_set_raster_queue_all.h"
 
 namespace cc {
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 6fc3fe81..33324a6 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -15,7 +15,6 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc
index 421848a..6bb3562 100644
--- a/cc/tiles/tile_manager_perftest.cc
+++ b/cc/tiles/tile_manager_perftest.cc
@@ -7,7 +7,6 @@
 
 #include "base/lazy_instance.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "cc/base/lap_timer.h"
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index dcfffbd..8c9a5f4 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/cc/trees/clip_node.cc b/cc/trees/clip_node.cc
index 3c9c58f..c1a73a9 100644
--- a/cc/trees/clip_node.cc
+++ b/cc/trees/clip_node.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
 #include "cc/layers/layer.h"
diff --git a/cc/trees/layer_tree_frame_sink_unittest.cc b/cc/trees/layer_tree_frame_sink_unittest.cc
index 7ccde47..8ac72b45 100644
--- a/cc/trees/layer_tree_frame_sink_unittest.cc
+++ b/cc/trees/layer_tree_frame_sink_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/trees/layer_tree_frame_sink.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "cc/test/fake_layer_tree_frame_sink_client.h"
 #include "components/viz/common/quads/compositor_frame.h"
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index c235590..16b8538 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -17,7 +17,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_math.h"
diff --git a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
index 1ae41ee..a4f98ae 100644
--- a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
+++ b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
@@ -4,7 +4,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/painted_overlay_scrollbar_layer.h"
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index cba18d5..acbd577a 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -11,7 +11,6 @@
 
 #include "base/auto_reset.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 9c7de67..024ca020 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "cc/layers/heads_up_display_layer.h"
 #include "cc/layers/layer_impl.h"
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc
index 5fff3e01..edc62a8 100644
--- a/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/layers/effect_tree_layer_list_iterator.h"
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index babaa05f..68982f6f 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -5,7 +5,6 @@
 #include "cc/trees/layer_tree_host.h"
 
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 3815722..62c31db 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "cc/base/synced_property.h"
 #include "cc/input/event_listener_properties.h"
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index ad61715..3856dcd 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -5,7 +5,6 @@
 #include "cc/trees/layer_tree_impl.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "cc/layers/heads_up_display_layer_impl.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
 #include "cc/test/geometry_test_utils.h"
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h
index 7594181..e4aae91 100644
--- a/cc/trees/mutator_host.h
+++ b/cc/trees/mutator_host.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/callback_forward.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "cc/trees/element_id.h"
 #include "cc/trees/layer_tree_mutator.h"
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index afc24f3..4aface25 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -9,7 +9,6 @@
 #include <map>
 #include <set>
 
-#include "base/memory/ptr_util.h"
 #include "cc/base/math_util.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index d81a1c1..4c4cdd4 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -10,7 +10,6 @@
 #include <string>
 
 #include "base/auto_reset.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/devtools_instrumentation.h"
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 7de104c6..7b75891 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <string>
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/completion_event.h"
diff --git a/cc/trees/swap_promise_manager_unittest.cc b/cc/trees/swap_promise_manager_unittest.cc
index f95b353..3acf5aa 100644
--- a/cc/trees/swap_promise_manager_unittest.cc
+++ b/cc/trees/swap_promise_manager_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/trees/swap_promise_manager.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/trees/swap_promise_monitor.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 5ddf723d..acb05f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -170,7 +170,6 @@
     public static final String CHROME_HOME_PERSISTENT_IPH = "ChromeHomePersistentIph";
     public static final String CHROME_HOME_PULL_TO_REFRESH_IPH_AT_TOP =
             "ChromeHomePullToRefreshIphAtTop";
-    public static final String CHROME_HOME_SURVEY = "ChromeHomeSurvey";
     public static final String CHROME_HOME_SWIPE_VELOCITY_FEATURE = "ChromeHomeSwipeLogicVelocity";
     public static final String CHROME_MEMEX = "ChromeMemex";
     public static final String CHROME_MODERN_DESIGN = "ChromeModernDesign";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
index f619c60..faf5daf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
@@ -167,8 +167,8 @@
      */
     public static final String CHROME_HOME_SWIPE_LOGIC_VELOCITY = "velocity";
 
-    /** Switch for enabling the Chrome Home Survey. */
-    public static final String CHROME_HOME_FORCE_ENABLE_SURVEY = "force-enable-chrome-home-survey";
+    /** Switch for enabling the Chrome Survey. */
+    public static final String CHROME_FORCE_ENABLE_SURVEY = "force-enable-chrome-survey";
 
     /** Switch to enable incognito tabs to be seen in Android Recents. */
     public static final String ENABLE_INCOGNITO_SNAPSHOTS_IN_ANDROID_RECENTS =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 1c347a0..a8a7cc1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -107,7 +107,7 @@
 import org.chromium.chrome.browser.snackbar.undo.UndoBarController;
 import org.chromium.chrome.browser.suggestions.SuggestionsEventReporterBridge;
 import org.chromium.chrome.browser.suggestions.SuggestionsMetrics;
-import org.chromium.chrome.browser.survey.ChromeHomeSurveyController;
+import org.chromium.chrome.browser.survey.ChromeSurveyController;
 import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
@@ -1606,7 +1606,7 @@
 
             LauncherShortcutActivity.updateIncognitoShortcut(ChromeTabbedActivity.this);
 
-            ChromeHomeSurveyController.initialize(mTabModelSelectorImpl);
+            ChromeSurveyController.initialize(mTabModelSelectorImpl);
         });
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 3b91de5..e056cad1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -417,7 +417,6 @@
 
         String referrerUrl = getReferrerUrlIncludingExtraHeaders(intent);
         String extraHeaders = getExtraHeadersFromIntent(intent);
-        extraHeaders = maybeAddAdditionalExtraHeaders(intent, url, extraHeaders);
 
         if (isIntentForMhtmlFileOrContent(intent) && tabOpenType == TabOpenType.OPEN_NEW_TAB
                 && referrerUrl == null && extraHeaders == null) {
@@ -425,13 +424,23 @@
             return true;
         }
 
+        processUrlViewIntent(url, referrerUrl, extraHeaders, tabOpenType,
+                IntentUtils.safeGetStringExtra(intent, Browser.EXTRA_APPLICATION_ID),
+                tabIdToBringToFront, hasUserGesture, intent);
+        return true;
+    }
+
+    private void processUrlViewIntent(String url, String referrerUrl, String extraHeaders,
+            TabOpenType tabOpenType, String externalAppId, int tabIdToBringToFront,
+            boolean hasUserGesture, Intent intent) {
+        extraHeaders = maybeAddAdditionalExtraHeaders(intent, url, extraHeaders);
+
         // TODO(joth): Presumably this should check the action too.
         mDelegate.processUrlViewIntent(url, referrerUrl, extraHeaders, tabOpenType,
                 IntentUtils.safeGetStringExtra(intent, Browser.EXTRA_APPLICATION_ID),
                 tabIdToBringToFront, hasUserGesture, intent);
         recordExternalIntentSourceUMA(intent);
         recordAppHandlersForIntent(intent);
-        return true;
     }
 
     /**
@@ -606,11 +615,8 @@
 
     private void handleMhtmlFileOrContentIntent(final String url, final Intent intent) {
         OfflinePageUtils.getLoadUrlParamsForOpeningMhtmlFileOrContent(url, (loadUrlParams) -> {
-            mDelegate.processUrlViewIntent(loadUrlParams.getUrl(), null,
-                    loadUrlParams.getVerbatimHeaders(), TabOpenType.OPEN_NEW_TAB, null, 0, false,
-                    intent);
-            recordExternalIntentSourceUMA(intent);
-            recordAppHandlersForIntent(intent);
+            processUrlViewIntent(loadUrlParams.getUrl(), null, loadUrlParams.getVerbatimHeaders(),
+                    TabOpenType.OPEN_NEW_TAB, null, 0, false, intent);
         });
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 2b7cee6e..b323034 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -2520,13 +2520,6 @@
         return mIsTablet;
     }
 
-    /**
-     * Scroll to ensure the TLD is visible, if necessary.
-     */
-    public void scrollUrlBarToTld() {
-        if (getScrollType() == UrlBar.SCROLL_TO_TLD) mUrlBar.scrollToTLD();
-    }
-
     @Override
     public AutocompleteController getAutocompleteController() {
         return mAutocomplete;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index 4535def..b9dcfc64 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -154,7 +154,8 @@
      */
     public void finishUrlFocusChange(boolean hasFocus) {
         if (!hasFocus) {
-            mUrlBar.scrollToTLD();
+            // Scroll to ensure the TLD is visible, if necessary.
+            if (getScrollType() == UrlBar.SCROLL_TO_TLD) mUrlBar.scrollDisplayText();
 
             // The animation rendering may not yet be 100% complete and hiding the keyboard makes
             // the animation quite choppy.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
index 2d410c7a..c2894b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -695,17 +695,31 @@
         return textChanged;
     }
 
+    /**
+     * Scrolls the omnibox text to a position determined by the call to
+     * {@link UrlBarDelegate#getScrollType}.
+     */
     public void scrollDisplayText() {
+        @ScrollType
+        int scrollType = mUrlBarDelegate.getScrollType();
         if (isLayoutRequested()) {
-            if (mUrlBarDelegate.getScrollType() == NO_SCROLL) return;
-            mPendingScroll = true;
-        } else {
-            scrollDisplayTextInternal();
+            mPendingScroll = scrollType != NO_SCROLL;
+            return;
         }
+        scrollDisplayTextInternal(scrollType);
     }
 
-    private void scrollDisplayTextInternal() {
-        switch (mUrlBarDelegate.getScrollType()) {
+    /**
+     * Scrolls the omnibox text to the position specified, based on the {@link ScrollType}.
+     *
+     * @param scrollType What type of scroll to perform.
+     *                   SCROLL_TO_TLD: Scrolls the omnibox text to bring the TLD into view.
+     *                   SCROLL_TO_BEGINNING: Scrolls text that's too long to fit in the omnibox
+     *                                        to the beginning so we can see the first character.
+     */
+    private void scrollDisplayTextInternal(@ScrollType int scrollType) {
+        mPendingScroll = false;
+        switch (scrollType) {
             case SCROLL_TO_TLD:
                 scrollToTLD();
                 break;
@@ -717,6 +731,9 @@
         }
     }
 
+    /**
+     * Scrolls the omnibox text to show the very beginning of the text entered.
+     */
     private void scrollToBeginning() {
         if (mFocused) return;
 
@@ -734,7 +751,10 @@
         scrollTo((int) scrollPos, getScrollY());
     }
 
-    public void scrollToTLD() {
+    /**
+     * Scrolls the omnibox text to bring the TLD into view.
+     */
+    private void scrollToTLD() {
         if (mFocused) return;
 
         // Ensure any selection from the focus state is cleared.
@@ -819,10 +839,9 @@
         super.onLayout(changed, left, top, right, bottom);
 
         if (mPendingScroll) {
-            scrollDisplayTextInternal();
-            mPendingScroll = false;
+            scrollDisplayTextInternal(mUrlBarDelegate.getScrollType());
         } else if (mPreviousWidth != (right - left)) {
-            scrollDisplayTextInternal();
+            scrollDisplayTextInternal(mUrlBarDelegate.getScrollType());
             mPreviousWidth = right - left;
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
index 9323b72d..bf04de6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
@@ -22,7 +22,10 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.IntDef;
+import android.support.annotation.StringRes;
 import android.support.v7.widget.AppCompatTextView;
 import android.text.Layout;
 import android.text.Spannable;
@@ -260,7 +263,6 @@
 
     /**  Parameters to configure the view of the page info popup. */
     private static class PageInfoViewParams {
-        public boolean permissionsListShown = true;
         public boolean instantAppButtonShown = true;
         public boolean siteSettingsButtonShown = true;
         public boolean openOnlineButtonShown = true;
@@ -276,6 +278,16 @@
         public int urlOriginLength;
     }
 
+    /**  Parameters to configure the view of a permission row. */
+    private static class PermissionParams {
+        public CharSequence status;
+        public @DrawableRes int iconResource;
+        public @ColorRes int iconTintColorResource;
+        public @StringRes int warningTextResource;
+        public @StringRes int subtitleTextResource;
+        public Runnable clickCallback;
+    }
+
     // Delay enter to allow the triggering button to animate before we cover it.
     private static final int ENTER_START_DELAY = 100;
     private static final int FADE_DURATION = 200;
@@ -389,9 +401,6 @@
 
         mDisplayedPermissions = new ArrayList<PageInfoPermissionEntry>();
 
-        // Hide the permissions list for sites with no permissions.
-        viewParams.permissionsListShown = false;
-
         // Work out the URL and connection message and status visibility.
         mFullUrl = isShowingOfflinePage() ? offlinePageUrl : mTab.getOriginalUrl();
 
@@ -530,17 +539,6 @@
     }
 
     /**
-     * Sets the visibility of the permissions list, which contains padding and borders that should
-     * not be shown if a site has no permissions.
-     *
-     * @param isVisible Whether to show or hide the dialog area.
-     */
-    private void setVisibilityOfPermissionsList(boolean isVisible) {
-        int visibility = isVisible ? View.VISIBLE : View.GONE;
-        mPermissionsList.setVisibility(visibility);
-    }
-
-    /**
      * Finds the Image resource of the icon to use for the given permission.
      *
      * @param permission A valid ContentSettingsType that can be displayed in the PageInfo dialog to
@@ -584,8 +582,6 @@
      */
     @CalledByNative
     private void addPermissionSection(String name, int type, int currentSettingValue) {
-        // We have at least one permission, so show the lower permissions area.
-        setVisibilityOfPermissionsList(true);
         mDisplayedPermissions.add(new PageInfoPermissionEntry(name, type, ContentSetting
                 .fromInt(currentSettingValue)));
     }
@@ -595,69 +591,93 @@
      */
     @CalledByNative
     private void updatePermissionDisplay() {
-        mPermissionsList.removeAllViews();
+        List<PermissionParams> permissionParamsList = new ArrayList<>();
         for (PageInfoPermissionEntry permission : mDisplayedPermissions) {
-            addReadOnlyPermissionSection(permission);
+            permissionParamsList.add(createPermissionParams(permission));
         }
+        setPermissions(permissionParamsList);
     }
 
-    private void addReadOnlyPermissionSection(PageInfoPermissionEntry permission) {
-        View permissionRow = LayoutInflater.from(mContext).inflate(
-                R.layout.page_info_permission_row, null);
+    private Runnable createPermissionClickCallback(
+            Intent intentOverride, String[] androidPermissions) {
+        return () -> {
+            if (intentOverride == null && mWindowAndroid != null) {
+                // Try and immediately request missing Android permissions where possible.
+                for (int i = 0; i < androidPermissions.length; i++) {
+                    if (!mWindowAndroid.canRequestPermission(androidPermissions[i])) continue;
 
-        ImageView permissionIcon = (ImageView) permissionRow.findViewById(
-                R.id.page_info_permission_icon);
-        permissionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(
-                permissionIcon.getResources(), getImageResourceForPermission(permission.type)));
-
-        if (permission.setting == ContentSetting.ALLOW) {
-            int warningTextResource = 0;
-
-            // If warningTextResource is non-zero, then the view must be tagged with either
-            // permission_intent_override or permission_type.
-            LocationUtils locationUtils = LocationUtils.getInstance();
-            if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION
-                    && !locationUtils.isSystemLocationSettingEnabled()) {
-                warningTextResource = R.string.page_info_android_location_blocked;
-                permissionRow.setTag(R.id.permission_intent_override,
-                        locationUtils.getSystemLocationSettingsIntent());
-            } else if (!hasAndroidPermission(permission.type)) {
-                warningTextResource = R.string.page_info_android_permission_blocked;
-                permissionRow.setTag(R.id.permission_type,
-                        PrefServiceBridge.getAndroidPermissionsForContentSetting(permission.type));
+                    // If any permissions can be requested, attempt to request them all.
+                    mWindowAndroid.requestPermissions(androidPermissions, new PermissionCallback() {
+                        @Override
+                        public void onRequestPermissionsResult(
+                                String[] permissions, int[] grantResults) {
+                            boolean allGranted = true;
+                            for (int i = 0; i < grantResults.length; i++) {
+                                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
+                                    allGranted = false;
+                                    break;
+                                }
+                            }
+                            if (allGranted) updatePermissionDisplay();
+                        }
+                    });
+                    return;
+                }
             }
 
-            if (warningTextResource != 0) {
-                TextView permissionUnavailable = (TextView) permissionRow.findViewById(
-                        R.id.page_info_permission_unavailable_message);
-                permissionUnavailable.setVisibility(View.VISIBLE);
-                permissionUnavailable.setText(warningTextResource);
+            runAfterDismiss(() -> {
+                Intent settingsIntent;
+                if (intentOverride != null) {
+                    settingsIntent = intentOverride;
+                } else {
+                    settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+                    settingsIntent.setData(Uri.parse("package:" + mContext.getPackageName()));
+                }
+                settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivity(settingsIntent);
+            });
+        };
+    }
 
-                permissionIcon.setImageResource(R.drawable.exclamation_triangle);
-                permissionIcon.setColorFilter(ApiCompatibilityUtils.getColor(
-                        mContext.getResources(), R.color.google_blue_700));
+    private PermissionParams createPermissionParams(PageInfoPermissionEntry permission) {
+        PermissionParams permissionParams = new PermissionParams();
 
-                permissionRow.setOnClickListener(this);
+        permissionParams.iconResource = getImageResourceForPermission(permission.type);
+        if (permission.setting == ContentSetting.ALLOW) {
+            LocationUtils locationUtils = LocationUtils.getInstance();
+            Intent intentOverride = null;
+            String[] androidPermissions = null;
+            if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION
+                    && !locationUtils.isSystemLocationSettingEnabled()) {
+                permissionParams.warningTextResource = R.string.page_info_android_location_blocked;
+                intentOverride = locationUtils.getSystemLocationSettingsIntent();
+            } else if (!hasAndroidPermission(permission.type)) {
+                permissionParams.warningTextResource =
+                        R.string.page_info_android_permission_blocked;
+                androidPermissions =
+                        PrefServiceBridge.getAndroidPermissionsForContentSetting(permission.type);
+            }
+
+            if (permissionParams.warningTextResource != 0) {
+                permissionParams.iconResource = R.drawable.exclamation_triangle;
+                permissionParams.iconTintColorResource = R.color.google_blue_700;
+                permissionParams.clickCallback =
+                        createPermissionClickCallback(intentOverride, androidPermissions);
             }
         }
 
         // The ads permission requires an additional static subtitle.
         if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_ADS) {
-            TextView permissionSubtitle =
-                    (TextView) permissionRow.findViewById(R.id.page_info_permission_subtitle);
-            permissionSubtitle.setVisibility(View.VISIBLE);
-            permissionSubtitle.setText(R.string.page_info_permission_ads_subtitle);
+            permissionParams.subtitleTextResource = R.string.page_info_permission_ads_subtitle;
         }
 
-        TextView permissionStatus = (TextView) permissionRow.findViewById(
-                R.id.page_info_permission_status);
         SpannableStringBuilder builder = new SpannableStringBuilder();
         SpannableString nameString = new SpannableString(permission.name);
         final StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
         nameString.setSpan(boldSpan, 0, nameString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
 
         builder.append(nameString);
-        builder.append(" – ");  // en-dash.
+        builder.append(" – "); // en-dash.
         String status_text = "";
         switch (permission.setting) {
             case ALLOW:
@@ -668,21 +688,22 @@
                 break;
             default:
                 assert false : "Invalid setting " + permission.setting + " for permission "
-                        + permission.type;
+                               + permission.type;
         }
         if (WebsitePreferenceBridge.isPermissionControlledByDSE(permission.type, mFullUrl, false)) {
-            status_text = statusTextForDSEPermission(permission);
+            status_text = statusTextForDSEPermission(permission.setting);
         }
         builder.append(status_text);
-        permissionStatus.setText(builder);
-        mPermissionsList.addView(permissionRow);
+        permissionParams.status = builder;
+
+        return permissionParams;
     }
 
     /**
-     * Update the permission string for the Default Search Engine.
+     * Returns the permission string for the Default Search Engine.
      */
-    private String statusTextForDSEPermission(PageInfoPermissionEntry permission) {
-        if (permission.setting == ContentSetting.ALLOW) {
+    private String statusTextForDSEPermission(ContentSetting setting) {
+        if (setting == ContentSetting.ALLOW) {
             return mContext.getString(R.string.page_info_dse_permission_allowed);
         }
 
@@ -825,48 +846,6 @@
                     showConnectionInfoPopup();
                 }
             });
-        } else if (view.getId() == R.id.page_info_permission_row) {
-            final Object intentOverride = view.getTag(R.id.permission_intent_override);
-
-            if (intentOverride == null && mWindowAndroid != null) {
-                // Try and immediately request missing Android permissions where possible.
-                final String[] permissionType = (String[]) view.getTag(R.id.permission_type);
-                for (int i = 0; i < permissionType.length; i++) {
-                    if (!mWindowAndroid.canRequestPermission(permissionType[i])) continue;
-
-                    // If any permissions can be requested, attempt to request them all.
-                    mWindowAndroid.requestPermissions(permissionType, new PermissionCallback() {
-                        @Override
-                        public void onRequestPermissionsResult(
-                                String[] permissions, int[] grantResults) {
-                            boolean allGranted = true;
-                            for (int i = 0; i < grantResults.length; i++) {
-                                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
-                                    allGranted = false;
-                                    break;
-                                }
-                            }
-                            if (allGranted) updatePermissionDisplay();
-                        }
-                    });
-                    return;
-                }
-            }
-
-            runAfterDismiss(new Runnable() {
-                @Override
-                public void run() {
-                    Intent settingsIntent;
-                    if (intentOverride != null) {
-                        settingsIntent = (Intent) intentOverride;
-                    } else {
-                        settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-                        settingsIntent.setData(Uri.parse("package:" + mContext.getPackageName()));
-                    }
-                    settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    mContext.startActivity(settingsIntent);
-                }
-            });
         }
     }
 
@@ -1096,7 +1075,8 @@
         }
 
         initializePageInfoViewChild(mUrlTitle, true, params.urlTitleClickCallback);
-        initializePageInfoViewChild(mPermissionsList, params.permissionsListShown, null);
+        // Hide the permissions list for sites with no permissions.
+        initializePageInfoViewChild(mPermissionsList, false, null);
         initializePageInfoViewChild(mInstantAppButton, params.instantAppButtonShown,
                 params.instantAppButtonClickCallback);
         initializePageInfoViewChild(mSiteSettingsButton, params.siteSettingsButtonShown,
@@ -1111,6 +1091,55 @@
         child.setOnClickListener((View v) -> { clickCallback.run(); });
     }
 
+    private void setPermissions(List<PermissionParams> permissionParamsList) {
+        mPermissionsList.removeAllViews();
+        // If we have at least one permission show the lower permissions area.
+        mPermissionsList.setVisibility(!permissionParamsList.isEmpty() ? View.VISIBLE : View.GONE);
+        for (PermissionParams params : permissionParamsList) {
+            mPermissionsList.addView(createPermissionRow(params));
+        }
+    }
+
+    private View createPermissionRow(PermissionParams params) {
+        View permissionRow =
+                LayoutInflater.from(mContext).inflate(R.layout.page_info_permission_row, null);
+
+        TextView permissionStatus =
+                (TextView) permissionRow.findViewById(R.id.page_info_permission_status);
+        permissionStatus.setText(params.status);
+
+        ImageView permissionIcon =
+                (ImageView) permissionRow.findViewById(R.id.page_info_permission_icon);
+        if (params.iconTintColorResource == 0) {
+            permissionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(
+                    mContext.getResources(), params.iconResource));
+        } else {
+            permissionIcon.setImageResource(params.iconResource);
+            permissionIcon.setColorFilter(ApiCompatibilityUtils.getColor(
+                    mContext.getResources(), params.iconTintColorResource));
+        }
+
+        if (params.warningTextResource != 0) {
+            TextView permissionUnavailable = (TextView) permissionRow.findViewById(
+                    R.id.page_info_permission_unavailable_message);
+            permissionUnavailable.setVisibility(View.VISIBLE);
+            permissionUnavailable.setText(params.warningTextResource);
+        }
+
+        if (params.subtitleTextResource != 0) {
+            TextView permissionSubtitle =
+                    (TextView) permissionRow.findViewById(R.id.page_info_permission_subtitle);
+            permissionSubtitle.setVisibility(View.VISIBLE);
+            permissionSubtitle.setText(params.subtitleTextResource);
+        }
+
+        if (params.clickCallback != null) {
+            permissionRow.setOnClickListener((View v) -> { params.clickCallback.run(); });
+        }
+
+        return permissionRow;
+    }
+
     /**
      * Shows a PageInfo dialog for the provided Tab. The popup adds itself to the view
      * hierarchy which owns the reference while it's visible.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
index 920dcba8..2c40749f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -135,7 +135,7 @@
      *         this method reads is not initialized until the asynchronous initialization of this
      *         class has been completed.
      */
-    static boolean isHomepageProviderAvailableAndEnabled() {
+    public static boolean isHomepageProviderAvailableAndEnabled() {
         return !TextUtils.isEmpty(getHomePageUrl());
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogView.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogView.java
index 791c45f6..283d84b5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogView.java
@@ -50,9 +50,11 @@
         LayoutInflater inflater = LayoutInflater.from(activity);
         View view = inflater.inflate(R.layout.permission_dialog, null);
         TextView messageTextView = (TextView) view.findViewById(R.id.text);
-        messageTextView.setText(prepareMainMessageString(mDialogDelegate));
+        String messageText = mDialogDelegate.getMessageText();
+        assert !TextUtils.isEmpty(messageText);
+        messageTextView.setText(messageText);
         messageTextView.setVisibility(View.VISIBLE);
-        messageTextView.announceForAccessibility(mDialogDelegate.getMessageText());
+        messageTextView.announceForAccessibility(messageText);
         TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(
                 messageTextView, mDialogDelegate.getDrawableId(), 0, 0, 0);
         mDialog.setView(view);
@@ -81,18 +83,4 @@
     public Button getButton(int whichButton) {
         return mDialog.getButton(whichButton);
     }
-
-    private CharSequence prepareMainMessageString(final PermissionDialogDelegate delegate) {
-        String messageText = delegate.getMessageText();
-        assert !TextUtils.isEmpty(messageText);
-
-        // TODO(timloh): Currently the strings are shared with infobars, so we for now manually
-        // remove the full stop (this code catches most but not all languages). Update the strings
-        // after removing the infobar path.
-        if (messageText.endsWith(".") || messageText.endsWith("。")) {
-            messageText = messageText.substring(0, messageText.length() - 1);
-        }
-
-        return messageText;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
index 3b3483d..3f39ee8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java
@@ -4,8 +4,11 @@
 
 package org.chromium.chrome.browser.ssl;
 
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.Network;
+import android.os.Build;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.annotations.CalledByNative;
@@ -52,6 +55,47 @@
         }
     }
 
+    @TargetApi(Build.VERSION_CODES.M)
+    @CalledByNative
+    private static void reportNetworkConnectivity() {
+        // Call reportNetworkConnectivity on all networks, including the current network.
+        Context context = ContextUtils.getApplicationContext();
+        ConnectivityManager connectivityManager =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            for (Network network : connectivityManager.getAllNetworks()) {
+                // Try both true and false for |hasConnectivity|, that's what reportBadNetwork does.
+                // See
+                // https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/net/ConnectivityManager.java#L2463
+                // for details.
+                connectivityManager.reportNetworkConnectivity(network, true);
+                connectivityManager.reportNetworkConnectivity(network, false);
+            }
+            return;
+        }
+
+        try {
+            Class<?> networkClass = Class.forName("android.net.Network");
+            Method reportNetworkConnectivityMethod =
+                    connectivityManager.getClass().getMethod("reportNetworkConnectivity",
+                            Class.forName("android.net.Network"), boolean.class);
+            Method getAllNetworksMethod =
+                    connectivityManager.getClass().getMethod("getAllNetworks");
+
+            for (Object obj : (Object[]) getAllNetworksMethod.invoke(connectivityManager)) {
+                // Try both true and false for |hasConnectivity|, as above.
+                reportNetworkConnectivityMethod.invoke(
+                        connectivityManager, new Object[] {networkClass.cast(obj), true});
+                reportNetworkConnectivityMethod.invoke(
+                        connectivityManager, new Object[] {networkClass.cast(obj), false});
+            }
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException
+                | ClassNotFoundException e) {
+            // Ignore and do nothing.
+        }
+    }
+
     private CaptivePortalHelper() {}
 
     private static native void nativeSetCaptivePortalCertificateForTesting(String spkiHash);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
similarity index 82%
rename from chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java
rename to chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
index a6fd52a..7b569640 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
@@ -18,14 +18,12 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
 import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
 import org.chromium.chrome.browser.infobar.SurveyInfoBar;
 import org.chromium.chrome.browser.infobar.SurveyInfoBarDelegate;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -33,7 +31,6 @@
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.components.variations.VariationsAssociatedData;
 
 import java.lang.annotation.Retention;
@@ -44,35 +41,35 @@
 /**
  * Class that controls if and when to show surveys related to the Chrome Home experiment.
  */
-public class ChromeHomeSurveyController implements InfoBarContainer.InfoBarAnimationListener {
-    public static final String SURVEY_INFO_BAR_DISPLAYED_KEY =
-            "chrome_home_survey_info_bar_displayed";
-    public static final String PARAM_NAME = "survey_override_site_id";
-    public static final long REQUIRED_VISIBILITY_DURATION_MS = 5000;
+public class ChromeSurveyController implements InfoBarContainer.InfoBarAnimationListener {
+    /**
+     *  The survey questions for this survey are the same as those in the survey used for Chrome
+     *  Home, so we reuse the old infobar key to prevent the users from seeing the same survey more
+     *  than once.
+     */
+    static final String SURVEY_INFO_BAR_DISPLAYED_KEY = "chrome_home_survey_info_bar_displayed";
+    static final String DATE_LAST_ROLLED_KEY = "last_rolled_for_chrome_survey_key";
 
-    private static final String CHROME_HOME_TRIAL_NAME = "ChromeHome";
-    private static final String HAPPINESS_SURVEY_TRIAL_NAME = "ChromeHomeHappinessSurvey";
+    private static final String CHROME_SURVEY_TRIAL_NAME = "ChromeSurvey";
     private static final String MAX_NUMBER = "max-number";
-    private static final String TEST_SITE_ID = "obw74vpeieqaw4xmw7o6qlpdbq";
+    private static final String SITE_ID_PARAM_NAME = "site-id";
+    private static final long REQUIRED_VISIBILITY_DURATION_MS = 5000;
 
     private static boolean sForceUmaEnabledForTesting;
 
-    static final long ONE_WEEK_IN_MILLIS = 604800000L;
-    static final String DATE_LAST_ROLLED_KEY = "chrome_home_date_last_rolled_for_survey";
+    public static final String COMMAND_LINE_PARAM_NAME = "survey_override_site_id";
 
     /**
      * Reasons that the user was rejected from being selected for a survey
      *  Note: these values must match the SurveyFilteringResult enum in enums.xml.
      */
     @IntDef({FilteringResult.SURVEY_INFOBAR_ALREADY_DISPLAYED,
-            FilteringResult.CHROME_HOME_ON_FOR_LESS_THAN_ONE_WEEK,
             FilteringResult.FORCE_SURVEY_ON_COMMAND_PRESENT,
             FilteringResult.USER_ALREADY_SAMPLED_TODAY, FilteringResult.MAX_NUMBER_MISSING,
             FilteringResult.ROLLED_NON_ZERO_NUMBER, FilteringResult.USER_SELECTED_FOR_SURVEY})
     @Retention(RetentionPolicy.SOURCE)
     public @interface FilteringResult {
         int SURVEY_INFOBAR_ALREADY_DISPLAYED = 0;
-        int CHROME_HOME_ON_FOR_LESS_THAN_ONE_WEEK = 1;
         int FORCE_SURVEY_ON_COMMAND_PRESENT = 2;
         int USER_ALREADY_SAMPLED_TODAY = 3;
         int MAX_NUMBER_MISSING = 4;
@@ -102,7 +99,7 @@
     private TabModelSelectorObserver mTabModelObserver;
 
     @VisibleForTesting
-    ChromeHomeSurveyController() {
+    ChromeSurveyController() {
         // Empty constructor.
     }
 
@@ -113,7 +110,7 @@
      */
     public static void initialize(TabModelSelector tabModelSelector) {
         assert tabModelSelector != null;
-        new StartDownloadIfEligibleTask(new ChromeHomeSurveyController(), tabModelSelector)
+        new StartDownloadIfEligibleTask(new ChromeSurveyController(), tabModelSelector)
                 .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
@@ -138,20 +135,16 @@
                 onSurveyAvailable(siteId);
             }
         };
-        String siteContext =
-                String.format("ChromeHomeEnabled=%s", FeatureUtilities.isChromeHomeEnabled());
-        surveyController.downloadSurvey(context, siteId, onSuccessRunnable, siteContext);
+        surveyController.downloadSurvey(context, siteId, onSuccessRunnable, null);
     }
 
     private String getSiteId() {
         CommandLine commandLine = CommandLine.getInstance();
-        if (commandLine.hasSwitch(PARAM_NAME)) {
-            return commandLine.getSwitchValue(PARAM_NAME);
-        } else if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_SURVEY)) {
-            return TEST_SITE_ID;
+        if (commandLine.hasSwitch(COMMAND_LINE_PARAM_NAME)) {
+            return commandLine.getSwitchValue(COMMAND_LINE_PARAM_NAME);
         } else {
             return VariationsAssociatedData.getVariationParamValue(
-                    HAPPINESS_SURVEY_TRIAL_NAME, PARAM_NAME);
+                    CHROME_SURVEY_TRIAL_NAME, SITE_ID_PARAM_NAME);
         }
     }
 
@@ -159,11 +152,7 @@
     private boolean doesUserQualifyForSurvey() {
         if (!isUMAEnabled() && !sForceUmaEnabledForTesting) return false;
         if (hasInfoBarBeenDisplayed()) return false;
-        if (!FeatureUtilities.isChromeHomeEnabled()) return true;
-        return wasChromeHomeEnabledForMinimumOneWeek()
-                || CommandLine.getInstance().hasSwitch(
-                           ChromeSwitches.CHROME_HOME_FORCE_ENABLE_SURVEY)
-                || ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_SURVEY);
+        return true;
     }
 
     /**
@@ -215,7 +204,7 @@
         SurveyInfoBar.showSurveyInfoBar(tab.getWebContents(), siteId, true,
                 R.drawable.chrome_sync_logo, getSurveyInfoBarDelegate());
 
-        RecordUserAction.record("Android.ChromeHome.Survey.ShowSurveyInfoBar");
+        RecordUserAction.record("Android.Survey.ShowSurveyInfoBar");
 
         mTabModelSelector.removeObserver(mTabModelObserver);
     }
@@ -263,30 +252,15 @@
         return PrivacyPreferencesManager.getInstance().isUsageAndCrashReportingPermittedByUser();
     }
 
-    /** @return If the survey info bar was logged as seen before. */
+    /** @return If the survey info bar for this survey was logged as seen before. */
     @VisibleForTesting
     boolean hasInfoBarBeenDisplayed() {
         SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences();
         if (sharedPreferences.getLong(SURVEY_INFO_BAR_DISPLAYED_KEY, -1L) != -1L) {
             recordSurveyFilteringResult(FilteringResult.SURVEY_INFOBAR_ALREADY_DISPLAYED);
             return true;
-        } else {
-            return false;
         }
-    }
-
-    /** @return If it has been over a week since ChromeHome was enabled. */
-    @VisibleForTesting
-    boolean wasChromeHomeEnabledForMinimumOneWeek() {
-        SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences();
-        long earliestLoggedDate = sharedPreferences.getLong(
-                ChromePreferenceManager.CHROME_HOME_SHARED_PREFERENCES_KEY, Long.MAX_VALUE);
-        if (System.currentTimeMillis() - earliestLoggedDate >= ONE_WEEK_IN_MILLIS) {
-            return true;
-        } else {
-            recordSurveyFilteringResult(FilteringResult.CHROME_HOME_ON_FOR_LESS_THAN_ONE_WEEK);
-            return false;
-        }
+        return false;
     }
 
     /**
@@ -299,10 +273,10 @@
         return tab != null && tab.getWebContents() != null && !tab.isIncognito();
     }
 
-    /** @return A new {@link ChromeHomeSurveyController} for testing. */
+    /** @return A new {@link ChromeSurveyController} for testing. */
     @VisibleForTesting
-    public static ChromeHomeSurveyController createChromeHomeSurveyControllerForTests() {
-        return new ChromeHomeSurveyController();
+    public static ChromeSurveyController createChromeSurveyControllerForTests() {
+        return new ChromeSurveyController();
     }
 
     @Override
@@ -367,7 +341,7 @@
     int getMaxNumber() {
         try {
             String number = VariationsAssociatedData.getVariationParamValue(
-                    CHROME_HOME_TRIAL_NAME, MAX_NUMBER);
+                    CHROME_SURVEY_TRIAL_NAME, MAX_NUMBER);
             if (TextUtils.isEmpty(number)) return -1;
             return Integer.parseInt(number);
         } catch (NumberFormatException e) {
@@ -429,7 +403,7 @@
             @Override
             public String getSurveyPromptString() {
                 return ContextUtils.getApplicationContext().getString(
-                        R.string.chrome_home_survey_prompt);
+                        R.string.chrome_survey_prompt);
             }
         };
     }
@@ -460,21 +434,20 @@
 
     private void recordSurveyFilteringResult(@FilteringResult int value) {
         RecordHistogram.recordEnumeratedHistogram(
-                "Android.ChromeHome.Survey.SurveyFilteringResults", value,
-                FilteringResult.ENUM_BOUNDARY);
+                "Android.Survey.SurveyFilteringResults", value, FilteringResult.ENUM_BOUNDARY);
     }
 
     private void recordInfoBarClosingState(@InfoBarClosingState int value) {
-        RecordHistogram.recordEnumeratedHistogram("Android.ChromeHome.Survey.InfoBarClosingState",
-                value, InfoBarClosingState.ENUM_BOUNDARY);
+        RecordHistogram.recordEnumeratedHistogram(
+                "Android.Survey.InfoBarClosingState", value, InfoBarClosingState.ENUM_BOUNDARY);
     }
 
     static class StartDownloadIfEligibleTask extends AsyncTask<Void, Void, Boolean> {
-        ChromeHomeSurveyController mController;
+        ChromeSurveyController mController;
         final TabModelSelector mSelector;
 
         public StartDownloadIfEligibleTask(
-                ChromeHomeSurveyController controller, TabModelSelector tabModelSelector) {
+                ChromeSurveyController controller, TabModelSelector tabModelSelector) {
             mController = controller;
             mSelector = tabModelSelector;
         }
@@ -489,8 +462,7 @@
             } else {
                 boolean forceSurveyOn = false;
                 if (CommandLine.getInstance().hasSwitch(
-                            ChromeSwitches.CHROME_HOME_FORCE_ENABLE_SURVEY)
-                        || ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_SURVEY)) {
+                            ChromeSwitches.CHROME_FORCE_ENABLE_SURVEY)) {
                     forceSurveyOn = true;
                     mController.recordSurveyFilteringResult(
                             FilteringResult.FORCE_SURVEY_ON_COMMAND_PRESENT);
@@ -510,4 +482,19 @@
     public static void forceIsUMAEnabledForTesting(boolean forcedUMAStatus) {
         sForceUmaEnabledForTesting = forcedUMAStatus;
     }
+
+    @VisibleForTesting
+    public static Long getRequiredVisibilityDurationMs() {
+        return REQUIRED_VISIBILITY_DURATION_MS;
+    }
+
+    @VisibleForTesting
+    public static String getChromeSurveyInfoBarDisplayedKey() {
+        return SURVEY_INFO_BAR_DISPLAYED_KEY;
+    }
+
+    @VisibleForTesting
+    public static String getCommandLineParamName() {
+        return COMMAND_LINE_PARAM_NAME;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index 0dab7ea9..8ca9e40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -25,6 +25,7 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.firstrun.FirstRunUtils;
 import org.chromium.chrome.browser.locale.LocaleManager;
+import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.tabmodel.DocumentModeAssassin;
 import org.chromium.components.signin.AccountManagerFacade;
@@ -188,6 +189,7 @@
      * be made available immediately.
      */
     public static void cacheHomePageButtonForceEnabled() {
+        if (PartnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()) return;
         ChromePreferenceManager.getInstance().setHomePageButtonForceEnabled(
                 ChromeFeatureList.isEnabled(ChromeFeatureList.HOME_PAGE_BUTTON_FORCE_ENABLED));
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 83b7f97..0ffd0d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -1900,6 +1900,7 @@
         mListeningForWebVrActivate = listening;
         if (mListeningForWebVrActivate) {
             registerDaydreamIntent(mActivity);
+            if (mNeedsAnimationCancel || mCancellingEntryAnimation) return;
             if (mAutopresentWebVr || mActivateFromHeadsetInsertion) {
                 // Dispatch vrdisplayactivate so that the WebVr page can call requestPresent
                 // to start presentation.
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 584b27f..6d40decdd 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2709,7 +2709,7 @@
       <message name="IDS_URL_COPIED" desc="Notification telling the user that the url has been copied to clipboard. [CHAR-LIMIT=32]">
         URL copied.
       </message>
-      <message name="IDS_CHROME_HOME_SURVEY_PROMPT" desc="Message shown that invites the user to take a survey about Chrome. 'Help' and 'improve' are imperative verbs. 'Take survey' is a tappable link. When tapped, a survey about Chrome opens.">
+      <message name="IDS_CHROME_SURVEY_PROMPT" desc="Message shown that invites the user to take a survey about Chrome. 'Help' and 'improve' are imperative verbs. 'Take survey' is a tappable link. When tapped, a survey about Chrome opens.">
         Help improve Chrome. <ph name="BEGIN_LINK">&lt;LINK&gt;</ph>Take survey<ph name="END_LINK">&lt;/LINK&gt;</ph>
       </message>
 
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index f2d1ea9..4cd615d 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1197,7 +1197,7 @@
   "java/src/org/chromium/chrome/browser/suggestions/SuggestionsRanker.java",
   "java/src/org/chromium/chrome/browser/suggestions/SuggestionsSheetVisibilityChangeObserver.java",
   "java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java",
-  "java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java",
+  "java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java",
   "java/src/org/chromium/chrome/browser/survey/SurveyController.java",
   "java/src/org/chromium/chrome/browser/sync/GmsCoreSyncListener.java",
   "java/src/org/chromium/chrome/browser/sync/GoogleServiceAuthError.java",
@@ -2059,7 +2059,7 @@
   "junit/src/org/chromium/chrome/browser/suggestions/ImageFetcherTest.java",
   "junit/src/org/chromium/chrome/browser/suggestions/TileGroupUnitTest.java",
   "junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyControllerTest.java",
+  "junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java",
   "junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java",
   "junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java",
   "junit/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
index 4fa7745..d7fd66843 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.vr_shell;
 
-import org.junit.Assert;
-
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.ChromeActivity;
 
@@ -16,7 +14,6 @@
  * - Allows us to have test-specific behavior if necessary without changing production code
  */
 public class TestVrShellDelegate extends VrShellDelegate {
-    private boolean mOnResumeCalled;
     private Runnable mOnVSyncPausedCallback;
     private static TestVrShellDelegate sInstance;
     private boolean mDisableVrBrowsing;
@@ -110,7 +107,6 @@
             mTestWorkaroundDontCancelVrEntryOnResume = true;
         }
         super.onResume();
-        mOnResumeCalled = true;
         mTestWorkaroundDontCancelVrEntryOnResume = false;
     }
 
@@ -133,19 +129,6 @@
     }
 
     /**
-     * Make sure that onResume is called before onPause.
-     *
-     * This is necessary since we don't want weird problems to show up caused by the delayed
-     * onResume being called after onPause.
-     */
-    @Override
-    protected void onPause() {
-        Assert.assertTrue(mOnResumeCalled);
-        mOnResumeCalled = false;
-        super.onPause();
-    }
-
-    /**
      * If we need to know when the normal VSync gets paused, we have a small window between when
      * the VrShell is created and we actually enter VR to set the callback. So, do it immediately
      * after creation here.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
similarity index 73%
rename from chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyControllerTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
index 0000bcb..6a801da 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
@@ -24,18 +24,17 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.content_public.browser.WebContents;
 
 /**
- * Unit tests for ChromeHomeSurveyController.java.
+ * Unit tests for ChromeSurveyController.java.
  */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
-public class ChromeHomeSurveyControllerTest {
-    private TestChromeHomeSurveyController mTestController;
+public class ChromeSurveyControllerTest {
+    private TestChromeSurveyController mTestController;
     private RiggedSurveyController mRiggedController;
     private SharedPreferences mSharedPreferences;
 
@@ -53,7 +52,7 @@
         MockitoAnnotations.initMocks(this);
         RecordHistogram.setDisabledForTests(true);
 
-        mTestController = new TestChromeHomeSurveyController();
+        mTestController = new TestChromeSurveyController();
         mTestController.setTabModelSelector(mSelector);
         mSharedPreferences = ContextUtils.getAppSharedPreferences();
         mSharedPreferences.edit().clear().apply();
@@ -68,42 +67,17 @@
 
     @Test
     public void testInfoBarDisplayedBefore() {
-        Assert.assertFalse(mSharedPreferences.contains(
-                ChromeHomeSurveyController.SURVEY_INFO_BAR_DISPLAYED_KEY));
+        Assert.assertFalse(
+                mSharedPreferences.contains(ChromeSurveyController.SURVEY_INFO_BAR_DISPLAYED_KEY));
         Assert.assertFalse(mTestController.hasInfoBarBeenDisplayed());
         mSharedPreferences.edit()
-                .putLong(ChromeHomeSurveyController.SURVEY_INFO_BAR_DISPLAYED_KEY,
+                .putLong(ChromeSurveyController.SURVEY_INFO_BAR_DISPLAYED_KEY,
                         System.currentTimeMillis())
                 .apply();
         Assert.assertTrue(mTestController.hasInfoBarBeenDisplayed());
     }
 
     @Test
-    public void testChromeHomeEnabledForOneWeek() {
-        Assert.assertFalse(mTestController.wasChromeHomeEnabledForMinimumOneWeek());
-        Assert.assertFalse(mSharedPreferences.contains(
-                ChromePreferenceManager.CHROME_HOME_SHARED_PREFERENCES_KEY));
-        mSharedPreferences.edit()
-                .putLong(ChromePreferenceManager.CHROME_HOME_SHARED_PREFERENCES_KEY,
-                        System.currentTimeMillis() - ChromeHomeSurveyController.ONE_WEEK_IN_MILLIS)
-                .apply();
-        Assert.assertTrue(mTestController.wasChromeHomeEnabledForMinimumOneWeek());
-    }
-
-    @Test
-    public void testChromeHomeEnabledForLessThanOneWeek() {
-        Assert.assertFalse(mTestController.wasChromeHomeEnabledForMinimumOneWeek());
-        Assert.assertFalse(mSharedPreferences.contains(
-                ChromePreferenceManager.CHROME_HOME_SHARED_PREFERENCES_KEY));
-        mSharedPreferences.edit()
-                .putLong(ChromePreferenceManager.CHROME_HOME_SHARED_PREFERENCES_KEY,
-                        System.currentTimeMillis()
-                                - ChromeHomeSurveyController.ONE_WEEK_IN_MILLIS / 2)
-                .apply();
-        Assert.assertFalse(mTestController.wasChromeHomeEnabledForMinimumOneWeek());
-    }
-
-    @Test
     public void testValidTab() {
         doReturn(mWebContents).when(mTab).getWebContents();
         doReturn(false).when(mTab).isIncognito();
@@ -189,7 +163,7 @@
     @Test
     public void testEligibilityRolledYesterday() {
         mRiggedController = new RiggedSurveyController(0, 5, 10);
-        mSharedPreferences.edit().putInt(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY, 4);
+        mSharedPreferences.edit().putInt(ChromeSurveyController.DATE_LAST_ROLLED_KEY, 4);
         Assert.assertTrue(
                 "Random selection should be true", mRiggedController.isRandomlySelectedForSurvey());
     }
@@ -197,9 +171,7 @@
     @Test
     public void testEligibilityRollingTwiceSameDay() {
         mRiggedController = new RiggedSurveyController(0, 5, 10);
-        mSharedPreferences.edit()
-                .putInt(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY, 5)
-                .apply();
+        mSharedPreferences.edit().putInt(ChromeSurveyController.DATE_LAST_ROLLED_KEY, 5).apply();
         Assert.assertFalse("Random selection should be false",
                 mRiggedController.isRandomlySelectedForSurvey());
     }
@@ -208,25 +180,25 @@
     public void testEligibilityFirstTimeRollingQualifies() {
         mRiggedController = new RiggedSurveyController(0, 5, 10);
         Assert.assertFalse(
-                mSharedPreferences.contains(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY));
+                mSharedPreferences.contains(ChromeSurveyController.DATE_LAST_ROLLED_KEY));
         Assert.assertTrue(
                 "Random selection should be true", mRiggedController.isRandomlySelectedForSurvey());
         Assert.assertEquals("Numbers should match", 5,
-                mSharedPreferences.getInt(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY, -1));
+                mSharedPreferences.getInt(ChromeSurveyController.DATE_LAST_ROLLED_KEY, -1));
     }
 
     @Test
     public void testEligibilityFirstTimeRollingDoesNotQualify() {
         mRiggedController = new RiggedSurveyController(5, 1, 10);
         Assert.assertFalse(
-                mSharedPreferences.contains(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY));
+                mSharedPreferences.contains(ChromeSurveyController.DATE_LAST_ROLLED_KEY));
         Assert.assertFalse(
                 "Random selection should be true", mRiggedController.isRandomlySelectedForSurvey());
         Assert.assertEquals("Numbers should match", 1,
-                mSharedPreferences.getInt(ChromeHomeSurveyController.DATE_LAST_ROLLED_KEY, -1));
+                mSharedPreferences.getInt(ChromeSurveyController.DATE_LAST_ROLLED_KEY, -1));
     }
 
-    class RiggedSurveyController extends ChromeHomeSurveyController {
+    class RiggedSurveyController extends ChromeSurveyController {
         private int mRandomNumberToReturn;
         private int mDayOfYear;
         private int mMaxNumber;
@@ -254,10 +226,10 @@
         }
     }
 
-    class TestChromeHomeSurveyController extends ChromeHomeSurveyController {
+    class TestChromeSurveyController extends ChromeSurveyController {
         private Tab mTab;
 
-        public TestChromeHomeSurveyController() {
+        public TestChromeSurveyController() {
             super();
         }
 
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8903f19..5ed0e17 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8564,7 +8564,7 @@
 
       <!-- Web and message center notifications -->
       <message name="IDS_NOTIFICATIONS_INFOBAR_TEXT" desc="Text requesting permission for Web Notifications.">
-        <ph name="site">$1<ex>mail.google.com</ex></ph> wants to send you notifications.
+        <ph name="site">$1<ex>mail.google.com</ex></ph> wants to send you notifications
       </message>
       <message name="IDS_NOTIFICATION_PERMISSIONS_FRAGMENT" desc="Permission sentence fragment to show following the prompt 'This site wants to:' in a permissions request">
         Show notifications
@@ -9113,7 +9113,7 @@
           Know your unique device identifier
         </message>
         <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_TEXT" desc="Text requesting permission for a site to access protected media identifier. It shows the origin of the URL.">
-          <ph name="URL">$1<ex>https://www.youtube.com</ex></ph> wants to play protected content. Your device’s identity will be verified by Google
+          <ph name="URL">$1<ex>https://www.youtube.com</ex></ph> wants to play protected content. Your device’s identity will be verified by Google.
         </message>
       </if>
       <message name="IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT" desc="A message that the browser shows after saving a password it has autogenerated for the user. This message appears in a bubble and contains a link to all the user's saved autogenerated passwords. The link text is a separate string in the translation console and appears here as placeholder text.">
diff --git a/chrome/app/resources/BUILD.gn b/chrome/app/resources/BUILD.gn
index b557079c..4ebae9de 100644
--- a/chrome/app/resources/BUILD.gn
+++ b/chrome/app/resources/BUILD.gn
@@ -82,7 +82,7 @@
     } else {
       source = "locale_settings_chromiumos.grd"
     }
-  } else if (is_posix) {
+  } else if (is_posix || is_fuchsia) {
     # All other posix systems just use the Linux one.
     source = "locale_settings_linux.grd"
   }
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 53d8e157..c69164847 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">የ<ph name="USERNAME" /> ይለፍ ቃልን ሰርዝ</translation>
 <translation id="1819721979226826163">የመተግበሪያ ማሳወቂያዎች &gt; Google Play አገልግሎቶችን መታ ያድርጉ።</translation>
 <translation id="1826516787628120939">በመፈተሸ ላይ</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> ማሳወቂያዎችን ለእርስዎ ለመላክ ይፈልጋል።</translation>
 <translation id="1828378091493947763">ይህ ተሰኪ በዚህ መሣሪያ ላይ አይደገፍም</translation>
 <translation id="1828901632669367785">የስርዓት መልዕክቱን ተጠቅመው ያትሙ…</translation>
 <translation id="1829192082282182671">&amp;አሳንስ</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 75651ac..8efbf26 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">حذف كلمة مرور <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">‏يُرجى النقر على "إشعارات التطبيق" &gt; خدمات Google Play.</translation>
 <translation id="1826516787628120939">حساب شيكات</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> يريد إرسال إشعارات لك.</translation>
 <translation id="1828378091493947763">هذا المكوِّن الإضافي غير مدعوم على هذا الجهاز</translation>
 <translation id="1828901632669367785">مربع حوار الطباعة باستخدام النظام…</translation>
 <translation id="1829192082282182671">ت&amp;صغير</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index 7985773..04bde613 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Изтриване на паролата за <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Докоснете „Известия за прилож.“ &gt; Услуги за Google Play.</translation>
 <translation id="1826516787628120939">Извършва се проверка</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> иска да ви изпраща известия.</translation>
 <translation id="1828378091493947763">Тази приставка не се поддържа на устройството</translation>
 <translation id="1828901632669367785">Печат чрез системния диалогов прозорец...</translation>
 <translation id="1829192082282182671">&amp;Намаляване</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 318a0731..9af2c9fa 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -551,7 +551,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> এর পাসওয়ার্ড মুছে দিন</translation>
 <translation id="1819721979226826163">অ্যাপ বিজ্ঞপ্তি &gt; Google Play পরিষেবা ট্যাপ করুন।</translation>
 <translation id="1826516787628120939">চেক করা হচ্ছে</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> আপনাকে বিজ্ঞপ্তি পাঠাতে চায়।</translation>
 <translation id="1828378091493947763">এই ডিভাইসে এই প্লাগ ইন সমর্থিত নয়</translation>
 <translation id="1828901632669367785">সিস্টেম কথোপকথন ব্যবহার করে প্রিন্ট করুন...</translation>
 <translation id="1829192082282182671">Zoom &amp;Out</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index f5013d0f..066caac3 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Suprimeix la contrasenya de: <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Toca Notificacions d'aplicacions &gt; Serveis de Google Play.</translation>
 <translation id="1826516787628120939">S'està comprovant</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> us vol enviar notificacions.</translation>
 <translation id="1828378091493947763">Aquest connector no és compatible amb el dispositiu</translation>
 <translation id="1828901632669367785">Imprimeix des de la finestra de diàleg del sistema…</translation>
 <translation id="1829192082282182671">&amp;Redueix</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 02f8507..32d3fdc8 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Smazat heslo uživatele <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Klepněte na Oznámení aplikací &gt; Služby Google Play.</translation>
 <translation id="1826516787628120939">Probíhá kontrola</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> vám chce zasílat oznámení.</translation>
 <translation id="1828378091493947763">Tento plugin v tomto zařízení není podporován</translation>
 <translation id="1828901632669367785">Vytisknout prostřednictvím dialogového okna systému...</translation>
 <translation id="1829192082282182671">&amp;Oddálit</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 76eea36..de0511b0 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Slet adgangskoden til <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tryk på Appunderretninger &gt; Google Play-tjenester.</translation>
 <translation id="1826516787628120939">Kontrollerer</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> ønsker at sende dig underretninger.</translation>
 <translation id="1828378091493947763">Dette plugin understøttes ikke på denne enhed</translation>
 <translation id="1828901632669367785">Dialogboks til Udskriv via system...</translation>
 <translation id="1829192082282182671">Zoom &amp;ud</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index e2c00fda..e206d51 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Passwort löschen für <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tippen Sie auf "App-Benachrichtigungen" &gt; "Google Play-Dienste".</translation>
 <translation id="1826516787628120939">Überprüfung läuft</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> möchte Ihnen Benachrichtigungen senden.</translation>
 <translation id="1828378091493947763">Dieses Plug-in wird auf diesem Gerät nicht unterstützt</translation>
 <translation id="1828901632669367785">Über das Systemdialogfeld drucken...</translation>
 <translation id="1829192082282182671">Ver&amp;kleinern</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index 998c48b..d226f57 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Διαγραφή κωδικού πρόσβασης για τον λογαριασμό <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Πατήστε Ειδοποιήσεις εφαρμογών &gt; Υπηρεσίες Google Play.</translation>
 <translation id="1826516787628120939">Έλεγχος</translation>
-<translation id="1828149253358786390">Η διεύθυνση <ph name="SITE" /> θέλει να σας στείλει ειδοποιήσεις.</translation>
 <translation id="1828378091493947763">Αυτή η προσθήκη δεν υποστηρίζεται σε αυτήν τη συσκευή</translation>
 <translation id="1828901632669367785">Εκτύπωση με χρήση του παραθύρου διαλόγου του συστήματος...</translation>
 <translation id="1829192082282182671">Σμίκρυνση</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index 39e2d3a..84a5542 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Delete password for <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tap App notifications &gt; Google Play services.</translation>
 <translation id="1826516787628120939">Checking</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> wants to send you notifications.</translation>
 <translation id="1828378091493947763">This plug-in is not supported on this device</translation>
 <translation id="1828901632669367785">Print Using System Dialogue...</translation>
 <translation id="1829192082282182671">Zoom &amp;Out</translation>
@@ -2112,6 +2111,7 @@
 <translation id="4206944295053515692">Ask Google for Suggestions</translation>
 <translation id="4208390505124702064">Search <ph name="SITE_NAME" /></translation>
 <translation id="4209092469652827314">Large</translation>
+<translation id="4209464433672152343">Documents are <ph name="BEGIN_LINK_HELP" />sent to Google<ph name="END_LINK_HELP" /> to prepare them for printing. View, edit and manage your printers and printer history on the <ph name="BEGIN_LINK_DASHBOARD" />Google Cloud Print dashboard<ph name="END_LINK_DASHBOARD" />.</translation>
 <translation id="421017592316736757">You must be online to access this file.</translation>
 <translation id="421182450098841253">&amp;Show Bookmarks Bar</translation>
 <translation id="42126664696688958">Export</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index 64051b0..1b35569 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Borrar la contraseña para <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Presiona Notificaciones de apps &gt; Servicios de Google Play.</translation>
 <translation id="1826516787628120939">Comprobando</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> quiere enviarte notificaciones.</translation>
 <translation id="1828378091493947763">Este complemento no es compatible con este dispositivo</translation>
 <translation id="1828901632669367785">Imprimir utilizando el diálogo del sistema…</translation>
 <translation id="1829192082282182671">Alejar</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 93f5409..3c070ef 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Eliminar la contraseña de <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Toca Notificaciones de aplicaciones &gt; Servicios de Google Play.</translation>
 <translation id="1826516787628120939">Comprobando</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> quiere enviarte notificaciones.</translation>
 <translation id="1828378091493947763">Este complemento no se admite en este dispositivo</translation>
 <translation id="1828901632669367785">Imprimir utilizando el cuadro de diálogo del sistema</translation>
 <translation id="1829192082282182671">&amp;Reducir zoom</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index f9f8885..c5914bae 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Kustuta kasutaja <ph name="USERNAME" /> parool</translation>
 <translation id="1819721979226826163">Puudutage valikuid Rakenduse märguanded &gt; Google Play teenused.</translation>
 <translation id="1826516787628120939">Kontrollimine</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> soovib teile saata märguandeid.</translation>
 <translation id="1828378091493947763">Seda pistikprogrammi selles seadmes ei toetata</translation>
 <translation id="1828901632669367785">Prindi, kasutades süsteemidialoogi ...</translation>
 <translation id="1829192082282182671">&amp;Vähenda</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index 55ac61d..a1b850c4 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">گذرواژه مربوط به <ph name="USERNAME" /> حذف شود</translation>
 <translation id="1819721979226826163">‏روی «اعلان‌های برنامه &gt; خدمات Google Play» ضربه بزنید.</translation>
 <translation id="1826516787628120939">در حال بررسی</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> می‌خواهد برایتان اعلان بفرستد.</translation>
 <translation id="1828378091493947763">این افزایه در این دستگاه پشتیبانی نمی‌شود</translation>
 <translation id="1828901632669367785">چاپ با استفاده از گفتگوی سیستم...</translation>
 <translation id="1829192082282182671">کوچک&amp; نمایی</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 1ec3a7a..febd9653 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Poista salasana: <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Valitse Sovellusilmoitukset &gt; Google Play Palvelut.</translation>
 <translation id="1826516787628120939">Tarkistetaan</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> haluaa lähettää sinulle ilmoituksia.</translation>
 <translation id="1828378091493947763">Laite ei tue tätä laajennusta.</translation>
 <translation id="1828901632669367785">Tulosta järjestelmän tulostusikkunalla...</translation>
 <translation id="1829192082282182671">L&amp;oitonna</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index 53c42283..bfef26c7 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">I-delete ang password para sa <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">I-tap ang Mga notification ng app &gt; Mga serbisyo ng Google Play.</translation>
 <translation id="1826516787628120939">Sinusuri</translation>
-<translation id="1828149253358786390">Gusto kang padalhan ng <ph name="SITE" /> ng mga notification.</translation>
 <translation id="1828378091493947763">Hindi sinusuportahan ang plugin na ito para sa device na ito</translation>
 <translation id="1828901632669367785">I-print Gamit ang Dialog ng System...</translation>
 <translation id="1829192082282182671">Mag-zoom &amp;Out</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index de807bd..f39135f2 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Supprimer le mot de passe du compte <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Appuyez sur Notifications des applications &gt; Services Google Play.</translation>
 <translation id="1826516787628120939">Vérification en cours…</translation>
-<translation id="1828149253358786390">"<ph name="SITE" />" requiert l'envoi de notifications.</translation>
 <translation id="1828378091493947763">Ce plug-in n'est pas compatible avec cet appareil.</translation>
 <translation id="1828901632669367785">Imprimer via la boîte de dialogue système...</translation>
 <translation id="1829192082282182671">Z&amp;oom arrière</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 8de88b2..d6b3302 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -547,7 +547,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> માટેનો પાસવર્ડ ડિલીટ કરો</translation>
 <translation id="1819721979226826163">ઍપ નોટિફિકેશન &gt; Google Play સેવાઓને ટૅપ કરો.</translation>
 <translation id="1826516787628120939">તપાસી રહ્યાં છે</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> તમને સૂચનાઓ મોકલવા માંગે છે.</translation>
 <translation id="1828378091493947763">આ ઉપકરણ પર આ પ્લગ-ઇન સમર્થિત નથી</translation>
 <translation id="1828901632669367785">સિસ્ટમ સંવાદનો ઉપયોગ કરીને છાપો... </translation>
 <translation id="1829192082282182671">Zoom &amp;Out</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 34378c5c..c0d6dd9 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> का पासवर्ड मिटाएं</translation>
 <translation id="1819721979226826163">ऐप्लिकेशन सूचनाएं &gt; Google Play सेवाएं पर टैप करें.</translation>
 <translation id="1826516787628120939">जाँच की जा रही है</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> आपको नोटिफ़िकेशन भेजना चाहती है.</translation>
 <translation id="1828378091493947763">यह प्लग इन इस डिवाइस पर समर्थित नहीं है</translation>
 <translation id="1828901632669367785">सिस्‍टम डॉयलॉग का उपयोग करके प्रिंट करें…</translation>
 <translation id="1829192082282182671">ज़ूम &amp;आउट करें</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index ba97f43..3867d815b 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Izbrišite zaporku za <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Dodirnite Obavijesti aplikacije &gt; Google Play usluge.</translation>
 <translation id="1826516787628120939">Provjera</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> želi vam slati obavijesti.</translation>
 <translation id="1828378091493947763">Ovaj dodatak nije podržan na ovom uređaju</translation>
 <translation id="1828901632669367785">Ispis pomoću dijaloškog okvira sustava...</translation>
 <translation id="1829192082282182671">Zoom &amp;Out (Smanji)</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 6e3358b..0e474b34 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> jelszavának törlése</translation>
 <translation id="1819721979226826163">Koppintson az Alkalmazásértesítések &gt; Google Play-szolgáltatások menüpontra.</translation>
 <translation id="1826516787628120939">Ellenőrzés</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> értesítéseket szeretne küldeni Önnek.</translation>
 <translation id="1828378091493947763">Ez a beépülő modul nem támogatott ezen az eszközön</translation>
 <translation id="1828901632669367785">Nyomtatás a rendszer párbeszédpanelének segítségével...</translation>
 <translation id="1829192082282182671">Kics&amp;inyítés</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index 70a9365c..6575fab 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Hapus sandi untuk <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tap Notifikasi aplikasi &gt; Layanan Google Play.</translation>
 <translation id="1826516787628120939">Memeriksa</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> ingin mengirimi Anda notifikasi.</translation>
 <translation id="1828378091493947763">Plugin tidak didukung di perangkat ini</translation>
 <translation id="1828901632669367785">Cetak Menggunakan Dialog Sistem...</translation>
 <translation id="1829192082282182671">Per&amp;kecil</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index 32c36e4..7b3a51a 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Elimina la password di <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tocca Notifiche app &gt; Google Play Services.</translation>
 <translation id="1826516787628120939">Verifica in corso...</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> desidera inviarti le notifiche.</translation>
 <translation id="1828378091493947763">Questo plug-in non è supportato sul dispositivo in uso</translation>
 <translation id="1828901632669367785">Stampa utilizzando la finestra di dialogo di sistema...</translation>
 <translation id="1829192082282182671">Riduc&amp;i</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 31acdac9..64d75a0 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">מחיקת הסיסמה של <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">‏מקישים על 'הודעות אפליקציה' &gt; 'שירותי Google Play'.</translation>
 <translation id="1826516787628120939">מתבצעת בדיקה</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> רוצה לשלוח לך הודעות.</translation>
 <translation id="1828378091493947763">הפלאגין אינו נתמך במכשיר זה</translation>
 <translation id="1828901632669367785">הדפס באמצעות תיבת דו-שיח של המערכת...</translation>
 <translation id="1829192082282182671">הת&amp;רחק</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 8a412a7..283b5e99 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> のパスワードを削除します</translation>
 <translation id="1819721979226826163">[アプリの通知] &gt; [Google Play 開発者サービス] の順にタップします。</translation>
 <translation id="1826516787628120939">確認中</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> が通知を送信しようとしています。</translation>
 <translation id="1828378091493947763">このプラグインはこの端末ではサポートされていません</translation>
 <translation id="1828901632669367785">システム ダイアログを使用して印刷...</translation>
 <translation id="1829192082282182671">縮小(&amp;O)</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index fc836eb9..20251c7 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -548,7 +548,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> ಗಾಗಿ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ</translation>
 <translation id="1819721979226826163">ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆಗಳು &gt; Google Play ಸೇವೆಗಳನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ.</translation>
 <translation id="1826516787628120939">ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</translation>
-<translation id="1828149253358786390">ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು <ph name="SITE" /> ಬಯಸುತ್ತದೆ.</translation>
 <translation id="1828378091493947763">ಈ ಸಾಧನದಲ್ಲಿ ಈ ಪ್ಲಗಿನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ</translation>
 <translation id="1828901632669367785">ಸಿಸ್ಟಂ ಸಂವಾದವನ್ನು ಬಳಸಿಕೊಂಡು ಮುದ್ರಿಸಿ...</translation>
 <translation id="1829192082282182671">ಝೂಮ್ &amp;ಔಟ್</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index 69c0dfe..9d4646f3 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" />님의 비밀번호 삭제</translation>
 <translation id="1819721979226826163">앱 알림 &gt; Google Play 서비스를 탭합니다.</translation>
 <translation id="1826516787628120939">확인 중</translation>
-<translation id="1828149253358786390"><ph name="SITE" />에서 알림을 보내려고 합니다.</translation>
 <translation id="1828378091493947763">이 기기에서 지원되지 않는 플러그인입니다.</translation>
 <translation id="1828901632669367785">시스템 대화상자를 사용하여 인쇄...</translation>
 <translation id="1829192082282182671">축소(&amp;O)</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index 30071f5..1a20223d 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Ištrinti <ph name="USERNAME" /> slaptažodį</translation>
 <translation id="1819721979226826163">Palieskite „Programų pranešimai“ &gt; „Google Play“ paslaugos“.</translation>
 <translation id="1826516787628120939">Tikrinama</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> nori jums siųsti pranešimus.</translation>
 <translation id="1828378091493947763">Šis papildinys šiame įrenginyje nepalaikomas</translation>
 <translation id="1828901632669367785">Spausdinti naudojant sistemos dialogo langą...</translation>
 <translation id="1829192082282182671">Tolin&amp;ti</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index 43e414b9..401711c 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Dzēst lietotāja <ph name="USERNAME" /> paroli</translation>
 <translation id="1819721979226826163">Pieskarieties vienumam Lietotņu paziņojumi &gt; Google Play pakalpojumi.</translation>
 <translation id="1826516787628120939">Pārbaude</translation>
-<translation id="1828149253358786390">No vietnes <ph name="SITE" /> tiek mēģināts nosūtīt paziņojumus.</translation>
 <translation id="1828378091493947763">Spraudnis šajā ierīcē netiek atbalstīts</translation>
 <translation id="1828901632669367785">Drukāt, izmantojot sistēmas dialoglodziņu...</translation>
 <translation id="1829192082282182671">Tālināt</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 0fca4516..f86ed19 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> എന്നതിന്‍റെ പാസ്‌വേഡ് ഇല്ലാതാക്കുക</translation>
 <translation id="1819721979226826163">ആപ്പ് അറിയിപ്പുകൾ &gt; Google Play സേവനങ്ങൾ ടാപ്പ് ചെയ്യുക.</translation>
 <translation id="1826516787628120939">പരിശോധിക്കുന്നു</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയയ്‌ക്കാൻ താൽപ്പര്യപ്പെടുന്നു.</translation>
 <translation id="1828378091493947763">ഈ പ്ലഗിൻ ഈ ഉപകരണത്തിൽ പിന്തുണയ്‌ക്കുന്നില്ല</translation>
 <translation id="1828901632669367785">സിസ്റ്റം ഡയലോഗ് ഉപയോഗിച്ച് പ്രിന്റ് ചെയ്യുക...</translation>
 <translation id="1829192082282182671">സൂം &amp;ഔട്ട് ചെയ്യുക</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 1430da02..c49f772 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -555,7 +555,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> चा पासवर्ड हटवा</translation>
 <translation id="1819721979226826163">अ‍ॅप सूचना &gt; Google Play सेवा वर टॅप करा.</translation>
 <translation id="1826516787628120939">तपासत आहे</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> आपल्याला सूचना पाठवू इच्छिते.</translation>
 <translation id="1828378091493947763">हे प्लगिन या डिव्हाइसवर समर्थित नाही</translation>
 <translation id="1828901632669367785">सिस्टम संवाद वापरून प्रिंट करा…</translation>
 <translation id="1829192082282182671">झूम &amp;कमी करा</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index a516e508..e9e75cf 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Padam kata laluan untuk <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Ketik Pemberitahuan apl &gt; Perkhidmatan Google Play.</translation>
 <translation id="1826516787628120939">Menyemak</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> mahu menghantar pemberitahuan kepada anda.</translation>
 <translation id="1828378091493947763">Pemalam ini tidak disokong pada peranti ini</translation>
 <translation id="1828901632669367785">Cetak Menggunakan Dialog Sistem...</translation>
 <translation id="1829192082282182671">Zum &amp;Keluar</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 26de258..dbe5787 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Wachtwoord voor <ph name="USERNAME" /> verwijderen</translation>
 <translation id="1819721979226826163">Tik op App-meldingen &gt; Google Play-services.</translation>
 <translation id="1826516787628120939">Controleren</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> wil jou meldingen sturen.</translation>
 <translation id="1828378091493947763">Deze plug-in wordt niet ondersteund op dit apparaat</translation>
 <translation id="1828901632669367785">Afdrukken met systeemdialoogvenster...</translation>
 <translation id="1829192082282182671">Uitz&amp;oomen</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index 6f106efe..0af8ef6 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Slett passordet for <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Trykk på Appvarsler &gt; Google Play Tjenester.</translation>
 <translation id="1826516787628120939">Kontrollerer</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> vil sende deg varsler.</translation>
 <translation id="1828378091493947763">Dette programtillegget støttes ikke på denne enheten</translation>
 <translation id="1828901632669367785">Skriv ut ved hjelp av systemdialog</translation>
 <translation id="1829192082282182671">Zoom &amp;ut</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index 1392f813..d6f95f6 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Usuń hasło użytkownika <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Kliknij Powiadomienia z aplikacji &gt; Usługi Google Play.</translation>
 <translation id="1826516787628120939">Sprawdzam</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> chce wysyłać Ci powiadomienia.</translation>
 <translation id="1828378091493947763">To urządzenie nie obsługuje tej wtyczki</translation>
 <translation id="1828901632669367785">Drukuj w oknie systemowym</translation>
 <translation id="1829192082282182671">Po&amp;mniejsz</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index cb35cb4..97c938a 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Excluir a senha de <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Toque em Notificações de apps &gt; Google Play Services.</translation>
 <translation id="1826516787628120939">Em verificação</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> quer enviar notificações a você.</translation>
 <translation id="1828378091493947763">Este plug-in não é compatível com este dispositivo</translation>
 <translation id="1828901632669367785">Imprimir utilizando caixa de diálogo de sistema...</translation>
 <translation id="1829192082282182671">Diminuir &amp;zoom</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index f8dbd35..6d90bf42 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Eliminar a palavra-passe para <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Toque em Notificações da aplicação &gt; Serviços do Google Play.</translation>
 <translation id="1826516787628120939">A verificar</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> pretende enviar-lhe notificações.</translation>
 <translation id="1828378091493947763">Este plug-in não é compatível com este dispositivo</translation>
 <translation id="1828901632669367785">Imprimir Utilizando a Caixa de Diálogo do Sistema...</translation>
 <translation id="1829192082282182671">Re&amp;duzir</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 500140a..80dbf7b 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Șterge parola pentru <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Atinge Notificări din aplicații &gt; Servicii Google Play.</translation>
 <translation id="1826516787628120939">Se verifică</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> dorește să îți trimită notificări.</translation>
 <translation id="1828378091493947763">Acest plugin nu este acceptat pe dispozitiv</translation>
 <translation id="1828901632669367785">Printați utilizând caseta de dialog a sistemului...</translation>
 <translation id="1829192082282182671">Mi&amp;cșorează</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index 381fb52c..67cb21c 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -556,7 +556,6 @@
 <translation id="1818007989243628752">Удалить пароль пользователя <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Нажмите "Уведомления приложений &gt; Сервисы Google Play".</translation>
 <translation id="1826516787628120939">Проверка</translation>
-<translation id="1828149253358786390">Сайт <ph name="SITE" /> запрашивает разрешение на отправку уведомлений</translation>
 <translation id="1828378091493947763">Плагин не поддерживается на этом устройстве</translation>
 <translation id="1828901632669367785">Печатать с помощью системного диалогового окна</translation>
 <translation id="1829192082282182671">&amp;Уменьшить</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index ebf487f..0a10dfc4 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Odstrániť heslo používateľa <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Klepnite na položky Upozornenia aplikácií &gt; Služby Google Play.</translation>
 <translation id="1826516787628120939">Kontroluje sa</translation>
-<translation id="1828149253358786390">Stránky <ph name="SITE" /> vám chcú posielať upozornenia.</translation>
 <translation id="1828378091493947763">Doplnok nie je v tomto zariadení podporovaný</translation>
 <translation id="1828901632669367785">Tlačiť prostredníctvom dialógového okna systému...</translation>
 <translation id="1829192082282182671">&amp;Oddialiť</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index dbce6b0..35e26ff 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Izbris gesla za <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Dotaknite se »Obvestila aplikacije &gt; Storitve Google Play«.</translation>
 <translation id="1826516787628120939">Preverjanje</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> vam želi pošiljati obvestila.</translation>
 <translation id="1828378091493947763">Ta vtičnik ni podprt v tej napravi</translation>
 <translation id="1828901632669367785">Tiskanje v sistemskem pogovornem oknu ...</translation>
 <translation id="1829192082282182671">Poma&amp;njšaj</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 6981a34..0ed6c5f7 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -554,7 +554,6 @@
 <translation id="1818007989243628752">Избришите лозинку за <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Додирните Обавештења о апликацији &gt; Google Play услуге.</translation>
 <translation id="1826516787628120939">Провера</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> жели да вам шаље обавештења.</translation>
 <translation id="1828378091493947763">Ова додатна компонента није подржана на овом уређају</translation>
 <translation id="1828901632669367785">Одштампај помоћу системског дијалога...</translation>
 <translation id="1829192082282182671">Zoom &amp;Out (Умањи)</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index 90f6664..f0b433c6 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -556,7 +556,6 @@
 <translation id="1818007989243628752">Radera lösenordet för <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Tryck på Appaviseringar &gt; Google Play-tjänster.</translation>
 <translation id="1826516787628120939">Kontrollerar</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> vill skicka aviseringar.</translation>
 <translation id="1828378091493947763">Enheten har inte stöd för det här pluginprogrammet</translation>
 <translation id="1828901632669367785">Skriv ut via systemets dialogruta ...</translation>
 <translation id="1829192082282182671">Zooma ut</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index 935b7b8..caad605e 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -555,7 +555,6 @@
 <translation id="1818007989243628752">Futa nenosiri la <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Gusa Arifa za programu &gt; Huduma za Google Play.</translation>
 <translation id="1826516787628120939">Inakagua</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> inataka kukutumia arifa.</translation>
 <translation id="1828378091493947763">Programu-jalizi hii haitumiki kwenye kifaa hiki</translation>
 <translation id="1828901632669367785">Chapisha kwa Kutumia Kidadisi cha Mfumo...</translation>
 <translation id="1829192082282182671">Fif&amp;iza</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index ae34566..5ed67cb9 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> இன் கடவுச்சொல்லை நீக்கும்</translation>
 <translation id="1819721979226826163">பயன்பாட்டு அறிவிப்புகள் &gt; Google Play சேவைகள் என்பதைத் தட்டவும்.</translation>
 <translation id="1826516787628120939">சரிபார்க்கிறது</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> உங்களுக்கு அறிவிப்புகளை அனுப்ப விரும்புகிறது.</translation>
 <translation id="1828378091493947763">சாதனத்தில் இந்தச் செருகுநிரல் ஆதரிக்கப்படவில்லை</translation>
 <translation id="1828901632669367785">கணினி உரையாடலைப் பயன்படுத்தி அச்சிடுக…</translation>
 <translation id="1829192082282182671">Zoom &amp;Out</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index c828ceb7..74445c2b 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -551,7 +551,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> యొక్క పాస్‌వర్డ్‌ను తొలగించండి</translation>
 <translation id="1819721979226826163">యాప్ నోటిఫికేషన్‌లు &gt; Google Play సేవలను నొక్కండి.</translation>
 <translation id="1826516787628120939">తనిఖీ చేస్తోంది</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> మీకు నోటిఫికేషన్‌లను పంపాలనుకుంటోంది.</translation>
 <translation id="1828378091493947763">ఈ పరికరంలో ఈ ప్లగిన్‌కు మద్దతు లేదు</translation>
 <translation id="1828901632669367785">సిస్టమ్ డైలాగ్‌ని ఉపయోగించి ముద్రించు...</translation>
 <translation id="1829192082282182671">&amp;దూరంగా జూమ్ చెయ్యి</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index 75d20fb..9b69069 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">ลบรหัสผ่านสำหรับ <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">แตะ "การแจ้งเตือนของแอป" &gt; บริการ Google Play</translation>
 <translation id="1826516787628120939">กำลังตรวจสอบ</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> ต้องการส่งการแจ้งเตือนถึงคุณ</translation>
 <translation id="1828378091493947763">อุปกรณ์นี้ไม่รองรับปลั๊กอินนี้</translation>
 <translation id="1828901632669367785">พิมพ์โดยใช้ช่องโต้ตอบของระบบ…</translation>
 <translation id="1829192082282182671">ย่อ</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index c93b8c7..d7e3e68 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752"><ph name="USERNAME" /> kullanıcısının şifresini sil</translation>
 <translation id="1819721979226826163">Uygulama bildirimleri &gt; Google Play hizmetlerine dokunun.</translation>
 <translation id="1826516787628120939">Kontrol ediliyor</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> size bildirim göndermek istiyor.</translation>
 <translation id="1828378091493947763">Bu eklenti, bu cihazda desteklenmiyor</translation>
 <translation id="1828901632669367785">Sistem İletişim Kutusunu Kullanarak Yazdır…</translation>
 <translation id="1829192082282182671">U&amp;zaklaştır</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index d3bdc4e..984f5ec 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">Видалити пароль для <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Торкніться меню "Сповіщення додатків" &gt; "Сервіси Google Play".</translation>
 <translation id="1826516787628120939">Перевірка</translation>
-<translation id="1828149253358786390">Сайт <ph name="SITE" /> хоче надсилати вам сповіщення.</translation>
 <translation id="1828378091493947763">Цей плагін не підтримується на цьому пристрої</translation>
 <translation id="1828901632669367785">Друкувати за допомогою діалогового вікна системи...</translation>
 <translation id="1829192082282182671">Зменшити &amp;масштаб</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 59c51d1..9a35e886 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -558,7 +558,6 @@
 <translation id="1818007989243628752">Xóa mật khẩu của <ph name="USERNAME" /></translation>
 <translation id="1819721979226826163">Nhấn vào Thông báo ứng dụng &gt; Dịch vụ của Google Play.</translation>
 <translation id="1826516787628120939">Đang kiểm tra</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> muốn gửi cho bạn thông báo.</translation>
 <translation id="1828378091493947763">Thiết bị này không hỗ trợ plugin này</translation>
 <translation id="1828901632669367785">In bằng hộp thoại hệ thống...</translation>
 <translation id="1829192082282182671">Thu &amp;nhỏ</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 2580464c..52dad6e7 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -517,6 +517,7 @@
 <translation id="177336675152937177">托管应用数据</translation>
 <translation id="1774349594977710164">您的手机也可解锁您的其他 <ph name="DEVICE_TYPE" />,因为它们已自动同步。</translation>
 <translation id="1774833706453699074">为打开的网页添加书签…</translation>
+<translation id="1775381402323441512">视频信息</translation>
 <translation id="1776883657531386793"><ph name="OID" />: <ph name="INFO" /></translation>
 <translation id="177694132944350798">您的数据已于 <ph name="TIME" />使用您的 Google 密码加密。输入该密码即可开始同步。</translation>
 <translation id="1779652936965200207">请在“<ph name="DEVICE_NAME" />”上输入此匹配密钥:</translation>
@@ -553,12 +554,12 @@
 <translation id="1818007989243628752">删除 <ph name="USERNAME" /> 的密码</translation>
 <translation id="1819721979226826163">依次点按“应用通知”&gt;“Google Play 服务”。</translation>
 <translation id="1826516787628120939">正在检查</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> 想向您发送通知。</translation>
 <translation id="1828378091493947763">该插件在此设备上不受支持</translation>
 <translation id="1828901632669367785">使用系统对话框进行打印...</translation>
 <translation id="1829192082282182671">缩小(&amp;O)</translation>
 <translation id="1830550083491357902">未登录</translation>
 <translation id="1832511806131704864">配对手机已更新</translation>
+<translation id="1834503245783133039">未能成功下载“<ph name="FILE_NAME" />”</translation>
 <translation id="1838374766361614909">清除搜索字词</translation>
 <translation id="1838709767668011582">Google 网站</translation>
 <translation id="1839704667838141620">更改此文件的分享方式</translation>
@@ -695,6 +696,7 @@
 <translation id="2079053412993822885">如果您删除了自己的某个证书,则不能再用该证书标识自己的身份。</translation>
 <translation id="2079545284768500474">撤消</translation>
 <translation id="2080070583977670716">更多设置</translation>
+<translation id="2084108471225856927">设备设置</translation>
 <translation id="2085470240340828803">名为“<ph name="FILENAME" />”的文件已存在,要如何处理?</translation>
 <translation id="2087822576218954668">打印:<ph name="PRINT_NAME" /></translation>
 <translation id="2089566709556890888">使用 Google Chrome 进行安全浏览</translation>
@@ -1415,6 +1417,7 @@
 <translation id="3130528281680948470">您的设备将被重置,且所有用户帐号和本地数据都将移除。此操作无法撤消。</translation>
 <translation id="313205617302240621">忘记了密码?</translation>
 <translation id="3135204511829026971">旋转屏幕</translation>
+<translation id="313963229645891001">正在下载,<ph name="STATUS" /></translation>
 <translation id="3139925690611372679">默认的黄色头像</translation>
 <translation id="3140353188828248647">将地址栏设为焦点</translation>
 <translation id="3141318088920353606">正在听取…</translation>
@@ -1540,6 +1543,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="3335337277364016868">录制年份</translation>
 <translation id="3335947283844343239">重新打开关闭的标签页</translation>
 <translation id="3340978935015468852">设置</translation>
 <translation id="3341703758641437857">允许访问文件网址</translation>
@@ -1601,6 +1605,7 @@
 <translation id="3435738964857648380">安全</translation>
 <translation id="3435896845095436175">启用</translation>
 <translation id="3436038974659740746">自定义拼写检查</translation>
+<translation id="3437801641691368414">创建时间</translation>
 <translation id="3438633801274389918">忍者</translation>
 <translation id="3439153939049640737">始终允许 <ph name="HOST" /> 使用您的麦克风</translation>
 <translation id="3439970425423980614">准备使用预览程序打开 PDF</translation>
@@ -1644,6 +1649,7 @@
 <translation id="3487007233252413104">匿名函数</translation>
 <translation id="348780365869651045">正在等待 AppCache...</translation>
 <translation id="3488065109653206955">部分激活</translation>
+<translation id="348999362308956431">“<ph name="FILE_NAME" />”已下载完毕</translation>
 <translation id="3492788708641132712">无法同步。请尝试重新登录。</translation>
 <translation id="3493881266323043047">有效期</translation>
 <translation id="3494769164076977169">当网站下载第一个文件后要自动下载更多文件时询问您(推荐)</translation>
@@ -1747,6 +1753,7 @@
 <translation id="3646789916214779970">重置为默认主题背景</translation>
 <translation id="3648348069317717750">检测到<ph name="USB_DEVICE_NAME" /></translation>
 <translation id="3649138363871392317">照片已拍摄</translation>
+<translation id="3650952250015018111">允许“<ph name="APP_NAME" />”访问:</translation>
 <translation id="3651488188562686558">断开 Wi-Fi 连接</translation>
 <translation id="3652817283076144888">正在初始化</translation>
 <translation id="3653999333232393305">继续允许 <ph name="HOST" /> 使用您的麦克风</translation>
@@ -1859,6 +1866,7 @@
 <translation id="381202950560906753">添加其他指纹</translation>
 <translation id="3812525830114410218">证书有误</translation>
 <translation id="3813296892522778813">如果您找不到要查找的内容,请参阅 <ph name="BEGIN_LINK_CHROMIUM" />Google Chrome 帮助<ph name="END_LINK_CHROMIUM" /></translation>
+<translation id="3817579325494460411">未提供</translation>
 <translation id="3819007103695653773">允许所有网站发送后台推送消息</translation>
 <translation id="3819752733757735746">开关控制(只需一两个开关即可控制计算机)</translation>
 <translation id="3819800052061700452">全屏(&amp;F)</translation>
@@ -1951,6 +1959,7 @@
 <translation id="394984172568887996">从 IE 中导入</translation>
 <translation id="3950820424414687140">登录</translation>
 <translation id="3954354850384043518">正在下载</translation>
+<translation id="3954469006674843813"><ph name="WIDTH" />x<ph name="HEIGHT" />(<ph name="REFRESH_RATE" /> 赫兹)</translation>
 <translation id="3955193568934677022">允许网站播放受保护的内容(推荐)</translation>
 <translation id="3956702100721821638">无法连接到 Google Play</translation>
 <translation id="3958088479270651626">导入书签和设置</translation>
@@ -2030,6 +2039,7 @@
 <ph name="EXTENSION_FILE" /></translation>
 <translation id="4087470595660267445">在 Chromebook 上安装从 Google Play 下载的应用和游戏。&lt;a target="_blank" href="<ph name="URL" />"&gt;了解详情&lt;/a&gt;</translation>
 <translation id="4088095054444612037">代表群组接受</translation>
+<translation id="4089235344645910861">已保存设置。已开始同步。</translation>
 <translation id="4090103403438682346">允许已通过验证的访问凭证</translation>
 <translation id="4090535558450035482">(此扩展程序由政策控制,无法移除。)</translation>
 <translation id="4091434297613116013">张纸</translation>
@@ -2109,6 +2119,7 @@
 <translation id="4244238649050961491">查找更多触控笔应用</translation>
 <translation id="424546999567421758">检测到磁盘占用量非常高</translation>
 <translation id="424726838611654458">始终用Adobe Reader打开</translation>
+<translation id="4247901771970415646">无法同步到“<ph name="USERNAME" />”</translation>
 <translation id="4249248555939881673">正在等待建立网络连接…</translation>
 <translation id="4249373718504745892">已禁止此网页使用您的摄像头和麦克风。</translation>
 <translation id="424963718355121712">应用的安装来源必须是其自己发挥作用的主机</translation>
@@ -2146,6 +2157,7 @@
 <translation id="4305227814872083840">长(2 秒)</translation>
 <translation id="4306119971288449206">应用必须以“<ph name="CONTENT_TYPE" />”这种内容类型提供</translation>
 <translation id="4309420042698375243"><ph name="NUM_KILOBYTES" /> K(实际大小为 <ph name="NUM_KILOBYTES_LIVE" /> K)</translation>
+<translation id="4309915981827077375">基本信息</translation>
 <translation id="4310139701823742692">文件格式有误。请检查 PPD 文件,然后重试。</translation>
 <translation id="431076611119798497">详细信息(&amp;D)</translation>
 <translation id="4312866146174492540">屏蔽(默认)</translation>
@@ -2194,6 +2206,7 @@
 <translation id="4409697491990005945">边距</translation>
 <translation id="4411578466613447185">代码签名人</translation>
 <translation id="4412698727486357573">帮助中心</translation>
+<translation id="44141919652824029">允许“<ph name="APP_NAME" />”获取您所连接的 USB 设备的列表?</translation>
 <translation id="4414232939543644979">打开新的无痕窗口(&amp;I)</translation>
 <translation id="4415748029120993980">SECG 椭圆曲线 secp384r1(又称 NIST P-384)</translation>
 <translation id="4419409365248380979">总是允许 <ph name="HOST" /> 设置 Cookie</translation>
@@ -2287,6 +2300,7 @@
 <translation id="4565377596337484307">隐藏密码</translation>
 <translation id="4567772783389002344">添加字词</translation>
 <translation id="4568213207643490790">抱歉,您不能在此设备上登录 Google 帐号。</translation>
+<translation id="4568854179928172494">修改时间</translation>
 <translation id="4569747168316751899">空闲时</translation>
 <translation id="4572659312570518089">连接到“<ph name="DEVICE_NAME" />”时取消了身份验证。</translation>
 <translation id="4572815280350369984"><ph name="FILE_TYPE" /> 文件</translation>
@@ -2330,6 +2344,7 @@
 <translation id="4640525840053037973">使用您的 Google 帐号登录</translation>
 <translation id="4641539339823703554">Chrome无法设置系统时间。请检查下面的时间,并在必要时进行更正。</translation>
 <translation id="4643612240819915418">在新标签页中打开视频(&amp;O)</translation>
+<translation id="4644818355646995778">正在下载,还差百分之 <ph name="PERCENT_REMAINING" /></translation>
 <translation id="4645676300727003670">保留(&amp;K)</translation>
 <translation id="4647090755847581616">关闭标签页(&amp;C)</translation>
 <translation id="4647697156028544508">请输入“<ph name="DEVICE_NAME" />”的 PIN:</translation>
@@ -2716,6 +2731,7 @@
 <translation id="5250372599208556903"><ph name="SEARCH_ENGINE_NAME" /> 会使用您的位置信息为您提供本地内容。您可以在<ph name="SETTINGS_LINK" />中更改此设置。</translation>
 <translation id="5252456968953390977">漫游</translation>
 <translation id="5252653240322147470">PIN 码必须少于 <ph name="MAXIMUM" /> 位数</translation>
+<translation id="5253070652067921974">创建者</translation>
 <translation id="5254368820972107711">显示将被移除的文件</translation>
 <translation id="52550593576409946">无法启动自助服务终端应用。</translation>
 <translation id="5255315797444241226">您输入的密码不正确。</translation>
@@ -2789,6 +2805,7 @@
 <translation id="5353252989841766347">从 Chrome 中导出密码</translation>
 <translation id="5355097969896547230">重新查找</translation>
 <translation id="5355926466126177564">“<ph name="EXTENSION_NAME" />”扩展程序更改了您通过多功能框进行搜索时系统显示的页面。</translation>
+<translation id="5358764674931277">帧速率</translation>
 <translation id="5360150013186312835">在工具栏中显示</translation>
 <translation id="5362741141255528695">选择私有密钥文件。</translation>
 <translation id="5363109466694494651">执行 Powerwash 操作并还原</translation>
@@ -2825,6 +2842,7 @@
 <translation id="5414566801737831689">读取您访问过的网站对应的图标</translation>
 <translation id="5417312524372586921">浏览器主题背景</translation>
 <translation id="5419294236999569767">系统时间</translation>
+<translation id="5420438158931847627">确定文字和图片的清晰度</translation>
 <translation id="5422221874247253874">接入点</translation>
 <translation id="5422781158178868512">抱歉,系统无法识别您的外部存储设备。</translation>
 <translation id="5423849171846380976">已激活</translation>
@@ -3010,6 +3028,9 @@
 <translation id="5678550637669481956">已授予对 <ph name="VOLUME_NAME" />的读写权限。</translation>
 <translation id="5678955352098267522">读取您在 <ph name="WEBSITE_1" /> 上的数据</translation>
 <translation id="5684661240348539843">资产标识符</translation>
+<translation id="5686799162999241776"><ph name="BEGIN_BOLD" />无法断开与档案或虚拟磁盘的连接<ph name="END_BOLD" />
+   <ph name="LINE_BREAKS" />
+   请关闭档案或虚拟磁盘上的所有文件,然后重试。</translation>
 <translation id="5687326903064479980">时区</translation>
 <translation id="5689516760719285838">位置</translation>
 <translation id="56907980372820799">关联数据</translation>
@@ -3018,6 +3039,7 @@
 <translation id="5694501201003948907">正在压缩$1项内容…</translation>
 <translation id="5696143504434933566">举报“<ph name="EXTENSION_NAME" />”的滥用行为</translation>
 <translation id="5699533844376998780">扩展程序“<ph name="EXTENSION_NAME" />”已添加完毕。</translation>
+<translation id="5700087501958648444">音频信息</translation>
 <translation id="570043786759263127">Google Play 应用和服务</translation>
 <translation id="5700836101007545240">“添加连接”功能已由您的管理员停用</translation>
 <translation id="5701381305118179107">居中</translation>
@@ -3574,6 +3596,7 @@
 <translation id="656398493051028875">正在删除“<ph name="FILENAME" />”…</translation>
 <translation id="6567688344210276845">无法加载网页操作的“<ph name="ICON" />”图标。</translation>
 <translation id="657402800789773160">重新加载此页(&amp;R)</translation>
+<translation id="6577284282025554716">已取消下载“<ph name="FILE_NAME" />”</translation>
 <translation id="6578664922716508575">使用您的 Google 用户名和密码加密已同步的密码</translation>
 <translation id="6580151766480067746">ARC 版本</translation>
 <translation id="6581162200855843583">Google 云端硬盘链接</translation>
@@ -4036,6 +4059,7 @@
 <translation id="7297443947353982503">用户名/密码错误或 EAP 身份验证失败</translation>
 <translation id="729761647156315797">选择语言和键盘</translation>
 <translation id="7299337219131431707">启用访客浏览</translation>
+<translation id="730289542559375723">{NUM_APPLICATIONS,plural, =1{这款应用可能会致使 Chrome 无法正常运行。}other{这些应用可能会致使 Chrome 无法正常运行。}}</translation>
 <translation id="7303900363563182677">此网站已被阻止查看复制到剪贴板的文字和图片</translation>
 <translation id="730515362922783851">与本地网络或互联网中的任何设备交换数据</translation>
 <translation id="7308002049209013926">使用启动器快速访问新的应用和活动。若要通过键盘访问这些内容,请按 Alt + Shift + L 组合键。</translation>
@@ -4282,6 +4306,7 @@
 <translation id="7707922173985738739">使用移动数据</translation>
 <translation id="7709152031285164251">失败 - <ph name="INTERRUPT_REASON" /></translation>
 <translation id="7710568461918838723">投射(&amp;C)…</translation>
+<translation id="7711920809702896782">图片信息</translation>
 <translation id="7714307061282548371">已允许来自 <ph name="DOMAIN" /> 的 Cookie</translation>
 <translation id="7714464543167945231">证书</translation>
 <translation id="7716781361494605745">Netscape 证书授权中心政策网址</translation>
@@ -4400,6 +4425,7 @@
 <translation id="7886917304091689118">正在 Chrome 中运行</translation>
 <translation id="7887334752153342268">复制</translation>
 <translation id="7887864092952184874">蓝牙鼠标已配对</translation>
+<translation id="7889565820482017512">缩放比例</translation>
 <translation id="7889966925761734854">进度</translation>
 <translation id="7892100671754994880">下一位用户</translation>
 <translation id="7893008570150657497">通过计算机访问照片、音乐和其他媒体</translation>
@@ -4503,6 +4529,7 @@
 <translation id="8026334261755873520">清除浏览数据</translation>
 <translation id="8028060951694135607">Microsoft 密钥恢复</translation>
 <translation id="8028134359912645720">按住 Ctrl、Alt、Shift 或启动器键,即可查看这些辅助键的键盘快捷键。</translation>
+<translation id="8028803902702117856">正在下载“<ph name="FILE_NAME" />”,大小为 <ph name="SIZE" /></translation>
 <translation id="8028993641010258682">大小</translation>
 <translation id="8030656706657716245">添加打印机</translation>
 <translation id="8032244173881942855">无法投射标签页。</translation>
@@ -4758,6 +4785,7 @@
 <translation id="84613761564611563">正在显示请求的网络配置界面,请稍候…</translation>
 <translation id="8461914792118322307">代理</translation>
 <translation id="8463215747450521436">此受监管用户可能已被管理员删除或停用。如果您想继续以此用户身份登录,请与管理员联系。</translation>
+<translation id="846374874681391779">下载内容栏</translation>
 <translation id="8463955938112983119">“<ph name="PLUGIN_NAME" />”已被停用。</translation>
 <translation id="8464132254133862871">此用户帐号不能使用该服务。</translation>
 <translation id="8465252176946159372">无效</translation>
@@ -4773,6 +4801,7 @@
 <translation id="8477384620836102176">基本信息(&amp;G)</translation>
 <translation id="8480082892550707549">即使您之前从该网站下载过文件,该网站也可能暂时存在安全隐患(遭到黑客入侵)。请稍后再尝试下载此文件。</translation>
 <translation id="8480869669560681089">由“<ph name="VENDOR_NAME" />”提供的未知设备</translation>
+<translation id="8481187309597259238">确认 USB 权限</translation>
 <translation id="8483248364096924578">IP 地址</translation>
 <translation id="8487678622945914333">放大</translation>
 <translation id="8487693399751278191">开始</translation>
@@ -5159,6 +5188,7 @@
 <translation id="9094033019050270033">更新密码</translation>
 <translation id="9094982973264386462">移除</translation>
 <translation id="9095253524804455615">移除</translation>
+<translation id="9099674669267916096">页数</translation>
 <translation id="9100765901046053179">高级设置</translation>
 <translation id="9101691533782776290">启动应用</translation>
 <translation id="9102610709270966160">启用扩展程序</translation>
@@ -5250,6 +5280,7 @@
 <translation id="939736085109172342">新建文件夹</translation>
 <translation id="942532530371314860"><ph name="APP_NAME" /> 正在共享 Chrome 标签页和音频。</translation>
 <translation id="942954117721265519">此目录中没有图片。</translation>
+<translation id="943972244133411984">修改者</translation>
 <translation id="945522503751344254">发送反馈</translation>
 <translation id="952992212772159698">未激活</translation>
 <translation id="957960681186851048">此网站试图自动下载多个文件</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index b9aa56d8..2797e5e 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -557,7 +557,6 @@
 <translation id="1818007989243628752">刪除 <ph name="USERNAME" /> 的密碼</translation>
 <translation id="1819721979226826163">依序輕觸 [應用程式通知] &gt; [Google Play 服務]。</translation>
 <translation id="1826516787628120939">檢查中</translation>
-<translation id="1828149253358786390"><ph name="SITE" /> 要求傳送通知給您。</translation>
 <translation id="1828378091493947763">這部裝置不支援這個外掛程式</translation>
 <translation id="1828901632669367785">使用系統對話方塊進行列印...</translation>
 <translation id="1829192082282182671">縮小(&amp;O)</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 1310594..ad45700 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3078,7 +3078,7 @@
     }
   }
 
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     deps += [ "//chrome/app:shutdown_signal_handlers" ]
   }
 
@@ -3169,7 +3169,7 @@
     ]
   }
 
-  if (is_posix && !is_mac && !is_fuchsia) {
+  if (is_posix && !is_mac) {
     # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
     sources += [
       "//chrome/app/chrome_crash_reporter_client.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1a9351b0..95f7fc0e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -210,6 +210,14 @@
      switches::kOverscrollStartThreshold, "166"},
     {flag_descriptions::kOverscrollStartThreshold200Percent,
      switches::kOverscrollStartThreshold, "200"}};
+
+const FeatureEntry::Choice kPullToRefreshChoices[] = {
+    {flags_ui::kGenericExperimentChoiceDefault, "", ""},
+    {flags_ui::kGenericExperimentChoiceDisabled, switches::kPullToRefresh, "0"},
+    {flags_ui::kGenericExperimentChoiceEnabled, switches::kPullToRefresh, "1"},
+    {flag_descriptions::kPullToRefreshEnabledTouchscreen,
+     switches::kPullToRefresh, "2"}};
+
 #endif  // USE_AURA
 
 const FeatureEntry::Choice kTouchTextSelectionStrategyChoices[] = {
@@ -1660,10 +1668,7 @@
      MULTI_VALUE_TYPE(kOverscrollStartThresholdChoices)},
     {"pull-to-refresh", flag_descriptions::kPullToRefreshName,
      flag_descriptions::kPullToRefreshDescription, kOsAura,
-     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(switches::kPullToRefresh,
-                                         "1",
-                                         switches::kPullToRefresh,
-                                         "0")},
+     MULTI_VALUE_TYPE(kPullToRefreshChoices)},
 #endif  // USE_AURA
     {"enable-touch-drag-drop", flag_descriptions::kTouchDragDropName,
      flag_descriptions::kTouchDragDropDescription, kOsWin | kOsCrOS,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index d38d18a..942907e 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -75,7 +75,6 @@
     &kChromeHomeMenuItemsExpandSheet,
     &kChromeHomePersistentIph,
     &kChromeHomePullToRefreshIphAtTop,
-    &kChromeHomeSurvey,
     &kChromeHomeSwipeLogic,
     &kChromeHomeSwipeLogicVelocity,
     &kChromeSmartSelection,
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
index 6bff37a5..495b2be 100644
--- a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
+++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
@@ -43,8 +43,7 @@
           ContextualContentSuggestionsServiceFactory::GetForProfile(profile);
 
   std::unique_ptr<ContextualContentSuggestionsServiceProxy> service_proxy =
-      std::make_unique<ContextualContentSuggestionsServiceProxy>(
-          contextual_suggestions_service);
+      contextual_suggestions_service->CreateProxy();
 
   ContextualSuggestionsBridge* contextual_suggestions_bridge =
       new ContextualSuggestionsBridge(env, std::move(service_proxy));
@@ -77,6 +76,7 @@
 
 void ContextualSuggestionsBridge::Destroy(JNIEnv* env,
                                           const JavaParamRef<jobject>& obj) {
+  service_proxy_->FlushMetrics();
   delete this;
 }
 
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index ea855348..5b82798 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -1847,6 +1847,33 @@
   ExpectFieldValue("phone_form1", "");
 }
 
+// Test that we can Autofill forms where some fields name change during the
+// fill.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, FieldsChangeName) {
+  CreateTestProfile();
+
+  GURL url = embedded_test_server()->GetURL(
+      "/autofill/field_changing_name_during_fill.html");
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
+
+  TriggerFormFill("firstname");
+
+  // Wait for the fill to happen.
+  bool has_filled = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(GetRenderViewHost(),
+                                                   "hasFilled()", &has_filled));
+  ASSERT_TRUE(has_filled);
+
+  // Make sure the form was filled correctly.
+  ExpectFieldValue("firstname", "Milton");
+  ExpectFieldValue("address", "4120 Freidrich Lane");
+  ExpectFieldValue("state", "TX");
+  ExpectFieldValue("city", "Austin");
+  ExpectFieldValue("company", "Initech");
+  ExpectFieldValue("email", "red.swingline@initech.com");
+  ExpectFieldValue("phone", "15125551234");
+}
+
 // An extension of the test fixture for tests with site isolation.
 class AutofillInteractiveIsolationTest : public AutofillInteractiveTest {
  protected:
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index 2440c13..87aca6df5 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -282,12 +282,21 @@
   const bool kIsTopFrame = true;
   const uint64_t kPlayerId = 1234u;
 
+  media::mojom::PredictionFeatures prediction_features;
+  prediction_features.profile = kProfile;
+  prediction_features.video_size = kSize;
+  prediction_features.frames_per_sec = kFrameRate;
+
+  media::mojom::PredictionTargets prediction_targets;
+  prediction_targets.frames_decoded = kFramesDecoded;
+  prediction_targets.frames_dropped = kFramesDropped;
+  prediction_targets.frames_decoded_power_efficient = kFramesPowerEfficient;
+
   {
     base::RunLoop run_loop;
     video_decode_perf_history->SavePerfRecord(
-        kOrigin, kIsTopFrame, kProfile, kSize, kFrameRate, kFramesDecoded,
-        kFramesDropped, kFramesPowerEfficient, kPlayerId,
-        run_loop.QuitWhenIdleClosure());
+        kOrigin, kIsTopFrame, prediction_features, prediction_targets,
+        kPlayerId, run_loop.QuitWhenIdleClosure());
     run_loop.Run();
   }
 
@@ -299,7 +308,7 @@
   {
     base::RunLoop run_loop;
     video_decode_perf_history->GetPerfInfo(
-        kProfile, kSize, kFrameRate,
+        media::mojom::PredictionFeatures::New(prediction_features),
         base::BindOnce(&BrowsingDataRemoverBrowserTest::OnVideoDecodePerfInfo,
                        base::Unretained(this), &run_loop, &is_smooth,
                        &is_power_efficient));
@@ -317,7 +326,7 @@
   {
     base::RunLoop run_loop;
     video_decode_perf_history->GetPerfInfo(
-        kProfile, kSize, kFrameRate,
+        media::mojom::PredictionFeatures::New(prediction_features),
         base::BindOnce(&BrowsingDataRemoverBrowserTest::OnVideoDecodePerfInfo,
                        base::Unretained(this), &run_loop, &is_smooth,
                        &is_power_efficient));
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 8d73eaa3..2d3cc19 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -2124,7 +2124,7 @@
   for (size_t i = 0; i < host_settings.size(); ++i) {
     EXPECT_EQ(ContentSettingsPattern::Wildcard(),
               host_settings.at(i).secondary_pattern);
-    EXPECT_EQ(*expiration_times_dictionary, *host_settings.at(i).setting_value);
+    EXPECT_EQ(*expiration_times_dictionary, host_settings.at(i).setting_value);
   }
 }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 829ee63d..910cd29 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -760,20 +760,24 @@
     RendererContentSettingRules* rules) {
   rules->image_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), incognito));
 
   rules->script_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), incognito));
   rules->autoplay_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), incognito));
   rules->client_hints_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), incognito));
 }
 
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
index d150742e..436dced 100644
--- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -5,7 +5,7 @@
 #include <queue>
 
 #include "ash/accelerators/accelerator_controller.h"
-#include "ash/accelerators/accelerator_table.h"
+#include "ash/public/cpp/accelerators.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
 #include "base/command_line.h"
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
index b210bf23..56873d3 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -378,14 +378,6 @@
   return true;
 }
 
-ScreenlockState EasyUnlockService::GetScreenlockState() {
-  EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
-  if (!handler)
-    return ScreenlockState::INACTIVE;
-
-  return handler->state();
-}
-
 void EasyUnlockService::AttemptAuth(const AccountId& account_id) {
   const EasyUnlockAuthAttempt::Type auth_attempt_type =
       GetType() == TYPE_REGULAR ? EasyUnlockAuthAttempt::TYPE_UNLOCK
@@ -526,12 +518,6 @@
   weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
-void EasyUnlockService::ReloadAppAndLockScreen() {
-  // Make sure lock screen state set by the extension gets reset.
-  ResetScreenlockState();
-  app_manager_->ReloadApp();
-}
-
 void EasyUnlockService::UpdateAppState() {
   if (IsAllowed()) {
     EnsureTpmKeyPresentIfNeeded();
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
index 1f524e35..4a3a19f7 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
@@ -26,7 +26,6 @@
 class AccountId;
 
 namespace base {
-class DictionaryValue;
 class ListValue;
 }  // namespace base
 
@@ -93,8 +92,6 @@
   virtual void LaunchSetup() = 0;
 
   // Gets/Sets/Clears the permit access for the local device.
-  virtual const base::DictionaryValue* GetPermitAccess() const = 0;
-  virtual void SetPermitAccess(const base::DictionaryValue& permit) = 0;
   virtual void ClearPermitAccess() = 0;
 
   // Gets/Sets the remote devices list.
@@ -159,10 +156,6 @@
   // the service to reflect the provided screenlock state.
   bool UpdateScreenlockState(proximity_auth::ScreenlockState state);
 
-  // Returns the screenlock state if it is available. Otherwise STATE_INACTIVE
-  // is returned.
-  proximity_auth::ScreenlockState GetScreenlockState();
-
   // Starts an auth attempt for the user associated with the service. The
   // attempt type (unlock vs. signin) will depend on the service type.
   void AttemptAuth(const AccountId& account_id);
@@ -238,10 +231,6 @@
   // Opens an Easy Unlock Setup app window.
   void OpenSetupApp();
 
-  // Reloads the Easy unlock component app if it's loaded and resets the lock
-  // screen state.
-  void ReloadAppAndLockScreen();
-
   // Checks whether Easy unlock should be running and updates app state.
   void UpdateAppState();
 
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
index 70e4b71..0052e5ab 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
@@ -299,24 +299,6 @@
   CheckCryptohomeKeysAndMaybeHardlock();
 }
 
-const base::DictionaryValue* EasyUnlockServiceRegular::GetPermitAccess() const {
-  const base::DictionaryValue* pairing_dict =
-      profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
-  const base::DictionaryValue* permit_dict = NULL;
-  if (pairing_dict &&
-      pairing_dict->GetDictionary(kKeyPermitAccess, &permit_dict))
-    return permit_dict;
-
-  return NULL;
-}
-
-void EasyUnlockServiceRegular::SetPermitAccess(
-    const base::DictionaryValue& permit) {
-  DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
-                                      prefs::kEasyUnlockPairing);
-  pairing_update->SetKey(kKeyPermitAccess, permit.Clone());
-}
-
 void EasyUnlockServiceRegular::ClearPermitAccess() {
   DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
                                       prefs::kEasyUnlockPairing);
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h
index b5774e9..4521ca8 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h
@@ -20,7 +20,6 @@
 #include "components/prefs/pref_change_registrar.h"
 
 namespace base {
-class DictionaryValue;
 class ListValue;
 }  // namespace base
 
@@ -82,8 +81,6 @@
   EasyUnlockService::Type GetType() const override;
   AccountId GetAccountId() const override;
   void LaunchSetup() override;
-  const base::DictionaryValue* GetPermitAccess() const override;
-  void SetPermitAccess(const base::DictionaryValue& permit) override;
   void ClearPermitAccess() override;
   const base::ListValue* GetRemoteDevices() const override;
   void SetRemoteDevices(const base::ListValue& devices) override;
@@ -139,10 +136,6 @@
 
   std::unique_ptr<ShortLivedUserContext> short_lived_user_context_;
 
-  // Updates local state with the preference from the user's profile, so they
-  // can be accessed on the sign-in screen.
-  void SyncProfilePrefsToLocalState();
-
   // Returns the CryptAuthEnrollmentManager, which manages the profile's
   // CryptAuth enrollment.
   cryptauth::CryptAuthEnrollmentManager* GetCryptAuthEnrollmentManager();
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
index 795d2fc..1562de8 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
@@ -169,10 +169,6 @@
 
 EasyUnlockServiceSignin::~EasyUnlockServiceSignin() {}
 
-void EasyUnlockServiceSignin::SetCurrentUser(const AccountId& account_id) {
-  OnFocusedUserChanged(account_id);
-}
-
 void EasyUnlockServiceSignin::WrapChallengeForUserAndDevice(
     const AccountId& account_id,
     const std::string& device_public_key,
@@ -223,15 +219,6 @@
   NOTREACHED();
 }
 
-const base::DictionaryValue* EasyUnlockServiceSignin::GetPermitAccess() const {
-  return nullptr;
-}
-
-void EasyUnlockServiceSignin::SetPermitAccess(
-    const base::DictionaryValue& permit) {
-  NOTREACHED();
-}
-
 void EasyUnlockServiceSignin::ClearPermitAccess() {
   NOTREACHED();
 }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.h
index 373d216..c6505d6 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.h
@@ -35,10 +35,6 @@
   explicit EasyUnlockServiceSignin(Profile* profile);
   ~EasyUnlockServiceSignin() override;
 
-  // Sets |account_id| as the current user of the service. Note this does
-  // not change the focused user on the login screen.
-  void SetCurrentUser(const AccountId& account_id);
-
   // Wraps the challenge for the remote device identified by |account_id| and
   // the
   // |device_public_key|. The |channel_binding_data| is signed by the TPM
@@ -87,8 +83,6 @@
   EasyUnlockService::Type GetType() const override;
   AccountId GetAccountId() const override;
   void LaunchSetup() override;
-  const base::DictionaryValue* GetPermitAccess() const override;
-  void SetPermitAccess(const base::DictionaryValue& permit) override;
   void ClearPermitAccess() override;
   const base::ListValue* GetRemoteDevices() const override;
   void SetRemoteDevices(const base::ListValue& devices) override;
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index e77883b..a7a9ba9 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -221,6 +221,14 @@
 }
 
 void OobeBaseTest::WaitForGaiaPageReload() {
+  WaitForGaiaPageEvent("ready");
+}
+
+void OobeBaseTest::WaitForGaiaPageBackButtonUpdate() {
+  WaitForGaiaPageEvent("backButton");
+}
+
+void OobeBaseTest::WaitForGaiaPageEvent(const std::string& event) {
   // Starts listening to message before executing the JS code that generates
   // the message below.
   content::DOMMessageQueue message_queue;
@@ -229,16 +237,16 @@
       "(function() {"
       "  var authenticator = $('gaia-signin').gaiaAuthHost_;"
       "  var f = function() {"
-      "    authenticator.removeEventListener('ready', f);"
-      "    window.domAutomationController.send('GaiaReady');"
+      "    authenticator.removeEventListener('" + event + "', f);"
+      "    window.domAutomationController.send('Done');"
       "  };"
-      "  authenticator.addEventListener('ready', f);"
+      "  authenticator.addEventListener('" + event + "', f);"
       "})();");
 
   std::string message;
   do {
     ASSERT_TRUE(message_queue.WaitForMessage(&message));
-  } while (message != "\"GaiaReady\"");
+  } while (message != "\"Done\"");
 }
 
 void OobeBaseTest::WaitForSigninScreen() {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h
index f4f142a..1255ec0 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.h
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -92,6 +92,8 @@
 
   void WaitForGaiaPageLoad();
   void WaitForGaiaPageReload();
+  void WaitForGaiaPageBackButtonUpdate();
+  void WaitForGaiaPageEvent(const std::string& event);
   void WaitForSigninScreen();
   void ExecuteJsInSigninFrame(const std::string& js);
   void SetSignFormField(const std::string& field_id,
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index b8f470bd..94774d2 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -233,6 +233,7 @@
 
   SetSignFormField("identifier", OobeBaseTest::kFakeUserEmail);
   ClickNext();
+  WaitForGaiaPageBackButtonUpdate();
   ExpectPasswordPage();
 
   content::WindowedNotificationObserver session_start_waiter(
@@ -255,14 +256,17 @@
   // Move to password page.
   SetSignFormField("identifier", OobeBaseTest::kFakeUserEmail);
   ClickNext();
+  WaitForGaiaPageBackButtonUpdate();
   ExpectPasswordPage();
 
   // Click back to identifier page.
   JS().Evaluate("$('gaia-navigation').$.backButton.click();");
+  WaitForGaiaPageBackButtonUpdate();
   ExpectIdentifierPage();
 
   // Click next to password page, user id is remembered.
   ClickNext();
+  WaitForGaiaPageBackButtonUpdate();
   ExpectPasswordPage();
 
   content::WindowedNotificationObserver session_start_waiter(
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index c51abe55..bda60b5 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -438,7 +438,7 @@
       GURL("https://foo.com/"), GURL(), CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
       std::string(),
       std::make_unique<base::Value>(
-          client_hints_settings.at(0).setting_value->Clone()));
+          client_hints_settings.at(0).setting_value.Clone()));
 
   // Verify that client hints for the two hosts has been saved.
   host_content_settings_map =
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
index 5f96123..88b3522 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -323,7 +323,7 @@
     EXPECT_EQ(ContentSettingsPattern::Wildcard(),
               client_hints_settings.at(i).secondary_pattern);
     EXPECT_EQ(*expiration_times_dictionary,
-              *client_hints_settings.at(i).setting_value);
+              client_hints_settings.at(i).setting_value);
   }
 
   // Add setting for hosts[1].
@@ -342,7 +342,7 @@
     EXPECT_EQ(ContentSettingsPattern::Wildcard(),
               client_hints_settings.at(i).secondary_pattern);
     EXPECT_EQ(*expiration_times_dictionary,
-              *client_hints_settings.at(i).setting_value);
+              client_hints_settings.at(i).setting_value);
   }
 
   // Add settings again for hosts[0].
@@ -361,7 +361,7 @@
     EXPECT_EQ(ContentSettingsPattern::Wildcard(),
               client_hints_settings.at(i).secondary_pattern);
     EXPECT_EQ(*expiration_times_dictionary,
-              *client_hints_settings.at(i).setting_value);
+              client_hints_settings.at(i).setting_value);
   }
 }
 
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc
index 3177718..d8f0b19 100644
--- a/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/api/commands/commands.h"
 #include "chrome/browser/extensions/extension_commands_global_registry.h"
 #include "chrome/browser/extensions/extension_keybinding_registry.h"
@@ -428,8 +427,7 @@
   return RemovesBookmarkShortcut(extension) &&
          GetSuggestedExtensionCommand(
              extension->id(),
-             chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE),
-             nullptr);
+             chrome::GetPrimaryChromeAcceleratorForBookmarkPage(), nullptr);
 }
 
 void CommandService::AddObserver(Observer* observer) {
@@ -583,7 +581,7 @@
     // Not a global command, check if Chrome shortcut and whether
     // we can override it.
     if (command.accelerator() ==
-        chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE) &&
+            chrome::GetPrimaryChromeAcceleratorForBookmarkPage() &&
         CommandService::RemovesBookmarkShortcut(extension)) {
       // If this check fails it either means we have an API to override a
       // key that isn't a ChromeAccelerator (and the API can therefore be
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 6b90a7ae..6692d07a 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
@@ -447,26 +447,6 @@
   Respond(NoArguments());
 }
 
-EasyUnlockPrivateSetPermitAccessFunction::
-    EasyUnlockPrivateSetPermitAccessFunction() {
-}
-
-EasyUnlockPrivateSetPermitAccessFunction::
-    ~EasyUnlockPrivateSetPermitAccessFunction() {
-}
-
-ExtensionFunction::ResponseAction
-EasyUnlockPrivateSetPermitAccessFunction::Run() {
-  std::unique_ptr<easy_unlock_private::SetPermitAccess::Params> params(
-      easy_unlock_private::SetPermitAccess::Params::Create(*args_));
-  EXTENSION_FUNCTION_VALIDATE(params.get());
-
-  Profile* profile = Profile::FromBrowserContext(browser_context());
-  chromeos::EasyUnlockService::Get(profile)->SetPermitAccess(
-      *params->permit_access.ToValue());
-  return RespondNow(NoArguments());
-}
-
 EasyUnlockPrivateGetPermitAccessFunction::
     EasyUnlockPrivateGetPermitAccessFunction() {
 }
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
index d9348a6..f0f04d2 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
@@ -170,22 +170,6 @@
   DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateUnwrapSecureMessageFunction);
 };
 
-class EasyUnlockPrivateSetPermitAccessFunction
-    : public UIThreadExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.setPermitAccess",
-                             EASYUNLOCKPRIVATE_SETPERMITACCESS)
-  EasyUnlockPrivateSetPermitAccessFunction();
-
- private:
-  ~EasyUnlockPrivateSetPermitAccessFunction() override;
-
-  // ExtensionFunction:
-  ResponseAction Run() override;
-
-  DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateSetPermitAccessFunction);
-};
-
 class EasyUnlockPrivateGetPermitAccessFunction
     : public UIThreadExtensionFunction {
  public:
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
index 00ec29ba..d80d473 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -355,16 +355,11 @@
 bool ChromeContentBrowserClientExtensionsPart::ShouldUseSpareRenderProcessHost(
     Profile* profile,
     const GURL& site_url) {
-  const Extension* extension =
-      GetEnabledExtensionFromEffectiveURL(profile, site_url);
-  if (!extension)
-    return true;
-
   // Extensions should not use a spare process, because they require passing a
   // command-line flag (switches::kExtensionProcess) to the renderer process
   // when it launches. A spare process is launched earlier, before it is known
   // which navigation will use it, so it lacks this flag.
-  return false;
+  return !site_url.SchemeIs(kExtensionScheme);
 }
 
 // static
diff --git a/chrome/browser/extensions/test_extension_environment.h b/chrome/browser/extensions/test_extension_environment.h
index 7d2083bc..87518f65 100644
--- a/chrome/browser/extensions/test_extension_environment.h
+++ b/chrome/browser/extensions/test_extension_environment.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "extensions/common/extension.h"
 
 #if defined(OS_WIN)
@@ -25,8 +26,8 @@
 }
 
 namespace content {
-class WebContents;
 class TestBrowserThreadBundle;
+class WebContents;
 }
 
 namespace extensions {
@@ -96,7 +97,10 @@
 
   void Init();
 
+  // If |thread_bundle_| is needed, then it needs to constructed before
+  // |profile_| and destroyed after |profile_|.
   const std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
+
 #if defined(OS_CHROMEOS)
   const std::unique_ptr<ChromeOSEnv> chromeos_env_;
 #endif
@@ -104,6 +108,15 @@
 #if defined(OS_WIN)
   ui::ScopedOleInitializer ole_initializer_;
 #endif
+
+  // This makes sure that creating a renderer during a test will created a
+  // MockRenderProcessHost instead of a RenderProcessHostImpl.  It is important
+  // that the factory is created and registered before |profile_| and destroyed
+  // after |profile_|.
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory process_factory_;
+
   std::unique_ptr<TestingProfile> profile_;
   ExtensionService* extension_service_ = nullptr;
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a347569..c80b494 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1216,6 +1216,7 @@
 const char kPullToRefreshName[] = "Pull-to-refresh gesture";
 const char kPullToRefreshDescription[] =
     "Pull-to-refresh gesture in response to vertical overscroll.";
+const char kPullToRefreshEnabledTouchscreen[] = "Enabled for touchscreen only";
 
 const char kPushApiBackgroundModeName[] = "Enable Push API background mode";
 const char kPushApiBackgroundModeDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 6fc40e11..0744b0f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -764,6 +764,7 @@
 
 extern const char kPullToRefreshName[];
 extern const char kPullToRefreshDescription[];
+extern const char kPullToRefreshEnabledTouchscreen[];
 
 extern const char kPushApiBackgroundModeName[];
 extern const char kPushApiBackgroundModeDescription[];
diff --git a/chrome/browser/media/media_engagement_service.cc b/chrome/browser/media/media_engagement_service.cc
index 7a12111..7899e6eb 100644
--- a/chrome/browser/media/media_engagement_service.cc
+++ b/chrome/browser/media/media_engagement_service.cc
@@ -396,7 +396,7 @@
     auto* const site = it.second;
 
     std::unique_ptr<base::Value> clone =
-        std::make_unique<base::Value>(site->setting_value->Clone());
+        base::Value::ToUniquePtrValue(site->setting_value.Clone());
 
     data.push_back(MediaEngagementScore(
         clock_, origin, base::DictionaryValue::From(std::move(clone)),
diff --git a/chrome/browser/media/router/media_router_feature.cc b/chrome/browser/media/router/media_router_feature.cc
index 9898488..ced5c11 100644
--- a/chrome/browser/media/router/media_router_feature.cc
+++ b/chrome/browser/media/router/media_router_feature.cc
@@ -37,7 +37,7 @@
 
 // Controls if local media casting is enabled.
 const base::Feature kEnableCastLocalMedia{"EnableCastLocalMedia",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 #if defined(OS_ANDROID) || BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
index 605745c..a53a42e1 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -208,6 +208,21 @@
       content::SiteInstance* site_instance) const override;
 
  private:
+  class SharedMockRenderProcessHost : public content::MockRenderProcessHost {
+   public:
+    explicit SharedMockRenderProcessHost(
+        content::BrowserContext* browser_context)
+        : content::MockRenderProcessHost(browser_context) {}
+
+    // This test class lies that the process has not been used to allow
+    // testing of process sharing/reuse inherent in the unit tests that depend
+    // on the MockProfileSharedRenderProcessHostFactory.
+    bool HostHasNotBeenUsed() override { return true; }
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(SharedMockRenderProcessHost);
+  };
+
   mutable std::map<content::BrowserContext*,
                    std::unique_ptr<content::MockRenderProcessHost>>
       rph_map_;
@@ -425,7 +440,7 @@
   if (existing != rph_map_.end())
     return existing->second.get();
   rph_map_[browser_context] =
-      std::make_unique<content::MockRenderProcessHost>(browser_context);
+      std::make_unique<SharedMockRenderProcessHost>(browser_context);
   return rph_map_[browser_context].get();
 }
 
diff --git a/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc
index 2cebea3..10e77de 100644
--- a/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc
@@ -108,12 +108,13 @@
               std::make_unique<suggestions::ImageDecoderImpl>(),
               request_context.get()),
           pref_service, contextual_suggestions_database.get());
-  auto metrics_reporter = std::make_unique<
-      contextual_suggestions::ContextualSuggestionsMetricsReporter>();
+  auto metrics_reporter_provider = std::make_unique<
+      contextual_suggestions::ContextualSuggestionsMetricsReporterProvider>();
   auto* service = new ContextualContentSuggestionsService(
       std::move(contextual_suggestions_fetcher),
       std::move(cached_image_fetcher),
-      std::move(contextual_suggestions_database), std::move(metrics_reporter));
+      std::move(contextual_suggestions_database),
+      std::move(metrics_reporter_provider));
 
   return service;
 }
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 59772b0b..50639a90 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -39,6 +39,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/download/public/common/download_item.h"
+#include "components/viz/common/features.h"
 #include "components/zoom/page_zoom.h"
 #include "components/zoom/test/zoom_test_utils.h"
 #include "components/zoom/zoom_controller.h"
@@ -104,8 +105,7 @@
   return false;
 }
 
-class PDFExtensionTest : public ExtensionApiTest,
-                         public testing::WithParamInterface<int> {
+class PDFExtensionTest : public ExtensionApiTest {
  public:
   ~PDFExtensionTest() override {}
 
@@ -349,6 +349,28 @@
   }
 };
 
+class PDFExtensionLoadTest : public PDFExtensionTest,
+                             public testing::WithParamInterface<int> {
+ public:
+  PDFExtensionLoadTest() {}
+};
+
+class PDFExtensionHitTestTest : public PDFExtensionTest,
+                                public testing::WithParamInterface<bool> {
+ public:
+  PDFExtensionHitTestTest() {}
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    PDFExtensionTest::SetUpCommandLine(command_line);
+    if (GetParam()) {
+      feature_list_.InitAndEnableFeature(features::kEnableVizHitTestDrawQuad);
+    }
+  }
+
+  base::test::ScopedFeatureList feature_list_;
+};
+
 // Disabled because it's flaky.
 // See the issue for details: https://crbug.com/826055.
 #if defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
@@ -357,7 +379,7 @@
 #else
 #define MAYBE_Load Load
 #endif
-IN_PROC_BROWSER_TEST_P(PDFExtensionTest, MAYBE_Load) {
+IN_PROC_BROWSER_TEST_P(PDFExtensionLoadTest, MAYBE_Load) {
 #if defined(GOOGLE_CHROME_BUILD)
   // Load private PDFs.
   LoadAllPdfsTest("pdf_private", GetParam());
@@ -424,11 +446,15 @@
   downloads[0]->Cancel(false);
 }
 
-// We break PDFTest.Load up into kNumberLoadTestParts.
+// We break PDFExtensionLoadTest up into kNumberLoadTestParts.
 INSTANTIATE_TEST_CASE_P(PDFTestFiles,
-                        PDFExtensionTest,
+                        PDFExtensionLoadTest,
                         testing::Range(0, kNumberLoadTestParts));
 
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        PDFExtensionHitTestTest,
+                        testing::Bool());
+
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Basic) {
   RunTestsInFile("basic_test.js", "test.pdf");
 
@@ -1606,7 +1632,7 @@
 
 #endif  // defined(OS_MACOSX)
 
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, ContextMenuCoordinates) {
+IN_PROC_BROWSER_TEST_P(PDFExtensionHitTestTest, ContextMenuCoordinates) {
   GURL url = embedded_test_server()->GetURL("/pdf/pdf_embed.html");
 
   // Load page with embedded PDF and make sure it succeeds.
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index e4334b5..c507ddc1 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -695,9 +695,16 @@
   for (content::RenderProcessHost::iterator iter(
            content::RenderProcessHost::AllHostsIterator());
        !iter.IsAtEnd(); iter.Advance()) {
-    ++host_count;
+    // Don't count spare RenderProcessHosts.
+    if (!iter.GetCurrentValue()->HostHasNotBeenUsed())
+      ++host_count;
+
+    content::RenderProcessHostWatcher process_exit_observer(
+        iter.GetCurrentValue(),
+        content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
     // TODO(wez): This used to use wait=true.
     iter.GetCurrentValue()->Shutdown(content::RESULT_CODE_KILLED);
+    process_exit_observer.Wait();
   }
   // There should be at most one render_process_host, that created for the SW.
   EXPECT_EQ(1, host_count);
diff --git a/chrome/browser/profiles/profile_destroyer.cc b/chrome/browser/profiles/profile_destroyer.cc
index 371d48fd..52406861 100644
--- a/chrome/browser/profiles/profile_destroyer.cc
+++ b/chrome/browser/profiles/profile_destroyer.cc
@@ -62,8 +62,8 @@
   if (profile_is_off_the_record) {
     DCHECK(!profile_has_off_the_record);
     if (profile_hosts_count) {
-      // The instance will destroy itself once all render process hosts
-      // referring to it are properly terminated.
+      // The instance will destroy itself once all (non-spare) render process
+      // hosts referring to it are properly terminated.
       new ProfileDestroyer(profile, &profile_hosts);
     } else {
       profile->GetOriginalProfile()->DestroyOffTheRecordProfile();
@@ -207,10 +207,16 @@
         content::RenderProcessHost::AllHostsIterator());
       !iter.IsAtEnd(); iter.Advance()) {
     content::RenderProcessHost* render_process_host = iter.GetCurrentValue();
-    if (render_process_host &&
-            render_process_host->GetBrowserContext() == profile) {
-      hosts.insert(render_process_host);
-    }
+    DCHECK(render_process_host);
+
+    if (render_process_host->GetBrowserContext() != profile)
+      continue;
+
+    // Ignore the spare RenderProcessHost.
+    if (render_process_host->HostHasNotBeenUsed())
+      continue;
+
+    hosts.insert(render_process_host);
   }
   return hosts;
 }
diff --git a/chrome/browser/profiling_host/background_profiling_triggers.cc b/chrome/browser/profiling_host/background_profiling_triggers.cc
index 60f1a01f..4a25206 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers.cc
@@ -82,20 +82,7 @@
 }
 
 bool BackgroundProfilingTriggers::IsAllowedToUpload() const {
-  if (!ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled()) {
-    return false;
-  }
-
-  // Do not upload if there is an incognito session running in any profile.
-  std::vector<Profile*> profiles =
-      g_browser_process->profile_manager()->GetLoadedProfiles();
-  for (Profile* profile : profiles) {
-    if (profile->HasOffTheRecordProfile()) {
-      return false;
-    }
-  }
-
-  return true;
+  return ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 }
 
 bool BackgroundProfilingTriggers::IsOverTriggerThreshold(
diff --git a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
index 486505c..db2f925 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
@@ -223,51 +223,4 @@
   EXPECT_FALSE(triggers_.IsAllowedToUpload());
 }
 
-// Ensure IsAllowedToUpload() respects incognito sessions. Checke that behavior
-//   * respsects incognito sessions in primary profile.
-//   * respsects incognito sessions in non-primary profiles.
-//   * handles overlapping incognito sessions.
-//
-// NOTE: As of this test writing, TestingProfile::DestroyOffTheRecordProfile()
-// is mocked out to do nothing. Currently, using
-// TestingProfile::SetOffTheRecordProfile(nullptr) to fake destruction.
-TEST_F(BackgroundProfilingTriggersTest, IsAllowedToUpload_Incognito) {
-  // Create 2 profiles. The first is considered the primary.
-  TestingProfile* primary_profile =
-      testing_profile_manager_.CreateTestingProfile("primary");
-  TestingProfile* secondary_profile =
-      testing_profile_manager_.CreateTestingProfile("secondary");
-  ASSERT_FALSE(primary_profile->HasOffTheRecordProfile());
-
-  // Test IsAllowedToUpload() maps to incognito session in primary profile.
-  EXPECT_TRUE(triggers_.IsAllowedToUpload());
-
-  primary_profile->GetOffTheRecordProfile();
-  EXPECT_FALSE(triggers_.IsAllowedToUpload());
-
-  primary_profile->SetOffTheRecordProfile(nullptr);
-  EXPECT_TRUE(triggers_.IsAllowedToUpload());
-
-  // Test IsAllowedToUpload() maps to incognito session in secondary profile.
-  secondary_profile->GetOffTheRecordProfile();
-  EXPECT_FALSE(triggers_.IsAllowedToUpload());
-  secondary_profile->SetOffTheRecordProfile(nullptr);
-  EXPECT_TRUE(triggers_.IsAllowedToUpload());
-
-  // Test overlapping incognitos sessions.
-  primary_profile->GetOffTheRecordProfile();
-  secondary_profile->GetOffTheRecordProfile();
-  EXPECT_FALSE(triggers_.IsAllowedToUpload());
-
-  secondary_profile->SetOffTheRecordProfile(nullptr);
-  EXPECT_FALSE(triggers_.IsAllowedToUpload());
-
-  secondary_profile->GetOffTheRecordProfile();
-  primary_profile->SetOffTheRecordProfile(nullptr);
-  EXPECT_FALSE(triggers_.IsAllowedToUpload());
-
-  secondary_profile->SetOffTheRecordProfile(nullptr);
-  EXPECT_TRUE(triggers_.IsAllowedToUpload());
-}
-
 }  // namespace heap_profiling
diff --git a/chrome/browser/profiling_host/profiling_test_driver.cc b/chrome/browser/profiling_host/profiling_test_driver.cc
index f08e43c88..0ba0fe1 100644
--- a/chrome/browser/profiling_host/profiling_test_driver.cc
+++ b/chrome/browser/profiling_host/profiling_test_driver.cc
@@ -79,7 +79,9 @@
 }
 
 // On success, populates |pid|.
-int NumProcessesWithName(base::Value* dump_json, std::string name, int* pid) {
+int NumProcessesWithName(base::Value* dump_json,
+                         std::string name,
+                         std::vector<int>* pids) {
   int num_processes = 0;
   base::Value* events = dump_json->FindKey("traceEvents");
   for (const base::Value& event : events->GetList()) {
@@ -100,14 +102,14 @@
     if (found_process_name->GetString() != name)
       continue;
 
-    if (pid) {
+    if (pids) {
       const base::Value* found_pid =
           event.FindKeyOfType("pid", base::Value::Type::INTEGER);
       if (!found_pid) {
         LOG(ERROR) << "Process missing pid.";
         return 0;
       }
-      *pid = found_pid->GetInt();
+      pids->push_back(found_pid->GetInt());
     }
 
     ++num_processes;
@@ -840,49 +842,51 @@
 }
 
 bool ProfilingTestDriver::ValidateRendererAllocations(base::Value* dump_json) {
-  int pid;
-  bool result = NumProcessesWithName(dump_json, "Renderer", &pid) == 1;
+  std::vector<int> pids;
+  bool result = NumProcessesWithName(dump_json, "Renderer", &pids) >= 1;
   if (!result) {
     LOG(ERROR) << "Failed to find process with name Renderer";
     return false;
   }
 
-  base::ProcessId renderer_pid = static_cast<base::ProcessId>(pid);
-  base::Value* heaps_v2 = FindArgDump(renderer_pid, dump_json, "heaps_v2");
-  if (ShouldProfileRenderer()) {
-    if (!heaps_v2) {
-      LOG(ERROR) << "Failed to find heaps v2 for renderer";
-      return false;
+  for (int pid : pids) {
+    base::ProcessId renderer_pid = static_cast<base::ProcessId>(pid);
+    base::Value* heaps_v2 = FindArgDump(renderer_pid, dump_json, "heaps_v2");
+    if (ShouldProfileRenderer()) {
+      if (!heaps_v2) {
+        LOG(ERROR) << "Failed to find heaps v2 for renderer";
+        return false;
+      }
+
+      base::Value* process_mmaps =
+          FindArgDump(renderer_pid, dump_json, "process_mmaps");
+      if (!ValidateProcessMmaps(process_mmaps, HasNativeFrames())) {
+        LOG(ERROR) << "Failed to validate renderer process mmaps.";
+        return false;
+      }
+
+      // ValidateDump doesn't always succeed for the renderer, since we don't do
+      // anything to flush allocations, there are very few allocations recorded
+      // by the heap profiler. When we do a heap dump, we prune small
+      // allocations...and this can cause all allocations to be pruned.
+      // ASSERT_NO_FATAL_FAILURE(ValidateDump(dump_json.get(), 0, 0));
+    } else {
+      if (heaps_v2) {
+        LOG(ERROR) << "There should be no heap dump for the renderer.";
+        return false;
+      }
     }
 
-    base::Value* process_mmaps =
-        FindArgDump(renderer_pid, dump_json, "process_mmaps");
-    if (!ValidateProcessMmaps(process_mmaps, HasNativeFrames())) {
-      LOG(ERROR) << "Failed to validate renderer process mmaps.";
-      return false;
-    }
-
-    // ValidateDump doesn't always succeed for the renderer, since we don't do
-    // anything to flush allocations, there are very few allocations recorded
-    // by the heap profiler. When we do a heap dump, we prune small
-    // allocations...and this can cause all allocations to be pruned.
-    // ASSERT_NO_FATAL_FAILURE(ValidateDump(dump_json.get(), 0, 0));
-  } else {
-    if (heaps_v2) {
-      LOG(ERROR) << "There should be no heap dump for the renderer.";
-      return false;
-    }
-  }
-
-  if (options_.mode == Mode::kAllRenderers) {
-    if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) {
-      LOG(ERROR) << "There should be at least 1 renderer dump";
-      return false;
-    }
-  } else {
-    if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) {
-      LOG(ERROR) << "There should be more than 1 renderer dump";
-      return false;
+    if (options_.mode == Mode::kAllRenderers) {
+      if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) {
+        LOG(ERROR) << "There should be at least 1 renderer dump";
+        return false;
+      }
+    } else {
+      if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) {
+        LOG(ERROR) << "There should be more than 1 renderer dump";
+        return false;
+      }
     }
   }
 
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index f6c52d67..562367e 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -48,15 +48,7 @@
 namespace {
 
 int RenderProcessHostCount() {
-  content::RenderProcessHost::iterator hosts =
-      content::RenderProcessHost::AllHostsIterator();
-  int count = 0;
-  while (!hosts.IsAtEnd()) {
-    if (hosts.GetCurrentValue()->HasConnection())
-      count++;
-    hosts.Advance();
-  }
-  return count;
+  return content::RenderProcessHost::GetCurrentRenderProcessCountForTesting();
 }
 
 WebContents* FindFirstDevToolsContents() {
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
index 02575f9..b9ed89b 100644
--- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -1311,20 +1311,44 @@
   DISALLOW_COPY_AND_ASSIGN(TestBrowserClient);
 };
 
+// Earlier injection of TestBrowserClient (a ContentBrowserClient) is needed to
+// make sure it is active during creation of the first spare RenderProcessHost.
+// Without this change, the tests would be surprised that they cannot find an
+// injected message filter via GetTextInputClientMessageFilterForProcess.
+class SitePerProcessCustomTextInputManagerFilteringTest
+    : public SitePerProcessTextInputManagerTest {
+ public:
+  SitePerProcessCustomTextInputManagerFilteringTest() {}
+  ~SitePerProcessCustomTextInputManagerFilteringTest() override {}
+
+  void CreatedBrowserMainParts(content::BrowserMainParts* parts) override {
+    SitePerProcessTextInputManagerTest::CreatedBrowserMainParts(parts);
+    browser_client_ = std::make_unique<TestBrowserClient>();
+  }
+
+  void TearDown() override {
+    browser_client_.reset();
+    SitePerProcessTextInputManagerTest::TearDown();
+  }
+
+  scoped_refptr<content::TestTextInputClientMessageFilter>
+  GetTextInputClientMessageFilterForProcess(
+      content::RenderProcessHost* process_host) const {
+    return browser_client_->GetTextInputClientMessageFilterForProcess(
+        process_host);
+  }
+
+ private:
+  std::unique_ptr<TestBrowserClient> browser_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(SitePerProcessCustomTextInputManagerFilteringTest);
+};
+
 // This test verifies that requests for dictionary lookup based on selection
 // range are routed to the focused RenderWidgetHost.
 // Test is flaky: http://crbug.com/710842
-IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
+IN_PROC_BROWSER_TEST_F(SitePerProcessCustomTextInputManagerFilteringTest,
                        DISABLED_LookUpStringForRangeRoutesToFocusedWidget) {
-  // TestBrowserClient needs to replace the ChromeContenBrowserClient after most
-  // things are initialized but before the WebContents is created. Here we make
-  // that happen by creating a new WebContents in a new tab. But before the test
-  // exits, we must destroy the contents and replace the old
-  // ContentBrowserClient because the original WebContents and the new one have
-  // been initialized with the original ContentBrowserClient and the new
-  // TestBrowserClient, respectively.
-  TestBrowserClient browser_client;
-
   content::WebContents* new_contents =
       content::WebContents::Create(content::WebContents::CreateParams(
           active_contents()->GetBrowserContext(), nullptr));
@@ -1360,8 +1384,8 @@
   content::AskForLookUpDictionaryForRange(views[0], gfx::Range(0, 4));
 
   // Wait until the result comes back.
-  auto root_filter = browser_client.GetTextInputClientMessageFilterForProcess(
-      frames[0]->GetProcess());
+  auto root_filter =
+      GetTextInputClientMessageFilterForProcess(frames[0]->GetProcess());
   EXPECT_TRUE(root_filter);
   root_filter->WaitForStringFromRange();
 
@@ -1382,8 +1406,8 @@
   content::AskForLookUpDictionaryForRange(views[0], gfx::Range(0, 5));
 
   // Wait until the result comes back.
-  auto child_filter = browser_client.GetTextInputClientMessageFilterForProcess(
-      frames[1]->GetProcess());
+  auto child_filter =
+      GetTextInputClientMessageFilterForProcess(frames[1]->GetProcess());
   child_filter->WaitForStringFromRange();
 
   EXPECT_EQ("child", child_filter->string_from_range());
@@ -1403,10 +1427,8 @@
 // crash. This test covers the case where the target RenderWidgetHost is that of
 // an OOPIF.
 IN_PROC_BROWSER_TEST_F(
-    SitePerProcessTextInputManagerTest,
+    SitePerProcessCustomTextInputManagerFilteringTest,
     DoNotCrashBrowserInWordLookUpForDestroyedWidget_ChildFrame) {
-  TestBrowserClient browser_client;
-
   content::WebContents* new_contents =
       content::WebContents::Create(content::WebContents::CreateParams(
           active_contents()->GetBrowserContext(), nullptr));
@@ -1427,9 +1449,8 @@
 
   content::RenderWidgetHostView* child_view = child_frame->GetView();
   scoped_refptr<content::TestTextInputClientMessageFilter>
-      child_message_filter =
-          browser_client.GetTextInputClientMessageFilterForProcess(
-              child_view->GetRenderWidgetHost()->GetProcess());
+      child_message_filter = GetTextInputClientMessageFilterForProcess(
+          child_view->GetRenderWidgetHost()->GetProcess());
   DCHECK(child_message_filter);
 
   // We need to wait for test scenario to complete before leaving this block.
@@ -1476,10 +1497,8 @@
 // crash. This test covers the case where the target RenderWidgetHost is that of
 // the main frame (no OOPIFs on page).
 IN_PROC_BROWSER_TEST_F(
-    SitePerProcessTextInputManagerTest,
+    SitePerProcessCustomTextInputManagerFilteringTest,
     DoNotCrashBrowserInWordLookUpForDestroyedWidget_MainFrame) {
-  TestBrowserClient browser_client;
-
   content::WebContents* new_contents =
       content::WebContents::Create(content::WebContents::CreateParams(
           active_contents()->GetBrowserContext(), nullptr));
@@ -1499,7 +1518,7 @@
 
   content::RenderWidgetHostView* page_rwhv = main_frame->GetView();
   scoped_refptr<content::TestTextInputClientMessageFilter> message_filter =
-      browser_client.GetTextInputClientMessageFilterForProcess(
+      GetTextInputClientMessageFilterForProcess(
           page_rwhv->GetRenderWidgetHost()->GetProcess());
   DCHECK(message_filter);
 
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
index a82a80da..008d983 100644
--- a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
+++ b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
@@ -80,7 +80,9 @@
   // A tab is already open when the test begins.
   StartGatherCycleAndWait();
   EXPECT_EQ(1u, probe.current_gather_cycle_for_testing());
-  EXPECT_EQ(1u, probe.render_process_info_map_for_testing().size());
+  size_t initial_size = probe.render_process_info_map_for_testing().size();
+  EXPECT_LE(1u, initial_size);
+  EXPECT_GE(2u, initial_size);  // If a spare RenderProcessHost is present.
   EXPECT_TRUE(probe.AllRenderProcessMeasurementsAreCurrentForTesting());
 
   // Open a second tab and complete a navigation.
@@ -91,7 +93,8 @@
           ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   StartGatherCycleAndWait();
   EXPECT_EQ(2u, probe.current_gather_cycle_for_testing());
-  EXPECT_EQ(2u, probe.render_process_info_map_for_testing().size());
+  EXPECT_EQ(initial_size + 1u,
+            probe.render_process_info_map_for_testing().size());
   EXPECT_TRUE(probe.AllRenderProcessMeasurementsAreCurrentForTesting());
 
   // Kill one of the two open tabs.
@@ -103,7 +106,7 @@
                   ->FastShutdownIfPossible());
   StartGatherCycleAndWait();
   EXPECT_EQ(3u, probe.current_gather_cycle_for_testing());
-  EXPECT_EQ(1u, probe.render_process_info_map_for_testing().size());
+  EXPECT_EQ(initial_size, probe.render_process_info_map_for_testing().size());
   EXPECT_TRUE(probe.AllRenderProcessMeasurementsAreCurrentForTesting());
 }
 
diff --git a/chrome/browser/resources/bookmark_manager/js/dnd.js b/chrome/browser/resources/bookmark_manager/js/dnd.js
index 65f382b..9a97faf0 100644
--- a/chrome/browser/resources/bookmark_manager/js/dnd.js
+++ b/chrome/browser/resources/bookmark_manager/js/dnd.js
@@ -323,7 +323,8 @@
 
     if (target instanceof ListItem) {
       // Use selected items.
-      draggedNodes = target.parentNode.selectedItems;
+      draggedNodes =
+          /** @type {cr.ui.List} */ (target.parentNode).selectedItems;
     } else if (target instanceof TreeItem) {
       draggedNodes.push(target.bookmarkNode);
     }
diff --git a/chrome/browser/resources/bookmark_manager/js/main.js b/chrome/browser/resources/bookmark_manager/js/main.js
index c2689e21..9da605a 100644
--- a/chrome/browser/resources/bookmark_manager/js/main.js
+++ b/chrome/browser/resources/bookmark_manager/js/main.js
@@ -257,7 +257,7 @@
 // Activate is handled by the open-in-same-window-command.
 function handleDoubleClickForList(e) {
   if (e.button == 0)
-    $('open-in-same-window-command').execute();
+    /** @type {Command} */ ($('open-in-same-window-command')).execute();
 }
 
 // The list dispatches an event when the user clicks on the URL or the Show in
@@ -731,7 +731,8 @@
  * Update the canExecute state of all the commands.
  */
 function updateAllCommands() {
-  var commands = document.querySelectorAll('command');
+  var commands =
+      /** @type {NodeList<Command>} */ (document.querySelectorAll('command'));
   for (var i = 0; i < commands.length; i++) {
     commands[i].canExecuteChange();
   }
@@ -756,7 +757,7 @@
     if (result != canEdit) {
       canEdit = result;
       editingCommands.forEach(function(baseId) {
-        $(baseId + '-command').canExecuteChange();
+        /** @type {Command} */ ($(baseId + '-command')).canExecuteChange();
       });
     }
   });
@@ -770,10 +771,12 @@
   updateEditingCommands();
 
   if (e.currentTarget.id == 'folders-menu') {
-    $('copy-from-folders-menu-command').canExecuteChange();
-    $('undo-delete-from-folders-menu-command').canExecuteChange();
+    /** @type {Command} */ ($('copy-from-folders-menu-command'))
+        .canExecuteChange();
+    /** @type {Command} */ ($('undo-delete-from-folders-menu-command'))
+        .canExecuteChange();
   } else {
-    $('copy-command').canExecuteChange();
+    /** @type {Command} */ ($('copy-command')).canExecuteChange();
   }
 }
 
@@ -959,8 +962,9 @@
   function performDelete() {
     // Only remove filtered ids.
     chrome.bookmarkManagerPrivate.removeTrees(filteredIds);
-    $('undo-delete-command').canExecuteChange();
-    $('undo-delete-from-folders-menu-command').canExecuteChange();
+    /** @type {Command} */ ($('undo-delete-command')).canExecuteChange();
+    /** @type {Command} */ ($('undo-delete-from-folders-menu-command'))
+        .canExecuteChange();
     performGlobalUndo = undoDelete;
   }
 
@@ -1019,8 +1023,9 @@
     arr.forEach(restoreTree);
   });
   lastDeleted = null;
-  $('undo-delete-command').canExecuteChange();
-  $('undo-delete-from-folders-menu-command').canExecuteChange();
+  /** @type {Command} */ ($('undo-delete-command')).canExecuteChange();
+  /** @type {Command} */ ($('undo-delete-from-folders-menu-command'))
+      .canExecuteChange();
 
   // Only a single level of undo is supported, so disable global undo now.
   performGlobalUndo = null;
@@ -1411,7 +1416,7 @@
     if (document.activeElement != bmm.list &&
         document.activeElement != bmm.tree)
       return;
-    var command = $(commandId);
+    var command = /** @type {Command} */ ($(commandId));
     if (!command.disabled) {
       command.execute();
       if (e)
diff --git a/chrome/browser/resources/discards/discards.html b/chrome/browser/resources/discards/discards.html
index 96ae713..8fbb143 100644
--- a/chrome/browser/resources/discards/discards.html
+++ b/chrome/browser/resources/discards/discards.html
@@ -34,6 +34,7 @@
           <th data-sort-key="utilityRank" class="sort-column">Utility Rank</th>
           <th data-sort-key="title">Tab Title</th>
           <th data-sort-key="tabUrl">Tab URL</th>
+          <th data-sort-key="visibility">Visibility</th>
           <th data-sort-key="isMedia">Media</th>
           <th data-sort-key="isDiscarded">Discarded</th>
           <th data-sort-key="discardCount">Discard Count</th>
@@ -56,6 +57,7 @@
           </div>
         </td>
         <td class="tab-url-cell"></td>
+        <td class="visibility-cell"></td>
         <td class="is-media-cell boolean-cell"></td>
         <td class="is-discarded-cell boolean-cell"></td>
         <td class="discard-count-cell"></td>
diff --git a/chrome/browser/resources/discards/discards.js b/chrome/browser/resources/discards/discards.js
index 2c2da84..d282054 100644
--- a/chrome/browser/resources/discards/discards.js
+++ b/chrome/browser/resources/discards/discards.js
@@ -71,8 +71,10 @@
     }
 
     // Compares numeric fields.
-    if (['discardCount', 'utilityRank', 'lastActiveSeconds'].includes(
-            sortKey)) {
+    // Note: Visibility is represented as a numeric value.
+    if ([
+          'visibility', 'discardCount', 'utilityRank', 'lastActiveSeconds'
+        ].includes(sortKey)) {
       return val1 - val2;
     }
 
@@ -179,6 +181,24 @@
   }
 
   /**
+   * Returns a string representation of a visibility enum value for display in
+   * a table.
+   * @param {int} visibility A value in LifecycleUnitVisibility.
+   * @return {string} A string representation of the visibility.
+   */
+  function visibilityToString(visibility) {
+    switch (visibility) {
+      case 0:
+        return 'hidden';
+      case 1:
+        return 'occluded';
+      case 2:
+        return 'visible';
+    }
+    assertNotReached('Unsupported visibility: ' + visibility);
+  }
+
+  /**
    * Returns the index of the row in the table that houses the given |element|.
    * @param {HTMLElement} element Any element in the DOM.
    */
@@ -258,6 +278,8 @@
         info.faviconUrl ? info.faviconUrl : 'chrome://favicon';
     row.querySelector('.title-div').textContent = info.title;
     row.querySelector('.tab-url-cell').textContent = info.tabUrl;
+    row.querySelector('.visibility-cell').textContent =
+        visibilityToString(info.visibility);
     row.querySelector('.is-media-cell').textContent =
         boolToString(info.isMedia);
     row.querySelector('.is-discarded-cell').textContent =
diff --git a/chrome/browser/resources/extensions/chromeos/kiosk_apps.js b/chrome/browser/resources/extensions/chromeos/kiosk_apps.js
index 969842a..3052f55 100644
--- a/chrome/browser/resources/extensions/chromeos/kiosk_apps.js
+++ b/chrome/browser/resources/extensions/chromeos/kiosk_apps.js
@@ -120,17 +120,18 @@
    *     app info objects and disable bailout shortcut flag.
    */
   KioskAppsOverlay.setSettings = function(settings) {
-    $('kiosk-app-list').setApps(settings.apps);
+    /** @type {extensions.KioskAppList} */ ($('kiosk-app-list'))
+        .setApps(settings.apps);
     $('kiosk-disable-bailout-shortcut').checked = settings.disableBailout;
     $('kiosk-disable-bailout-shortcut').disabled = !settings.hasAutoLaunchApp;
   };
 
   /**
    * Update an app in kiosk-app-list.
-   * @param {!Object} app App info to be updated.
+   * @param {!AppDict} app App info to be updated.
    */
   KioskAppsOverlay.updateApp = function(app) {
-    $('kiosk-app-list').updateApp(app);
+    /** @type {extensions.KioskAppList} */ ($('kiosk-app-list')).updateApp(app);
   };
 
   /**
@@ -149,7 +150,8 @@
     $('add-kiosk-app').hidden = !params.kioskEnabled;
     $('kiosk-disable-bailout-shortcut').parentNode.hidden =
         !params.autoLaunchEnabled;
-    $('kiosk-app-list').setAutoLaunchEnabled(params.autoLaunchEnabled);
+    /** @type {extensions.KioskAppList} */ ($('kiosk-app-list'))
+        .setAutoLaunchEnabled(params.autoLaunchEnabled);
   };
 
   // Export
diff --git a/chrome/browser/resources/extensions/extension_code.js b/chrome/browser/resources/extensions/extension_code.js
index 255909d..fd99783 100644
--- a/chrome/browser/resources/extensions/extension_code.js
+++ b/chrome/browser/resources/extensions/extension_code.js
@@ -6,7 +6,7 @@
  * @typedef {{afterHighlight: string,
  *            beforeHighlight: string,
  *            highlight: string,
- *            title: string}}
+ *            message: string}}
  */
 var ExtensionHighlight;
 
diff --git a/chrome/browser/resources/extensions/extension_error_overlay.js b/chrome/browser/resources/extensions/extension_error_overlay.js
index 244a45e5..c8d6948b 100644
--- a/chrome/browser/resources/extensions/extension_error_overlay.js
+++ b/chrome/browser/resources/extensions/extension_error_overlay.js
@@ -44,7 +44,7 @@
         querySelector('.extension-error-overlay-runtime-content').
         cloneNode(true);
     contentArea.__proto__ = RuntimeErrorContent.prototype;
-    contentArea.init();
+    /** @type {RuntimeErrorContent} */ (contentArea).init();
     return contentArea;
   }
 
@@ -360,7 +360,9 @@
       // Remove all previous content.
       this.codeDiv_.clear();
 
-      this.overlayDiv_.querySelector('.extension-error-list').onRemoved();
+      /** @type {extensions.ExtensionErrorList} */ (
+          this.overlayDiv_.querySelector('.extension-error-list'))
+          .onRemoved();
 
       this.clearRuntimeContent_();
 
diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js
index 5582d587..5a2e396e 100644
--- a/chrome/browser/resources/extensions/extension_list.js
+++ b/chrome/browser/resources/extensions/extension_list.js
@@ -191,7 +191,8 @@
           case EventType.UNINSTALLED:
             var index = this.getIndexOfExtension_(eventData.item_id);
             this.extensions_.splice(index, 1);
-            this.removeWrapper_(getRequiredElement(eventData.item_id));
+            this.removeWrapper_(/**@type {!ExtensionWrapper} */ (
+                getRequiredElement(eventData.item_id)));
             break;
           default:
             assertNotReached();
@@ -293,7 +294,7 @@
 
       var idToHighlight = this.getIdQueryParam_();
       if (idToHighlight) {
-        var wrapper = $(idToHighlight);
+        var wrapper = /** @type {ExtensionWrapper} */ ($(idToHighlight));
         if (wrapper) {
           this.scrollToWrapper_(idToHighlight);
 
@@ -363,15 +364,15 @@
     /**
      * Removes the wrapper from the DOM and updates the focused element if
      * needed.
-     * @param {!Element} wrapper
+     * @param {!ExtensionWrapper} wrapper
      * @private
      */
     removeWrapper_: function(wrapper) {
       // If focus is in the wrapper about to be removed, move it first. This
       // happens when clicking the trash can to remove an extension.
       if (wrapper.contains(document.activeElement)) {
-        var wrappers = document.querySelectorAll(
-            '.extension-list-item-wrapper[id]');
+        var wrappers = /** @type {NodeList<ExtensionWrapper>}*/ (
+            document.querySelectorAll('.extension-list-item-wrapper[id]'));
         var index = Array.prototype.indexOf.call(wrappers, wrapper);
         assert(index != -1);
         var focusableWrapper = wrappers[index + 1] || wrappers[index - 1];
@@ -597,7 +598,8 @@
      * Updates an HTML element for the extension metadata given in |extension|.
      * @param {!chrome.developerPrivate.ExtensionInfo} extension A dictionary of
      *     extension metadata.
-     * @param {!Element} wrapper The extension wrapper element to update.
+     * @param {!ExtensionWrapper} wrapper The extension wrapper element to
+     *     update.
      * @private
      */
     updateWrapper_: function(extension, wrapper) {
@@ -1047,7 +1049,7 @@
         this.extensions_.sort(compareExtensions);
       }
 
-      var wrapper = $(extension.id);
+      var wrapper = /**@type {ExtensionWrapper} */ ($(extension.id));
       if (wrapper) {
         this.updateWrapper_(extension, wrapper);
       } else {
diff --git a/chrome/browser/resources/extensions/extension_loader.js b/chrome/browser/resources/extensions/extension_loader.js
index 95def83d..5c03d50 100644
--- a/chrome/browser/resources/extensions/extension_loader.js
+++ b/chrome/browser/resources/extensions/extension_loader.js
@@ -13,7 +13,7 @@
    */
   function ExtensionLoadError(div) {
     div.__proto__ = ExtensionLoadError.prototype;
-    div.init();
+    /** @type {ExtensionLoadError} */ (div).init();
     return div;
   }
 
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js
index 4f9d1b2..b3be062 100644
--- a/chrome/browser/resources/extensions/extensions.js
+++ b/chrome/browser/resources/extensions/extensions.js
@@ -202,7 +202,8 @@
       this.updateDevToggleControlledIndicator_(developerModeControlledByPolicy);
 
       $('load-unpacked').disabled = !profileInfo.canLoadUnpacked;
-      var extensionList = $('extension-settings-list');
+      var extensionList = /** @type {extensions.ExtensionList} */ (
+          $('extension-settings-list'));
       extensionList.updateExtensionsData(
           profileInfo.isIncognitoAvailable,
           profileInfo.appInfoDialogEnabled).then(function() {
@@ -331,7 +332,9 @@
     /** @override */
     onExtensionCountChanged: function() {
       /** @const */
-      var hasExtensions = $('extension-settings-list').getNumExtensions() != 0;
+      var hasExtensions =
+          /** @type {extensions.ExtensionList} */ ($('extension-settings-list'))
+              .getNumExtensions() != 0;
       $('no-extensions').hidden = hasExtensions;
       $('extension-list-wrapper').hidden = !hasExtensions;
     },
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js
index 7242b5b2..713c4f37 100644
--- a/chrome/browser/resources/ntp4/apps_page.js
+++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -627,7 +627,8 @@
      * @private
      */
     onCardSelected_: function() {
-      var apps = this.querySelectorAll('.app.icon-loading');
+      var apps = /** @type {NodeList<ntp.App>} */ (
+          this.querySelectorAll('.app.icon-loading'));
       for (var i = 0; i < apps.length; i++) {
         apps[i].loadIcon();
       }
diff --git a/chrome/browser/resources/ntp4/page_list_view.js b/chrome/browser/resources/ntp4/page_list_view.js
index 3f2e99b..cf3278c 100644
--- a/chrome/browser/resources/ntp4/page_list_view.js
+++ b/chrome/browser/resources/ntp4/page_list_view.js
@@ -87,7 +87,7 @@
 
     /**
      * The 'dots-list' element.
-     * @type {!Element|undefined}
+     * @type {!ntp.DotList|undefined}
      */
     dotList: undefined,
 
@@ -145,7 +145,7 @@
         opt_pageSwitcherEnd) {
       this.pageList = pageList;
 
-      this.dotList = dotList;
+      this.dotList = /** @type {!ntp.DotList} */ (dotList);
       cr.ui.decorate(this.dotList, ntp.DotList);
 
       this.trash = opt_trash;
@@ -191,7 +191,8 @@
       // This listener must be added before the card slider is initialized,
       // because it needs to be called before the card slider's handler.
       cardSliderFrame.addEventListener('mousewheel', function(e) {
-        if (cardSlider.currentCardValue.handleMouseWheel(e)) {
+        if (/** @type {!ntp.TilePage} */ (cardSlider.currentCardValue)
+                .handleMouseWheel(e)) {
           e.preventDefault();            // Prevent default scroll behavior.
           e.stopImmediatePropagation();  // Prevent horizontal card flipping.
         }
@@ -430,7 +431,7 @@
       }
 
       var page = this.appsPages[pageIndex];
-      var app = $(appData.id);
+      var app = /** @type {?ntp.App} */ ($(appData.id));
       if (app) {
         app.replaceAppData(appData);
       } else if (opt_highlight) {
@@ -535,7 +536,8 @@
       if (!this.pageSwitcherStart || !this.pageSwitcherEnd)
         return;
 
-      var page = this.cardSlider.currentCardValue;
+      var page =
+          /** @type {?ntp.TilePage} */ (this.cardSlider.currentCardValue);
 
       this.pageSwitcherStart.hidden =
           !page || (this.cardSlider.currentCard == 0);
@@ -676,7 +678,8 @@
      * @private
      */
     updateOfflineEnabledApps_: function() {
-      var apps = document.querySelectorAll('.app');
+      var apps = /** @type {!NodeList<!ntp.App>} */ (
+          document.querySelectorAll('.app'));
       for (var i = 0; i < apps.length; ++i) {
         if (apps[i].appData.enabled && !apps[i].appData.offlineEnabled) {
           apps[i].setIcon();
diff --git a/chrome/browser/resources/ntp4/tile_page.js b/chrome/browser/resources/ntp4/tile_page.js
index 3c48c361..d215f89 100644
--- a/chrome/browser/resources/ntp4/tile_page.js
+++ b/chrome/browser/resources/ntp4/tile_page.js
@@ -111,7 +111,7 @@
       setCurrentlyDraggingTile(this);
 
       e.dataTransfer.effectAllowed = 'copyMove';
-      this.firstChild.setDragData(e.dataTransfer);
+      /** @type {!ntp.App} */ (this.firstChild).setDragData(e.dataTransfer);
 
       // The drag clone is the node we use as a representation during the drag.
       // It's attached to the top level document element so that it floats above
@@ -1297,7 +1297,7 @@
     /**
      * Sets the drop effect on |dataTransfer| to the desired value (e.g.
      * 'copy').
-     * @param {Object} dataTransfer The drag event dataTransfer object.
+     * @param {DataTransfer} dataTransfer The drag event dataTransfer object.
      */
     setDropEffect: function(dataTransfer) {
       assertNotReached();
diff --git a/chrome/browser/resources/policy_tool.html b/chrome/browser/resources/policy_tool.html
index e2d27feb..073e871 100644
--- a/chrome/browser/resources/policy_tool.html
+++ b/chrome/browser/resources/policy_tool.html
@@ -62,6 +62,7 @@
       <div id="session-actions">
         <button id="delete-session-button">$i18n{removeSession}</button>
         <button id="rename-session-button">$i18n{renameSession}</button>
+        <button id="export-policies-linux">$i18n{exportLinux}</button>
       </div>
       <select size="4" id="session-list">
       </select>
diff --git a/chrome/browser/resources/policy_tool.js b/chrome/browser/resources/policy_tool.js
index 27f8090..b80796d7 100644
--- a/chrome/browser/resources/policy_tool.js
+++ b/chrome/browser/resources/policy_tool.js
@@ -169,6 +169,10 @@
     }
   };
 
+  $('export-policies-linux').onclick = (event) => {
+    chrome.send('exportLinux', [policy.Page.getInstance().getDictionary()]);
+  };
+
   // Notify the browser that the page has loaded, causing it to send the
   // list of all known policies and the values from the default session.
   chrome.send('initialized');
diff --git a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
index 00a484c..34577fe 100644
--- a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
+++ b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
@@ -84,9 +84,11 @@
   attached: function() {
     this.writeUma_(LockScreenProgress.START_SCREEN_LOCK);
     this.$.dialog.showModal();
+    // This needs to occur at the next paint otherwise the password input will
+    // not receive focus.
     this.async(() => {
       this.$.passwordInput.focus();
-    });
+    }, 1);
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
index 61c3c8e7..62595331c 100644
--- a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
+++ b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
@@ -55,14 +55,14 @@
         close-text="$i18n{close}">
       <div slot="title">[[getTitleMessage_(isConfirmStep_)]]</div>
       <div slot="body">
-        <!-- Pin keyboard -->
+        <!-- PIN keyboard -->
         <div id="pinKeyboardDiv" class="settings-box continuation">
           <pin-keyboard id="pinKeyboard" on-pin-change="onPinChange_"
               on-submit="onPinSubmit_" value="{{pinKeyboardValue_}}"
               has-error$="[[hasError_(problemMessage_, problemClass_)]]">
             <!-- Warning/error; only shown if title is hidden. -->
             <div id="problemDiv" class$="[[problemClass_]]"
-                hidden="[[!problemMessage_]]" problem>
+                invisible$="[[!problemMessage_]]" problem>
               <iron-icon icon="cr:error-outline"></iron-icon>
               <span id="problemMessage">[[problemMessage_]]</span>
             </div>
@@ -73,7 +73,6 @@
         <paper-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
         </paper-button>
-
         <paper-button class="action-button" on-click="onPinSubmit_"
             disabled$="[[!enableSubmit_]]">
           <span>[[getContinueMessage_(isConfirmStep_)]]</span>
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index dbe9f12..ffe274d 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -461,7 +461,6 @@
     database_manager_->StopOnIOThread(shutdown);
   }
 #endif
-  ui_manager_->StopOnIOThread(shutdown);
 
   services_delegate_->StopOnIOThread(shutdown);
 
@@ -497,6 +496,7 @@
 
 void SafeBrowsingService::Stop(bool shutdown) {
   ping_manager_.reset();
+  ui_manager_->Stop(shutdown);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&SafeBrowsingService::StopOnIOThread, this, shutdown));
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc
index ba9ccee..79b5aef 100644
--- a/chrome/browser/safe_browsing/ui_manager.cc
+++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -48,11 +48,11 @@
 
 SafeBrowsingUIManager::~SafeBrowsingUIManager() {}
 
-void SafeBrowsingUIManager::StopOnIOThread(bool shutdown) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void SafeBrowsingUIManager::Stop(bool shutdown) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (shutdown)
-    sb_service_ = NULL;
+    sb_service_ = nullptr;
 }
 
 void SafeBrowsingUIManager::CreateAndSendHitReport(
@@ -173,7 +173,7 @@
 // when the report is ready.
 void SafeBrowsingUIManager::SendSerializedThreatDetails(
     const std::string& serialized) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // The service may delete the ping manager (i.e. when user disabling service,
   // etc). This happens on the IO thread.
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h
index 069b367..f55740e 100644
--- a/chrome/browser/safe_browsing/ui_manager.h
+++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -56,10 +56,10 @@
   explicit SafeBrowsingUIManager(
       const scoped_refptr<SafeBrowsingService>& service);
 
-  // Called to stop or shutdown operations on the io_thread. This may be called
+  // Called to stop or shutdown operations on the UI thread. This may be called
   // multiple times during the life of the UIManager. Should be called
-  // on IO thread. If shutdown is true, the manager is disabled permanently.
-  void StopOnIOThread(bool shutdown) override;
+  // on UI thread. If shutdown is true, the manager is disabled permanently.
+  void Stop(bool shutdown);
 
   // Called on the IO thread by the ThreatDetails with the serialized
   // protocol buffer, so the service can send it over.
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc
index ab8fa12..42e438fb 100644
--- a/chrome/browser/site_details_browsertest.cc
+++ b/chrome/browser/site_details_browsertest.cc
@@ -268,13 +268,7 @@
   }
 
   int GetRenderProcessCount() {
-    int count = 0;
-    for (content::RenderProcessHost::iterator it(
-             content::RenderProcessHost::AllHostsIterator());
-         !it.IsAtEnd(); it.Advance()) {
-      count++;
-    }
-    return count;
+    return content::RenderProcessHost::GetCurrentRenderProcessCountForTesting();
   }
 
  private:
diff --git a/chrome/browser/ssl/captive_portal_helper_android.cc b/chrome/browser/ssl/captive_portal_helper_android.cc
index 6c75886..da72d48 100644
--- a/chrome/browser/ssl/captive_portal_helper_android.cc
+++ b/chrome/browser/ssl/captive_portal_helper_android.cc
@@ -46,6 +46,10 @@
                      os_reports_captive_portal));
 }
 
+void ReportNetworkConnectivity(JNIEnv* env) {
+  Java_CaptivePortalHelper_reportNetworkConnectivity(env);
+}
+
 std::string GetCaptivePortalServerUrl(JNIEnv* env) {
   return base::android::ConvertJavaStringToUTF8(
       Java_CaptivePortalHelper_getCaptivePortalServerUrl(env));
diff --git a/chrome/browser/ssl/captive_portal_helper_android.h b/chrome/browser/ssl/captive_portal_helper_android.h
index 99359cef..e307e8b 100644
--- a/chrome/browser/ssl/captive_portal_helper_android.h
+++ b/chrome/browser/ssl/captive_portal_helper_android.h
@@ -13,6 +13,8 @@
 
 std::string GetCaptivePortalServerUrl(JNIEnv* env);
 
+void ReportNetworkConnectivity(JNIEnv* env);
+
 }  // namespace android
 }  // namespace chrome
 
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 610d81d..95ffe312 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -23,6 +23,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
@@ -5903,12 +5904,19 @@
 }
 
 // Tests the scenario where the OS reports a captive portal. A captive portal
-// interstitial should be displayed.
+// interstitial should be displayed. The test then switches OS captive portal
+// status to false and reloads the page. This time, a normal SSL interstitial
+// will be displayed.
 IN_PROC_BROWSER_TEST_P(SSLUITest, OSReportsCaptivePortal) {
   ASSERT_TRUE(https_server_mismatched_.Start());
   base::HistogramTester histograms;
-
+  bool netwok_connectivity_reported = false;
   SSLErrorHandler::SetOSReportsCaptivePortalForTesting(true);
+  SSLErrorHandler::SetReportNetworkConnectivityCallbackForTesting(
+      base::BindLambdaForTesting([&]() {
+        SSLErrorHandler::SetOSReportsCaptivePortalForTesting(false);
+        netwok_connectivity_reported = true;
+      }));
 
   // Navigate to an unsafe page on the server.
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
@@ -5929,6 +5937,13 @@
       SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
   histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
                                SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 1);
+
+  // Reload the URL. This time the OS should not report a captive portal.
+  ui_test_utils::NavigateToURL(
+      browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
+  WaitForInterstitial(tab);
+  ASSERT_NO_FATAL_FAILURE(ExpectSSLInterstitial(tab));
+  EXPECT_TRUE(netwok_connectivity_reported);
 }
 
 // Tests the scenario where the OS reports a captive portal but captive portal
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index dcd971d9..8f5e2f2 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -57,6 +57,11 @@
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #endif  // #if defined(OS_WIN)
 
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "chrome/browser/ssl/captive_portal_helper_android.h"
+#endif
+
 const base::Feature kMITMSoftwareInterstitial{"MITMSoftwareInterstitial",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -218,6 +223,8 @@
   void SetClockForTesting(base::Clock* clock);
   void SetNetworkTimeTrackerForTesting(
       network_time::NetworkTimeTracker* tracker);
+  void SetReportNetworkConnectivityCallbackForTesting(
+      base::OnceClosure callback);
 
   void SetErrorAssistantProto(
       std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
@@ -231,6 +238,10 @@
   void SetOSReportsCaptivePortalForTesting(bool os_reports_captive_portal);
   bool DoesOSReportCaptivePortalForTesting() const;
 
+  base::OnceClosure report_network_connectivity_callback() {
+    return std::move(report_network_connectivity_callback_);
+  }
+
  private:
   base::TimeDelta interstitial_delay_;
 
@@ -244,6 +255,8 @@
 
   network_time::NetworkTimeTracker* network_time_tracker_ = nullptr;
 
+  base::OnceClosure report_network_connectivity_callback_;
+
   enum EnterpriseManaged {
     ENTERPRISE_MANAGED_STATUS_NOT_SET,
     ENTERPRISE_MANAGED_STATUS_TRUE,
@@ -318,6 +331,11 @@
   network_time_tracker_ = tracker;
 }
 
+void ConfigSingleton::SetReportNetworkConnectivityCallbackForTesting(
+    base::OnceClosure closure) {
+  report_network_connectivity_callback_ = std::move(closure);
+}
+
 void ConfigSingleton::SetEnterpriseManagedForTesting(bool enterprise_managed) {
   if (enterprise_managed) {
     is_enterprise_managed_for_testing_ = ENTERPRISE_MANAGED_STATUS_TRUE;
@@ -433,6 +451,7 @@
   void ShowSSLInterstitial(const GURL& support_url) override;
   void ShowBadClockInterstitial(const base::Time& now,
                                 ssl_errors::ClockState clock_state) override;
+  void ReportNetworkConnectivity(base::OnceClosure callback) override;
 
  private:
   // Calls the |blocking_page_ready_callback_| if it's not null, else calls
@@ -543,6 +562,18 @@
       std::move(ssl_cert_reporter_), decision_callback_));
 }
 
+void SSLErrorHandlerDelegateImpl::ReportNetworkConnectivity(
+    base::OnceClosure callback) {
+#if defined(OS_ANDROID)
+  chrome::android::ReportNetworkConnectivity(
+      base::android::AttachCurrentThread());
+#else
+// Nothing to do on other platforms.
+#endif
+  if (callback)
+    std::move(callback).Run();
+}
+
 void SSLErrorHandlerDelegateImpl::OnBlockingPageReady(
     security_interstitials::SecurityInterstitialPage* interstitial_page) {
   if (blocking_page_ready_callback_.is_null()) {
@@ -654,6 +685,13 @@
 }
 
 // static
+void SSLErrorHandler::SetReportNetworkConnectivityCallbackForTesting(
+    base::OnceClosure closure) {
+  g_config.Pointer()->SetReportNetworkConnectivityCallbackForTesting(
+      std::move(closure));
+}
+
+// static
 void SSLErrorHandler::SetEnterpriseManagedForTesting(bool enterprise_managed) {
   g_config.Pointer()->SetEnterpriseManagedForTesting(enterprise_managed);
 }
@@ -735,6 +773,8 @@
   if (IsCaptivePortalInterstitialEnabled() &&
       (g_config.Pointer()->DoesOSReportCaptivePortalForTesting() ||
        delegate_->DoesOSReportCaptivePortal())) {
+    delegate_->ReportNetworkConnectivity(
+        g_config.Pointer()->report_network_connectivity_callback());
     RecordUMA(OS_REPORTS_CAPTIVE_PORTAL);
     ShowCaptivePortalInterstitial(GURL());
     return;
@@ -747,12 +787,16 @@
   // name-mismatch. If there are multiple errors, it indicates that the captive
   // portal landing page itself will have SSL errors, and so it's not a very
   // helpful place to direct the user to go.
-  if (base::FeatureList::IsEnabled(kCaptivePortalCertificateList) &&
-      only_error_is_name_mismatch &&
-      g_config.Pointer()->IsKnownCaptivePortalCertificate(ssl_info_)) {
-    RecordUMA(CAPTIVE_PORTAL_CERT_FOUND);
-    ShowCaptivePortalInterstitial(GURL());
-    return;
+  if (only_error_is_name_mismatch) {
+    delegate_->ReportNetworkConnectivity(
+        g_config.Pointer()->report_network_connectivity_callback());
+
+    if (base::FeatureList::IsEnabled(kCaptivePortalCertificateList) &&
+        g_config.Pointer()->IsKnownCaptivePortalCertificate(ssl_info_)) {
+      RecordUMA(CAPTIVE_PORTAL_CERT_FOUND);
+      ShowCaptivePortalInterstitial(GURL());
+      return;
+    }
   }
 
   // The MITM software interstitial is displayed if and only if:
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h
index 565ed0f4..02e32c6 100644
--- a/chrome/browser/ssl/ssl_error_handler.h
+++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -121,6 +121,7 @@
     virtual void ShowBadClockInterstitial(
         const base::Time& now,
         ssl_errors::ClockState clock_state) = 0;
+    virtual void ReportNetworkConnectivity(base::OnceClosure callback) = 0;
   };
 
   // Entry point for the class. All parameters except
@@ -155,6 +156,8 @@
   static void SetClockForTesting(base::Clock* testing_clock);
   static void SetNetworkTimeTrackerForTesting(
       network_time::NetworkTimeTracker* tracker);
+  static void SetReportNetworkConnectivityCallbackForTesting(
+      base::OnceClosure callback);
   static void SetEnterpriseManagedForTesting(bool enterprise_managed);
   static bool IsEnterpriseManagedFlagSetForTesting();
   static std::string GetHistogramNameForTesting();
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc
index 010164b7..6f2c9f1 100644
--- a/chrome/browser/ssl/ssl_error_handler_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -267,6 +267,8 @@
 
   bool IsErrorOverridable() const override { return is_overridable_error_; }
 
+  void ReportNetworkConnectivity(base::OnceClosure callback) override {}
+
   Profile* profile_;
   bool captive_portal_checked_;
   bool os_reports_captive_portal_;
diff --git a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc
index ddad919..58f7d6f 100644
--- a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc
+++ b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h"
 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -41,6 +42,10 @@
   content::WebContents* test_contents() { return test_contents_.get(); }
 
  private:
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory process_factory_;
+
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   SyncSessionsWebContentsRouter* router_;
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
index 36adbc77..bdce1e9 100644
--- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -32,10 +32,20 @@
   return specifics;
 }
 
+std::string GetAccountId() {
+#if defined(OS_CHROMEOS)
+  // TODO(vitaliii): Unify the two, because it takes ages to debug and
+  // impossible to discover otherwise.
+  return "user@gmail.com";
+#else
+  return "gaia-id-user@gmail.com";
+#endif
+}
+
 UserEventSpecifics CreateUserConsent(int microseconds) {
   UserEventSpecifics specifics;
   specifics.set_event_time_usec(microseconds);
-  specifics.mutable_user_consent();
+  specifics.mutable_user_consent()->set_account_id(GetAccountId());
   return specifics;
 }
 
diff --git a/chrome/browser/sync/user_event_service_factory.cc b/chrome/browser/sync/user_event_service_factory.cc
index a0e6a4a8..66b4950 100644
--- a/chrome/browser/sync/user_event_service_factory.cc
+++ b/chrome/browser/sync/user_event_service_factory.cc
@@ -37,7 +37,12 @@
 UserEventServiceFactory::UserEventServiceFactory()
     : BrowserContextKeyedServiceFactory(
           "UserEventService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          BrowserContextDependencyManager::GetInstance()) {
+  // TODO(vitaliii): This is missing
+  // DependsOn(ProfileSyncServiceFactory::GetInstance()), which we can't
+  // simply add because ProfileSyncServiceFactory itself depends on this
+  // factory.
+}
 
 UserEventServiceFactory::~UserEventServiceFactory() {}
 
@@ -61,7 +66,7 @@
                               chrome::GetChannel()));
   auto bridge = std::make_unique<syncer::UserEventSyncBridge>(
       std::move(store_factory), std::move(change_processor),
-      sync_service->GetGlobalIdMapper());
+      sync_service->GetGlobalIdMapper(), sync_service);
   return new syncer::UserEventServiceImpl(sync_service, std::move(bridge));
 }
 
diff --git a/chrome/browser/ui/accelerator_utils.h b/chrome/browser/ui/accelerator_utils.h
index 70b4591..3c274f7b 100644
--- a/chrome/browser/ui/accelerator_utils.h
+++ b/chrome/browser/ui/accelerator_utils.h
@@ -18,7 +18,7 @@
 bool IsChromeAccelerator(const ui::Accelerator& accelerator,
                          Profile* profile);
 
-ui::Accelerator GetPrimaryChromeAcceleratorForCommandId(int command_id);
+ui::Accelerator GetPrimaryChromeAcceleratorForBookmarkPage();
 
 }  // namespace chrome
 
diff --git a/chrome/browser/ui/ash/ksv/DEPS b/chrome/browser/ui/ash/ksv/DEPS
index da58492d..02f33c6 100644
--- a/chrome/browser/ui/ash/ksv/DEPS
+++ b/chrome/browser/ui/ash/ksv/DEPS
@@ -5,6 +5,7 @@
   "-ash",
   "-chrome",
   "+ash/components/shortcut_viewer",
+  "+ash/public",
   "+ash/shell.h",
   "+ash/wm/window_util.h",
   "+chrome/browser/ui/ash/ksv",
@@ -12,7 +13,6 @@
 
 specific_include_rules = {
   "keyboard_shortcut_viewer_metadata_unittest\.cc": [
-    "+ash/accelerators",
     "+chrome/browser/ui/views",
   ],
 }
diff --git a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc
index 3d3a799..1458f9e 100644
--- a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc
+++ b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -7,9 +7,9 @@
 #include <tuple>
 #include <vector>
 
-#include "ash/accelerators/accelerator_table.h"
 #include "ash/components/shortcut_viewer/keyboard_shortcut_item.h"
 #include "ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
+#include "ash/public/cpp/accelerators.h"
 #include "base/macros.h"
 #include "base/md5.h"
 #include "base/strings/string_util.h"
@@ -24,9 +24,9 @@
 // The hash of Ash accelerators.
 constexpr char kAshAcceleratorsHash[] = "71c96531d7639ba0ecf255a59546c243";
 // The total number of Chrome accelerators (available on Chrome OS).
-constexpr int kChromeAcceleratorsTotalNum = 91;
+constexpr int kChromeAcceleratorsTotalNum = 92;
 // The hash of Chrome accelerators (available on Chrome OS).
-constexpr char kChromeAcceleratorsHash[] = "cde825b73b85f0ff34a1ff78086e61c8";
+constexpr char kChromeAcceleratorsHash[] = "b6e72a2f2c8e86938e645663e2b0d1fe";
 
 const char* BooleanToString(bool value) {
   return value ? "true" : "false";
diff --git a/chrome/browser/ui/bookmarks/enhanced_bookmark_key_service.cc b/chrome/browser/ui/bookmarks/enhanced_bookmark_key_service.cc
index 755600b..2429324 100644
--- a/chrome/browser/ui/bookmarks/enhanced_bookmark_key_service.cc
+++ b/chrome/browser/ui/bookmarks/enhanced_bookmark_key_service.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/strings/string_number_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/api/commands/command_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/accelerator_utils.h"
@@ -49,7 +48,7 @@
   ui::Accelerator key = extensions::Command::StringToAccelerator(
       payload->accelerator, payload->command_name);
   ui::Accelerator bookmark_accelerator =
-      chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE);
+      chrome::GetPrimaryChromeAcceleratorForBookmarkPage();
   if (key == bookmark_accelerator) {
     extensions::CommandService* command_service =
         extensions::CommandService::Get(browser_context_);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 8e2c0a3..77d3df8 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1212,8 +1212,8 @@
   if (is_app() || is_devtools() || !is_type_tabbed())
     return false;
 
-  return content::OverscrollConfig::GetMode() !=
-         content::OverscrollConfig::Mode::kDisabled;
+  return content::OverscrollConfig::GetHistoryNavigationMode() !=
+         content::OverscrollConfig::HistoryNavigationMode::kDisabled;
 }
 
 bool Browser::ShouldPreserveAbortedURLs(WebContents* source) {
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 3c2d0b97..272e7ae 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1014,14 +1014,14 @@
       browser(), ui_test_utils::GetTestUrl(
                      base::FilePath(base::FilePath::kCurrentDirectory),
                      base::FilePath(kTitle1File)));
-  content::RenderProcessHost::iterator it(
-      content::RenderProcessHost::AllHostsIterator());
-  for (; !it.IsAtEnd(); it.Advance()) {
-    base::TimeDelta renderer_td =
-        it.GetCurrentValue()->GetChildProcessIdleTime();
-    base::TimeDelta browser_td = base::TimeTicks::Now() - start;
-    EXPECT_TRUE(browser_td >= renderer_td);
-  }
+  base::TimeDelta renderer_td = browser()
+                                    ->tab_strip_model()
+                                    ->GetActiveWebContents()
+                                    ->GetMainFrame()
+                                    ->GetProcess()
+                                    ->GetChildProcessIdleTime();
+  base::TimeDelta browser_td = base::TimeTicks::Now() - start;
+  EXPECT_TRUE(browser_td >= renderer_td);
 }
 
 // Test RenderView correctly send back favicon url for web page that redirects
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 3774e9d..486c663 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -186,7 +186,7 @@
   DCHECK(command);
 
   ui::Accelerator bookmark_page_accelerator =
-      chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE);
+      chrome::GetPrimaryChromeAcceleratorForBookmarkPage();
   if (bookmark_page_accelerator.key_code() == ui::VKEY_UNKNOWN)
     return false;
 
diff --git a/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm b/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm
index 294536f2..1261ded 100644
--- a/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm
+++ b/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm
@@ -6,6 +6,7 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
 #include "chrome/browser/ui/cocoa/accelerators_cocoa.h"
 #include "ui/base/accelerators/accelerator.h"
@@ -48,9 +49,10 @@
   return CommandForKeyEvent(event) != -1;
 }
 
-ui::Accelerator GetPrimaryChromeAcceleratorForCommandId(int command_id) {
+ui::Accelerator GetPrimaryChromeAcceleratorForBookmarkPage() {
   const ui::Accelerator* accelerator =
-      AcceleratorsCocoa::GetInstance()->GetAcceleratorForCommand(command_id);
+      AcceleratorsCocoa::GetInstance()->GetAcceleratorForCommand(
+          IDC_BOOKMARK_PAGE);
 
   return accelerator ? *accelerator : ui::Accelerator();
 }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
index 63259ffe..1d8dc05 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
@@ -94,8 +94,8 @@
 
   Browser* browser = chrome::FindBrowserWithWindow(self.parentWindow);
   if (SyncPromoUI::ShouldShowSyncPromo(browser->profile())) {
-    base::RecordAction(
-        base::UserMetricsAction("Signin_Impression_FromBookmarkBubble"));
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE);
 
     syncPromoController_.reset(
         [[BubbleSyncPromoController alloc]
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
index d63f754..945f2e0a 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
@@ -11,7 +11,6 @@
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/metrics/user_metrics.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_action.h"
@@ -255,8 +254,8 @@
   [self updateAnchorPosition];
 
   if (syncPromoController_) {
-    base::RecordAction(base::UserMetricsAction(
-        "Signin_Impression_FromExtensionInstallBubble"));
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE);
   }
   [super showWindow:sender];
 }
diff --git a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
index 4948b7f..e4dbfde 100644
--- a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
@@ -5,13 +5,13 @@
 #import "chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.h"
 
 #include "base/mac/scoped_nsobject.h"
-#include "base/metrics/user_metrics.h"
 #include "chrome/browser/ui/cocoa/chrome_style.h"
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 #include "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/signin/core/browser/account_info.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -101,8 +101,8 @@
   [_closeButton setFrameOrigin:closeButtonOrigin];
   [view setFrame:NSMakeRect(0, 0, kDesiredBubbleWidth, height)];
   [self setView:view];
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromPasswordBubble"));
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+      signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE);
 }
 
 - (void)onSignInClicked:(id)sender {
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
index cc26370..0f992868 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
@@ -50,8 +50,7 @@
       return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE;
     }
 
-    if (keyboard_lock_controller_.IsKeyboardLockActive() &&
-        keyboard_lock_controller_.RequiresPressAndHoldEscToExit())
+    if (keyboard_lock_controller_.RequiresPressAndHoldEscToExit())
       return EXCLUSIVE_ACCESS_BUBBLE_TYPE_KEYBOARD_LOCK_EXIT_INSTRUCTION;
 
     if (mouse_lock_controller_.IsMouseLocked())
diff --git a/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc b/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc
index a773f79..7a27e96 100644
--- a/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc
+++ b/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc
@@ -77,7 +77,10 @@
 }
 
 bool KeyboardLockController::RequiresPressAndHoldEscToExit() const {
-  return keyboard_lock_state_ == KeyboardLockState::kLockedWithEsc;
+  DCHECK_EQ(keyboard_lock_state_ == KeyboardLockState::kUnlocked,
+            exclusive_access_tab() == nullptr);
+  return IsExperimentalKeyboardLockUIEnabled() ||
+         keyboard_lock_state_ == KeyboardLockState::kLockedWithEsc;
 }
 
 void KeyboardLockController::RequestKeyboardLock(WebContents* web_contents,
@@ -101,8 +104,7 @@
   // active keyboard lock request which requires press and hold, then we just
   // return as the simple 'press esc to exit' case is handled by the caller
   // (which is the ExclusiveAccessManager in this case).
-  if (!IsExperimentalKeyboardLockUIEnabled() &&
-      !(IsKeyboardLockActive() && RequiresPressAndHoldEscToExit()))
+  if (!RequiresPressAndHoldEscToExit())
     return false;
 
   // TODO(joedow): Hook up press and hold exit animation here.
diff --git a/chrome/browser/ui/extensions/accelerator_priority.cc b/chrome/browser/ui/extensions/accelerator_priority.cc
index 3ae21d3..4d4a7f3c 100644
--- a/chrome/browser/ui/extensions/accelerator_priority.cc
+++ b/chrome/browser/ui/extensions/accelerator_priority.cc
@@ -16,8 +16,7 @@
   // Extensions overriding the bookmark shortcut need normal priority to
   // preserve the built-in processing order of the key and not override
   // WebContents key handling.
-  if (accelerator ==
-      chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE) &&
+  if (accelerator == chrome::GetPrimaryChromeAcceleratorForBookmarkPage() &&
       extensions::UIOverrides::RemovesBookmarkShortcut(extension))
     return ui::AcceleratorManager::kNormalPriority;
 
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc
index c9fdb94..c28f13c 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
 #include "net/http/http_response_headers.h"
@@ -166,6 +167,10 @@
   // testing::Test:
   void SetUp() override;
 
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory test_process_factory_;
+
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   TestingProfile profile_;
   std::unique_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
index 289f357..265d3b1c 100644
--- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -32,6 +32,7 @@
 #include "components/ukm/test_ukm_recorder.h"
 #include "components/ukm/ukm_source.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
@@ -186,6 +187,10 @@
   std::vector<std::unique_ptr<autofill::PasswordForm>> GetCurrentForms() const;
 
  private:
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory test_process_factory_;
+
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   std::unique_ptr<content::WebContents> test_web_contents_;
diff --git a/chrome/browser/ui/passwords/password_manager_porter_unittest.cc b/chrome/browser/ui/passwords/password_manager_porter_unittest.cc
index dd947b6..fe8e07e9 100644
--- a/chrome/browser/ui/passwords/password_manager_porter_unittest.cc
+++ b/chrome/browser/ui/passwords/password_manager_porter_unittest.cc
@@ -21,6 +21,7 @@
 #include "components/password_manager/core/browser/export/password_manager_exporter.h"
 #include "components/password_manager/core/browser/ui/credential_provider_interface.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -214,6 +215,10 @@
   base::FilePath selected_file_;
 
  private:
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory process_factory_;
+
   // TODO(crbug.com/689520) This is needed for mojo not to crash on destruction.
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<TestPasswordManagerPorter> password_manager_porter_;
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 9acf8c7..be49c40 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -54,6 +54,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/profile_management_switches.h"
 #include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/zoom/zoom_controller.h"
 #include "components/zoom/zoom_event_manager.h"
@@ -903,8 +904,8 @@
               error->MenuItemIcon());
       menu_items_added = true;
       if (IDC_SHOW_SIGNIN_ERROR == error->MenuItemCommandID()) {
-        base::RecordAction(
-            base::UserMetricsAction("Signin_Impression_FromMenu"));
+        signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+            signin_metrics::AccessPoint::ACCESS_POINT_MENU);
       }
     }
   }
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 417cc17..8b6eb833 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -45,10 +45,6 @@
 #include "ui/gfx/paint_vector_icon.h"
 #endif
 
-#if defined(OS_CHROMEOS)
-#include "ash/accelerators/accelerator_table.h"
-#endif
-
 namespace {
 
 // Initial comamnd ID's for navigatable (and hence executable) tab/window menu
@@ -214,26 +210,9 @@
 
   Build();
 
-  // Retrieve accelerator key for IDC_RESTORE_TAB now, because on ASH, it's not
-  // defined in |accelerator_provider|, but in shell, so simply retrieve it now
-  // for all ASH and non-ASH for use in |GetAcceleratorForCommandId|.
-#if defined(OS_CHROMEOS)
-  for (size_t i = 0; i < ash::kAcceleratorDataLength; ++i) {
-    const ash::AcceleratorData& accel_data = ash::kAcceleratorData[i];
-    if (accel_data.action == ash::RESTORE_TAB) {
-      reopen_closed_tab_accelerator_ = ui::Accelerator(accel_data.keycode,
-                                                       accel_data.modifiers);
-      break;
-    }
-  }
-#else
   if (accelerator_provider) {
     accelerator_provider->GetAcceleratorForCommandId(
         IDC_RESTORE_TAB, &reopen_closed_tab_accelerator_);
-  }
-#endif  // defined(OS_CHROMEOS)
-
-  if (accelerator_provider) {
     accelerator_provider->GetAcceleratorForCommandId(
         IDC_SHOW_HISTORY, &show_history_accelerator_);
   }
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc
index 9a67390..a3a5794 100644
--- a/chrome/browser/ui/views/accelerator_table.cc
+++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -13,10 +13,6 @@
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/events/event_constants.h"
 
-#if defined(OS_CHROMEOS)
-#include "ash/accelerators/accelerator_table.h"
-#endif
-
 namespace {
 
 // For many commands, the Mac equivalent uses Cmd instead of Ctrl. We only need
@@ -156,11 +152,6 @@
     // handled via WM_APPCOMMAND.
     {ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH},
     {ui::VKEY_M, ui::EF_SHIFT_DOWN | kPlatformModifier, IDC_SHOW_AVATAR_MENU},
-  // For each entry until the end of the !OS_CHROMEOS block, and an entry into
-  // kChromeCmdId2AshActionId below if Ash has a corresponding accelerator.
-#if !defined(OS_MACOSX)
-    {ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT},
-#endif  // !OS_MACOSX
 #endif  // !OS_CHROMEOS
 
 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_MACOSX)
@@ -249,6 +240,7 @@
     {ui::VKEY_J, ui::EF_CONTROL_DOWN, IDC_SHOW_DOWNLOADS},
     {ui::VKEY_H, ui::EF_CONTROL_DOWN, IDC_SHOW_HISTORY},
     {ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE},
+    {ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT},
 #if !defined(OS_CHROMEOS)
     // On Chrome OS, these keys are assigned to change UI scale.
     {ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
@@ -270,29 +262,6 @@
 };
 const size_t kRepeatableCommandIdsLength = arraysize(kRepeatableCommandIds);
 
-#if defined(OS_CHROMEOS)
-// Below we map Chrome command ids to Ash action ids for commands that have
-// an shortcut that is handled by Ash (instead of Chrome). Adding entries
-// here will show shortcut text on menus. See comment above.
-struct ChromeCmdId2AshActionId {
-  const int chrome_cmd_id;
-  const ash::AcceleratorAction ash_action_id;
-};
-const ChromeCmdId2AshActionId kChromeCmdId2AshActionId[] = {
-#if defined(GOOGLE_CHROME_BUILD)
-  { IDC_FEEDBACK,             ash::OPEN_FEEDBACK_PAGE },
-#endif
-  { IDC_EXIT,                 ash::EXIT },
-  { IDC_NEW_INCOGNITO_WINDOW, ash::NEW_INCOGNITO_WINDOW },
-  { IDC_NEW_TAB,              ash::NEW_TAB },
-  { IDC_NEW_WINDOW,           ash::NEW_WINDOW },
-  { IDC_RESTORE_TAB,          ash::RESTORE_TAB },
-  { IDC_TASK_MANAGER,         ash::SHOW_TASK_MANAGER },
-};
-const size_t kChromeCmdId2AshActionIdLength =
-    arraysize(kChromeCmdId2AshActionId);
-#endif  // defined(OS_CHROMEOS)
-
 } // namespace
 
 std::vector<AcceleratorMapping> GetAcceleratorList() {
@@ -302,25 +271,6 @@
   return accelerators;
 }
 
-bool GetAshAcceleratorForCommandId(int command_id,
-                                   ui::Accelerator* accelerator) {
-#if defined(OS_CHROMEOS)
-  for (size_t i = 0; i < kChromeCmdId2AshActionIdLength; ++i) {
-    if (command_id == kChromeCmdId2AshActionId[i].chrome_cmd_id) {
-      for (size_t j = 0; j < ash::kAcceleratorDataLength; ++j) {
-        if (kChromeCmdId2AshActionId[i].ash_action_id ==
-            ash::kAcceleratorData[j].action) {
-          *accelerator = ui::Accelerator(ash::kAcceleratorData[j].keycode,
-                                         ash::kAcceleratorData[j].modifiers);
-          return true;
-        }
-      }
-    }
-  }
-#endif  // defined(OS_CHROMEOS)
-  return false;
-}
-
 bool GetStandardAcceleratorForCommandId(int command_id,
                                         ui::Accelerator* accelerator) {
   // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators
diff --git a/chrome/browser/ui/views/accelerator_table_unittest.cc b/chrome/browser/ui/views/accelerator_table_unittest.cc
index b64b999b..395c974 100644
--- a/chrome/browser/ui/views/accelerator_table_unittest.cc
+++ b/chrome/browser/ui/views/accelerator_table_unittest.cc
@@ -12,7 +12,7 @@
 #include "ui/events/event_constants.h"
 
 #if defined(OS_CHROMEOS)
-#include "ash/accelerators/accelerator_table.h"
+#include "ash/public/cpp/accelerators.h"
 #endif
 
 namespace chrome {
@@ -76,7 +76,7 @@
         ash_entry.action == ash::OPEN_FEEDBACK_PAGE ||
 #endif
         ash_entry.action == ash::RESTORE_TAB ||
-        ash_entry.action == ash::NEW_TAB) {
+        ash_entry.action == ash::NEW_TAB || ash_entry.action == ash::EXIT) {
       AcceleratorMapping entry;
       entry.keycode = ash_entry.keycode;
       entry.modifiers = ash_entry.modifiers;
diff --git a/chrome/browser/ui/views/accelerator_utils_aura.cc b/chrome/browser/ui/views/accelerator_utils_aura.cc
index 230ba83..e55308e 100644
--- a/chrome/browser/ui/views/accelerator_utils_aura.cc
+++ b/chrome/browser/ui/views/accelerator_utils_aura.cc
@@ -4,12 +4,13 @@
 
 #include <stddef.h>
 
+#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/accelerator_table.h"
 #include "ui/base/accelerators/accelerator.h"
 
 #if defined(OS_CHROMEOS)
-#include "ash/accelerators/accelerator_table.h"
+#include "ash/public/cpp/accelerators.h"
 #endif
 
 namespace chrome {
@@ -35,19 +36,10 @@
   return false;
 }
 
-ui::Accelerator GetPrimaryChromeAcceleratorForCommandId(int command_id) {
-  ui::Accelerator accelerator;
-  // GetAshAcceleratorForCommandId with HOST_DESKTOP_TYPE_ASH is used so we can
-  // find Ash accelerators if Ash is supported on this platform, even if it's
-  // not currently in use.
-  if (GetStandardAcceleratorForCommandId(command_id, &accelerator) ||
-      GetAshAcceleratorForCommandId(command_id, &accelerator)) {
-    return accelerator;
-  }
-
+ui::Accelerator GetPrimaryChromeAcceleratorForBookmarkPage() {
   std::vector<AcceleratorMapping> accelerators = GetAcceleratorList();
   for (size_t i = 0; i < accelerators.size(); ++i) {
-    if (accelerators[i].command_id == command_id) {
+    if (accelerators[i].command_id == IDC_BOOKMARK_PAGE) {
       return ui::Accelerator(accelerators[i].keycode,
                              accelerators[i].modifiers);
     }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index 5373409a..074fc03 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -193,23 +193,25 @@
   if (!SyncPromoUI::ShouldShowSyncPromo(profile_))
     return nullptr;
 
-  base::RecordAction(UserMetricsAction("Signin_Impression_FromBookmarkBubble"));
-
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)) {
     footnote_view_ = new DiceBubbleSyncPromoView(
-        profile_, delegate_.get(), IDS_BOOKMARK_DICE_PROMO_SIGNIN_MESSAGE,
+        profile_, delegate_.get(),
+        signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+        IDS_BOOKMARK_DICE_PROMO_SIGNIN_MESSAGE,
         IDS_BOOKMARK_DICE_PROMO_SYNC_MESSAGE,
         false /* signin_button_prominent */);
   } else {
-    footnote_view_ =
-        new BubbleSyncPromoView(delegate_.get(), IDS_BOOKMARK_SYNC_PROMO_LINK,
-                                IDS_BOOKMARK_SYNC_PROMO_MESSAGE);
+    footnote_view_ = new BubbleSyncPromoView(
+        delegate_.get(),
+        signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+        IDS_BOOKMARK_SYNC_PROMO_LINK, IDS_BOOKMARK_SYNC_PROMO_MESSAGE);
   }
 #else
-  footnote_view_ =
-      new BubbleSyncPromoView(delegate_.get(), IDS_BOOKMARK_SYNC_PROMO_LINK,
-                              IDS_BOOKMARK_SYNC_PROMO_MESSAGE);
+  footnote_view_ = new BubbleSyncPromoView(
+      delegate_.get(),
+      signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+      IDS_BOOKMARK_SYNC_PROMO_LINK, IDS_BOOKMARK_SYNC_PROMO_MESSAGE);
 #endif
   return footnote_view_;
 }
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index dea9629..524c489 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -9,8 +9,6 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
@@ -238,23 +236,26 @@
   if (!(controller_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO))
     return nullptr;
 
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromExtensionInstallBubble"));
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   Profile* profile = browser()->profile();
   if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) {
     return new DiceBubbleSyncPromoView(
-        profile, this, IDS_EXTENSION_INSTALLED_DICE_PROMO_SIGNIN_MESSAGE,
+        profile, this,
+        signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
+        IDS_EXTENSION_INSTALLED_DICE_PROMO_SIGNIN_MESSAGE,
         IDS_EXTENSION_INSTALLED_DICE_PROMO_SYNC_MESSAGE);
   } else {
-    return new BubbleSyncPromoView(this,
-                                   IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW,
-                                   IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW);
+    return new BubbleSyncPromoView(
+        this,
+        signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
+        IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW,
+        IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW);
   }
 #else
-  return new BubbleSyncPromoView(this,
-                                 IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW,
-                                 IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW);
+  return new BubbleSyncPromoView(
+      this, signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
+      IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW,
+      IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW);
 #endif
 }
 
@@ -365,8 +366,6 @@
 
   views::BubbleDialogDelegateView::CreateBubble(bubble_view_)->Show();
   bubble_view_->GetWidget()->AddObserver(this);
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromExtensionInstallBubble"));
 }
 
 void ExtensionInstalledBubbleUi::Close() {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index b28aba0..aec56b4 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -565,8 +565,7 @@
       return true;
     }
   }
-  // Else, we retrieve the accelerator information from Ash (if applicable).
-  return GetAshAcceleratorForCommandId(cmd_id, accelerator);
+  return false;
 }
 
 bool BrowserView::IsAcceleratorRegistered(const ui::Accelerator& accelerator) {
diff --git a/chrome/browser/ui/views/passwords/password_sign_in_promo_view.cc b/chrome/browser/ui/views/passwords/password_sign_in_promo_view.cc
index 4172bb9..b2412d4 100644
--- a/chrome/browser/ui/views/passwords/password_sign_in_promo_view.cc
+++ b/chrome/browser/ui/views/passwords/password_sign_in_promo_view.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/passwords/password_sign_in_promo_view.h"
 
+#include <memory>
+
 #include "base/metrics/user_metrics.h"
 #include "build/buildflag.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
@@ -13,6 +15,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/signin_buildflags.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/layout/fill_layout.h"
@@ -40,8 +43,6 @@
     ManagePasswordsBubbleModel* model)
     : model_(model) {
   DCHECK(model_);
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromPasswordBubble"));
 
   SetLayoutManager(std::make_unique<views::FillLayout>());
   Profile* profile = model_->GetProfile();
@@ -52,12 +53,15 @@
             model_);
     AddChildView(new DiceBubbleSyncPromoView(
         profile, dice_sync_promo_delegate_.get(),
+        signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE,
         IDS_PASSWORD_MANAGER_DICE_PROMO_SIGNIN_MESSAGE,
         IDS_PASSWORD_MANAGER_DICE_PROMO_SYNC_MESSAGE));
 #else
     NOTREACHED();
 #endif
   } else {
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE);
     auto label = std::make_unique<views::Label>(
         l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SIGNIN_PROMO_LABEL),
         CONTEXT_BODY_TEXT_LARGE, STYLE_SECONDARY);
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 2c5cd73e..38346215 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -9,8 +9,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
@@ -1052,8 +1050,8 @@
                       IDS_SYNC_START_SYNC_BUTTON_LABEL,
                       l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)));
     extra_links_view->AddChildView(signin_current_profile_button_);
-    base::RecordAction(
-        base::UserMetricsAction("Signin_Impression_FromAvatarBubbleSignin"));
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN);
     extra_links_view->SetBorder(views::CreateEmptyBorder(
         0, 0,
         provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_VERTICAL_SMALL),
diff --git a/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc b/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
index 5bc6bbd..a1c8585 100644
--- a/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
+++ b/chrome/browser/ui/views/sync/bubble_sync_promo_view.cc
@@ -16,9 +16,11 @@
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/fill_layout.h"
 
-BubbleSyncPromoView::BubbleSyncPromoView(BubbleSyncPromoDelegate* delegate,
-                                         int link_text_resource_id,
-                                         int message_text_resource_id)
+BubbleSyncPromoView::BubbleSyncPromoView(
+    BubbleSyncPromoDelegate* delegate,
+    signin_metrics::AccessPoint access_point,
+    int link_text_resource_id,
+    int message_text_resource_id)
     : StyledLabel(base::string16(), this), delegate_(delegate) {
   size_t offset = 0;
   base::string16 link_text = l10n_util::GetStringUTF16(link_text_resource_id);
@@ -37,6 +39,8 @@
   gfx::Range after_link_range(offset + link_text.length(), promo_text.length());
   if (!after_link_range.is_empty())
     AddStyleRange(after_link_range, promo_style);
+
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(access_point);
 }
 
 BubbleSyncPromoView::~BubbleSyncPromoView() {}
diff --git a/chrome/browser/ui/views/sync/bubble_sync_promo_view.h b/chrome/browser/ui/views/sync/bubble_sync_promo_view.h
index d355cbf..e879b24 100644
--- a/chrome/browser/ui/views/sync/bubble_sync_promo_view.h
+++ b/chrome/browser/ui/views/sync/bubble_sync_promo_view.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/styled_label_listener.h"
 
@@ -18,6 +19,7 @@
  public:
   // |delegate| is not owned by BubbleSyncPromoView.
   BubbleSyncPromoView(BubbleSyncPromoDelegate* delegate,
+                      signin_metrics::AccessPoint access_point,
                       int link_text_resource_id,
                       int message_text_resource_id);
   ~BubbleSyncPromoView() override;
diff --git a/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc b/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
index c037a03..20afbeb 100644
--- a/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
+++ b/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
@@ -43,8 +43,9 @@
 
 TEST_F(BubbleSyncPromoViewTest, SignInLink) {
   std::unique_ptr<BubbleSyncPromoView> sync_promo;
-  sync_promo.reset(new BubbleSyncPromoView(this, IDS_BOOKMARK_SYNC_PROMO_LINK,
-                                           IDS_BOOKMARK_SYNC_PROMO_MESSAGE));
+  sync_promo.reset(new BubbleSyncPromoView(
+      this, signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+      IDS_BOOKMARK_SYNC_PROMO_LINK, IDS_BOOKMARK_SYNC_PROMO_MESSAGE));
 
   // Simulate clicking the "Sign in" link.
   views::StyledLabel styled_label(base::ASCIIToUTF16("test"), nullptr);
diff --git a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc
index e359a1b9..640f999 100644
--- a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc
+++ b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc
@@ -24,6 +24,7 @@
 DiceBubbleSyncPromoView::DiceBubbleSyncPromoView(
     Profile* profile,
     BubbleSyncPromoDelegate* delegate,
+    signin_metrics::AccessPoint access_point,
     int no_accounts_promo_message_resource_id,
     int accounts_promo_message_resource_id,
     bool signin_button_prominent)
@@ -72,6 +73,9 @@
           tracker_service->GetAccountImage(account.account_id));
     }
   }
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(access_point);
+  signin_metrics::RecordSigninImpressionWithAccountUserActionForAccessPoint(
+      access_point, !accounts.empty() /* with_account */);
   AddChildView(signin_button_view_);
 }
 
diff --git a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h
index 1cdc31a..d1ab9488 100644
--- a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h
+++ b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h"
 #include "chrome/browser/ui/views/profiles/dice_accounts_menu.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
@@ -39,6 +40,7 @@
   // prominent.
   DiceBubbleSyncPromoView(Profile* profile,
                           BubbleSyncPromoDelegate* delegate,
+                          signin_metrics::AccessPoint access_point,
                           int no_accounts_promo_message_resource_id,
                           int accounts_promo_message_resource_id,
                           bool signin_button_prominent = true);
diff --git a/chrome/browser/ui/webui/app_launcher_login_handler.cc b/chrome/browser/ui/webui/app_launcher_login_handler.cc
index 30364d9..57d7d12 100644
--- a/chrome/browser/ui/webui/app_launcher_login_handler.cc
+++ b/chrome/browser/ui/webui/app_launcher_login_handler.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -36,6 +35,7 @@
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -211,11 +211,11 @@
       sub_header = l10n_util::GetStringFUTF16(
           IDS_SYNC_PROMO_NOT_SIGNED_IN_STATUS_SUB_HEADER, signed_in_link);
 
-      base::RecordAction(
+      signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
           web_ui()->GetWebContents()->GetURL().spec() ==
                   chrome::kChromeUIAppsURL
-              ? base::UserMetricsAction("Signin_Impression_FromAppsPageLink")
-              : base::UserMetricsAction("Signin_Impression_FromNTP"));
+              ? signin_metrics::AccessPoint::ACCESS_POINT_APPS_PAGE_LINK
+              : signin_metrics::AccessPoint::ACCESS_POINT_NTP_LINK);
       // Record that the user was shown the promo.
       RecordInHistogram(NTP_SIGN_IN_PROMO_VIEWED);
     }
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
index 09476c54..90f6982 100644
--- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -30,6 +30,7 @@
 #include "components/sync/base/model_type.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_ui.h"
 #include "net/http/http_status_code.h"
@@ -152,6 +153,10 @@
     return std::move(service);
   }
 
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory test_process_factory_;
+
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<TestingProfile> profile_;
   TestSyncService* sync_service_;
diff --git a/chrome/browser/ui/webui/chromeos/DEPS b/chrome/browser/ui/webui/chromeos/DEPS
index 2bc7e71..3a2bdd04 100644
--- a/chrome/browser/ui/webui/chromeos/DEPS
+++ b/chrome/browser/ui/webui/chromeos/DEPS
@@ -13,8 +13,4 @@
     # TODO(mash): Remove. http://crbug.com/770866
     "+ash/shell.h",
   ],
-  "keyboard_overlay_ui_browsertest\.cc": [
-    # TODO(mash): Remove. http://crbug.com/770866
-    "+ash/accelerators/accelerator_table.h",
-  ],
 }
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
index 2deea081..d460b5a 100644
--- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accelerators/accelerator_table.h"
+#include "ash/public/cpp/accelerators.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
@@ -125,11 +125,21 @@
 
 using KeyboardOverlayUIBrowserTest = InProcessBrowserTest;
 
+// This test verifies two things:
+//
+// 1. That all accelerators in kAcceleratorData appear in the keyboard overlay
+// UI. This will fail when a new shortcut is added (or replaced) in
+// kAcceleratorData but not the overlay UI.
+//
+// 2. That the number of accelerators shared by the Ash table and the UI is the
+// expected value. This will fail when a new shortcut is added to
+// kAcceleratorData but not the overlay UI.
 IN_PROC_BROWSER_TEST_F(KeyboardOverlayUIBrowserTest,
                        AcceleratorsShouldHaveKeyboardOverlay) {
   content::WebContents* const web_contents = StartKeyboardOverlayUI(browser());
   const bool is_display_ui_scaling_enabled =
       IsDisplayUIScalingEnabled(web_contents);
+  int found_accelerators = 0;
   for (size_t i = 0; i < ash::kAcceleratorDataLength; ++i) {
     const ash::AcceleratorData& entry = ash::kAcceleratorData[i];
     if (ShouldSkip(entry))
@@ -143,32 +153,26 @@
       }
     }
 
-    EXPECT_TRUE(ContainsShortcut(shortcut, web_contents))
-        << "Please add the new accelerators to keyboard "
-           "overlay. Add one entry '" +
-               shortcut +
-               "' in the 'shortcut' section"
-               " at the bottom of the file of "
-               "'/chrome/browser/resources/chromeos/"
-               "keyboard_overlay_data.js'. Please keep it in "
-               "alphabetical order.";
+    if (ContainsShortcut(shortcut, web_contents)) {
+      found_accelerators++;
+    } else {
+      ADD_FAILURE() << "Please add the new accelerators to keyboard "
+                       "overlay. Add one entry '" +
+                           shortcut +
+                           "' in the 'shortcut' section"
+                           " at the bottom of the file of "
+                           "'/chrome/browser/resources/chromeos/"
+                           "keyboard_overlay_data.js'. Please keep it in "
+                           "alphabetical order.";
+    }
   }
-}
 
-IN_PROC_BROWSER_TEST_F(KeyboardOverlayUIBrowserTest,
-                       DeprecatedAcceleratorsShouldNotHaveKeyboardOverlay) {
-  content::WebContents* const web_contents = StartKeyboardOverlayUI(browser());
-  for (size_t i = 0; i < ash::kDeprecatedAcceleratorsLength; ++i) {
-    const ash::AcceleratorData& entry = ash::kDeprecatedAccelerators[i];
-    if (ShouldSkip(entry))
-      continue;
-
-    const std::string shortcut = GenerateShortcutKey(entry, web_contents);
-    EXPECT_FALSE(ContainsShortcut(shortcut, web_contents))
-        << "Please remove the deprecated accelerator '" + shortcut +
-               "' from the 'shortcut' section"
-               " at the bottom of the file of "
-               "'/chrome/browser/resources/chromeos/"
-               "keyboard_overlay_data.js'.";
-  }
+  constexpr int kExpectedFoundAccelerators = 60;
+  DCHECK_EQ(kExpectedFoundAccelerators, found_accelerators)
+      << "It seems ash::kAcceleratorData or the 'shortcut' section of "
+         "'/chrome/browser/resources/chromeos/keyboard_overlay_data.js' has "
+         "changed. Please keep the two in sync. If you've deprecated an "
+         "accelerator, remove it from keyboard_overlay_data.js. If you have "
+         "added the accelerator in both places, update "
+         "kExpectedFoundAccelerators.";
 }
diff --git a/chrome/browser/ui/webui/discards/discards.mojom b/chrome/browser/ui/webui/discards/discards.mojom
index 52932e9bb..1cf89a7c 100644
--- a/chrome/browser/ui/webui/discards/discards.mojom
+++ b/chrome/browser/ui/webui/discards/discards.mojom
@@ -4,6 +4,13 @@
 
 module mojom;
 
+// Identical to content::Visibility.
+enum LifecycleUnitVisibility {
+  HIDDEN = 0,
+  OCCLUDED = 1,
+  VISIBLE = 2,
+};
+
 // Discard related information about a single tab in a browser.
 struct TabDiscardsInfo {
   // The URL associated with the tab. This corresponds to GetLastCommittedURL,
@@ -13,6 +20,8 @@
   string favicon_url;
   // The title of the tab, as displayed on the tab itself.
   string title;
+  // The visibility of the LifecycleUnit.
+  LifecycleUnitVisibility visibility;
   // If the tab is currently using media functionality (casting, WebRTC, playing
   // audio, etc) this is true.
   bool is_media;
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc
index d7b7532b1..bcf0a16 100644
--- a/chrome/browser/ui/webui/discards/discards_ui.cc
+++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -7,7 +7,9 @@
 #include <utility>
 #include <vector>
 
+#include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/discard_reason.h"
@@ -32,6 +34,22 @@
                 : resource_coordinator::DiscardReason::kProactive;
 }
 
+mojom::LifecycleUnitVisibility GetLifecycleUnitVisibility(
+    content::Visibility visibility) {
+  switch (visibility) {
+    case content::Visibility::HIDDEN:
+      return mojom::LifecycleUnitVisibility::HIDDEN;
+    case content::Visibility::OCCLUDED:
+      return mojom::LifecycleUnitVisibility::OCCLUDED;
+    case content::Visibility::VISIBLE:
+      return mojom::LifecycleUnitVisibility::VISIBLE;
+  }
+#if defined(COMPILER_MSVC)
+  NOTREACHED();
+  return mojom::LifecycleUnitVisibility::VISIBLE;
+#endif
+}
+
 class DiscardsDetailsProviderImpl : public mojom::DiscardsDetailsProvider {
  public:
   // This instance is deleted when the supplied pipe is destroyed.
@@ -69,6 +87,8 @@
       // showing the chrome://favicon default in that case.
       info->favicon_url = lifecycle_unit->GetIconURL();
       info->title = base::UTF16ToUTF8(lifecycle_unit->GetTitle());
+      info->visibility =
+          GetLifecycleUnitVisibility(lifecycle_unit->GetVisibility());
       info->is_media = tab_lifecycle_unit_external->IsMediaTab();
       info->is_discarded = tab_lifecycle_unit_external->IsDiscarded();
       info->discard_count = tab_lifecycle_unit_external->GetDiscardCount();
diff --git a/chrome/browser/ui/webui/policy_tool_ui.cc b/chrome/browser/ui/webui/policy_tool_ui.cc
index 05974ca..83c45eb 100644
--- a/chrome/browser/ui/webui/policy_tool_ui.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui.cc
@@ -26,6 +26,7 @@
   source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET);
   source->AddLocalizedString("showExpandedValue",
                              IDS_POLICY_SHOW_EXPANDED_VALUE);
+  source->AddLocalizedString("exportLinux", IDS_EXPORT_POLICIES_LINUX);
   source->AddLocalizedString("hideExpandedValue",
                              IDS_POLICY_HIDE_EXPANDED_VALUE);
   source->AddLocalizedString("loadSession", IDS_POLICY_TOOL_LOAD_SESSION);
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
index 3f812c1f..de744a0e 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -8,6 +8,8 @@
 #include "base/path_service.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
@@ -23,6 +25,9 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
 
 namespace {
 
@@ -43,8 +48,6 @@
   ~PolicyToolUITest() override;
 
  protected:
-  // InProcessBrowserTest implementation.
-  void SetUpInProcessBrowserTestFixture() override;
   void SetUp() override;
 
   base::FilePath GetSessionsDir();
@@ -105,8 +108,6 @@
 
 PolicyToolUITest::~PolicyToolUITest() {}
 
-void PolicyToolUITest::SetUpInProcessBrowserTestFixture() {}
-
 void PolicyToolUITest::SetUp() {
   scoped_feature_list_.InitAndEnableFeature(features::kPolicyTool);
   InProcessBrowserTest::SetUp();
@@ -261,6 +262,85 @@
   return value->GetString();
 }
 
+class PolicyToolUIExportTest : public PolicyToolUITest {
+ public:
+  PolicyToolUIExportTest();
+  ~PolicyToolUIExportTest() override;
+
+ protected:
+  // InProcessBrowserTest implementation.
+  void SetUpInProcessBrowserTestFixture() override;
+
+  // The temporary directory and file path for policy saving.
+  base::ScopedTempDir export_policies_test_dir_;
+  base::FilePath export_policies_test_file_path_;
+};
+
+PolicyToolUIExportTest::PolicyToolUIExportTest() {}
+
+PolicyToolUIExportTest::~PolicyToolUIExportTest() {}
+
+void PolicyToolUIExportTest::SetUpInProcessBrowserTestFixture() {
+  ASSERT_TRUE(export_policies_test_dir_.CreateUniqueTempDir());
+  const std::string filename = "policy.json";
+  export_policies_test_file_path_ =
+      export_policies_test_dir_.GetPath().AppendASCII(filename);
+}
+
+// An artificial SelectFileDialog that immediately returns the location of test
+// file instead of showing the UI file picker.
+class TestSelectFileDialogPolicyTool : public ui::SelectFileDialog {
+ public:
+  TestSelectFileDialogPolicyTool(ui::SelectFileDialog::Listener* listener,
+                                 std::unique_ptr<ui::SelectFilePolicy> policy,
+                                 const base::FilePath& default_selected_path)
+      : ui::SelectFileDialog(listener, std::move(policy)) {
+    default_path_ = default_selected_path;
+  }
+
+  void SelectFileImpl(Type type,
+                      const base::string16& title,
+                      const base::FilePath& default_path,
+                      const FileTypeInfo* file_types,
+                      int file_type_index,
+                      const base::FilePath::StringType& default_extension,
+                      gfx::NativeWindow owning_window,
+                      void* params) override {
+    listener_->FileSelected(default_path_, /*index=*/0, /*params=*/nullptr);
+  }
+
+  bool IsRunning(gfx::NativeWindow owning_window) const override {
+    return false;
+  }
+
+  void ListenerDestroyed() override {}
+
+  bool HasMultipleFileTypeChoicesImpl() override { return false; }
+
+ private:
+  ~TestSelectFileDialogPolicyTool() override {}
+  base::FilePath default_path_;
+};
+
+// A factory associated with the artificial file picker.
+class TestSelectFileDialogFactoryPolicyTool
+    : public ui::SelectFileDialogFactory {
+ public:
+  TestSelectFileDialogFactoryPolicyTool(
+      const base::FilePath& default_selected_path) {
+    default_path_ = default_selected_path;
+  }
+
+ private:
+  base::FilePath default_path_;
+  ui::SelectFileDialog* Create(
+      ui::SelectFileDialog::Listener* listener,
+      std::unique_ptr<ui::SelectFilePolicy> policy) override {
+    return new TestSelectFileDialogPolicyTool(listener, std::move(policy),
+                                              default_path_);
+  }
+};
+
 IN_PROC_BROWSER_TEST_F(PolicyToolUITest, CreatingSessionFiles) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   // Check that the directory is not created yet.
@@ -526,3 +606,43 @@
   EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed());
   EXPECT_EQ(expected, *ExtractSessionsList());
 }
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUIExportTest, ExportSessionPolicyToLinux) {
+  CreateMultipleSessionFiles(3);
+
+  // Set SelectFileDialog to use our factory.
+  ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactoryPolicyTool(
+      export_policies_test_file_path_));
+
+  // Test if the current session policy is successfully exported.
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  std::string javascript =
+      "$('show-unset').click();"
+      "var policyEntry = document.querySelectorAll("
+      "    'section.policy-table-section > * > tbody')[0];"
+      "policyEntry.getElementsByClassName('edit-button')[0].click();"
+      "policyEntry.getElementsByClassName('value-edit-field')[0].value ="
+      "                                                           'test';"
+      "policyEntry.getElementsByClassName('save-button')[0].click();"
+      "$('export-policies-linux').click()";
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(content::ExecuteScript(contents, javascript));
+
+  // Because we created 3 session policies (with paths {0, 1, 2}), the last one
+  // is the current active session policy.
+  EXPECT_TRUE(base::ContentsEqual(export_policies_test_file_path_,
+                                  GetSessionPath(FILE_PATH_LITERAL("2"))));
+
+  // Test if after an export action, we can continue exporting.
+  std::string change_session_js =
+      "$('session-name-field').value = '1';"
+      "$('load-session-button').click();";
+
+  EXPECT_TRUE(content::ExecuteScript(contents, change_session_js + javascript));
+  base::TaskScheduler::GetInstance()->FlushForTesting();
+  EXPECT_TRUE(base::ContentsEqual(export_policies_test_file_path_,
+                                  GetSessionPath(FILE_PATH_LITERAL("1"))));
+  TestSelectFileDialogPolicyTool::SetFactory(nullptr);
+}
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.cc b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
index a62547d..c9202af 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
@@ -11,9 +11,13 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
+#include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/shell_dialogs/select_file_policy.h"
 
 namespace {
 
@@ -26,6 +30,9 @@
 const base::FilePath::CharType kPolicyToolSessionExtension[] =
     FILE_PATH_LITERAL("json");
 
+const base::FilePath::CharType kPolicyToolLinuxExtension[] =
+    FILE_PATH_LITERAL("json");
+
 // Returns the current list of all sessions sorted by last access time in
 // decreasing order.
 base::ListValue GetSessionsList(const base::FilePath& sessions_dir) {
@@ -90,6 +97,10 @@
       "deleteSession",
       base::BindRepeating(&PolicyToolUIHandler::HandleDeleteSession,
                           base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "exportLinux",
+      base::BindRepeating(&PolicyToolUIHandler::HandleExportLinux,
+                          base::Unretained(this)));
 }
 
 void PolicyToolUIHandler::OnJavascriptDisallowed() {
@@ -377,3 +388,72 @@
       base::BindOnce(&PolicyToolUIHandler::OnSessionDeleted,
                      callback_weak_ptr_factory_.GetWeakPtr()));
 }
+
+void PolicyToolUIHandler::HandleExportLinux(const base::ListValue* args) {
+  DCHECK_EQ(1U, args->GetSize());
+
+  base::JSONWriter::Write(args->GetList()[0], &session_dict_for_exporting_);
+  ExportSessionToFile(kPolicyToolLinuxExtension);
+}
+
+void DoWriteSessionPolicyToFile(const base::FilePath& path,
+                                const std::string& data) {
+  // TODO(rodmartin): Handle when WriteFile fail.
+  base::WriteFile(path, data.c_str(), data.size());
+}
+
+void PolicyToolUIHandler::WriteSessionPolicyToFile(
+    const base::FilePath& path) const {
+  const std::string data = session_dict_for_exporting_;
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskPriority::BACKGROUND,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+      base::BindOnce(&DoWriteSessionPolicyToFile, path, data));
+}
+
+void PolicyToolUIHandler::FileSelected(const base::FilePath& path,
+                                       int index,
+                                       void* params) {
+  DCHECK(export_policies_select_file_dialog_);
+  WriteSessionPolicyToFile(path);
+  session_dict_for_exporting_.clear();
+  export_policies_select_file_dialog_ = nullptr;
+}
+
+void PolicyToolUIHandler::FileSelectionCanceled(void* params) {
+  DCHECK(export_policies_select_file_dialog_);
+  session_dict_for_exporting_.clear();
+  export_policies_select_file_dialog_ = nullptr;
+}
+
+void PolicyToolUIHandler::ExportSessionToFile(
+    const base::FilePath::StringType& file_extension) {
+  // If the "select file" dialog window is already opened, we don't want to open
+  // it again.
+  if (export_policies_select_file_dialog_)
+    return;
+
+  content::WebContents* webcontents = web_ui()->GetWebContents();
+
+  // Building initial path based on download preferences.
+  base::FilePath initial_dir =
+      DownloadPrefs::FromBrowserContext(webcontents->GetBrowserContext())
+          ->DownloadPath();
+  base::FilePath initial_path =
+      initial_dir.Append(kPolicyToolDefaultSessionName)
+          .AddExtension(file_extension);
+
+  // TODO(rodmartin): Put an error message when the user is not allowed
+  // to open select file dialogs.
+  export_policies_select_file_dialog_ = ui::SelectFileDialog::Create(
+      this, std::make_unique<ChromeSelectFilePolicy>(webcontents));
+  ui::SelectFileDialog::FileTypeInfo file_type_info;
+  file_type_info.extensions = {{file_extension}};
+  gfx::NativeWindow owning_window = webcontents->GetTopLevelNativeWindow();
+  export_policies_select_file_dialog_->SelectFile(
+      ui::SelectFileDialog::SELECT_SAVEAS_FILE, /*title=*/base::string16(),
+      initial_path, &file_type_info, /*file_type_index=*/0,
+      /*default_extension=*/base::FilePath::StringType(), owning_window,
+      /*params=*/nullptr);
+}
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.h b/chrome/browser/ui/webui/policy_tool_ui_handler.h
index 16f4058..861fa0a 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.h
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.h
@@ -45,6 +45,8 @@
 
   void HandleDeleteSession(const base::ListValue* args);
 
+  void HandleExportLinux(const base::ListValue* args);
+
   void OnSessionDeleted(bool is_successful);
 
   std::string ReadOrCreateFileCallback();
@@ -67,11 +69,28 @@
 
   void SetDefaultSessionName();
 
+  // ui::SelectFileDialog::Listener implementation.
+  void FileSelected(const base::FilePath& path,
+                    int index,
+                    void* params) override;
+
+  void FileSelectionCanceled(void* params) override;
+
+  void WriteSessionPolicyToFile(const base::FilePath& path) const;
+
+  void ExportSessionToFile(const base::FilePath::StringType& file_extension);
+
   bool is_saving_enabled_ = true;
 
+  // This string is filled when an export action occurs, it contains the current
+  // session dictionary in a specific format. This format will be JSON, PLIST,
+  // or REG; depending on the kind of export.
+  std::string session_dict_for_exporting_;
   base::FilePath sessions_dir_;
   base::FilePath::StringType session_name_;
 
+  scoped_refptr<ui::SelectFileDialog> export_policies_select_file_dialog_;
+
   base::WeakPtrFactory<PolicyToolUIHandler> callback_weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PolicyToolUIHandler);
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
index 8d6019a..ea6babf 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
@@ -56,10 +56,6 @@
   Type GetType() const override { return TYPE_REGULAR; }
   AccountId GetAccountId() const override { return EmptyAccountId(); }
   void LaunchSetup() override {}
-  const base::DictionaryValue* GetPermitAccess() const override {
-    return nullptr;
-  }
-  void SetPermitAccess(const base::DictionaryValue& permit) override {}
   void ClearPermitAccess() override {}
 
   const base::ListValue* GetRemoteDevices() const override { return nullptr; }
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
index 2014f38b..33d1695 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
@@ -20,6 +20,7 @@
 #include "components/sync/user_events/fake_user_event_service.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_ui.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -196,6 +197,10 @@
   void ResetHandler() { handler_.reset(); }
 
  private:
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory process_factory_;
+
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   scoped_refptr<content::SiteInstance> site_instance_;
diff --git a/chrome/browser/ui/webui/welcome_handler.cc b/chrome/browser/ui/webui/welcome_handler.cc
index c9f907e..cf7b834 100644
--- a/chrome/browser/ui/webui/welcome_handler.cc
+++ b/chrome/browser/ui/webui/welcome_handler.cc
@@ -32,8 +32,8 @@
   // construct-time on some platforms because this page is shown immediately
   // after a new installation of Chrome and loads while the user is deciding
   // whether or not to opt in to logging.
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromStartPage"));
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+      signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE);
 
   UMA_HISTOGRAM_ENUMERATION("Welcome.SignInPromptResult", result_,
                             WelcomeResult::WELCOME_RESULT_MAX);
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc
index 5499805c..0c093b3 100644
--- a/chrome/browser/vr/elements/ui_element.cc
+++ b/chrome/browser/vr/elements/ui_element.cc
@@ -23,6 +23,7 @@
 
 namespace {
 
+constexpr bool kEnableOptimizedTreeWalks = true;
 constexpr float kHitTestResolutionInMeter = 0.000001f;
 
 int AllocateId() {
@@ -257,7 +258,7 @@
                 updated_bindings_this_frame_) &&
                was_visible_at_any_point;
 
-  if (was_visible_at_any_point ||
+  if (!kEnableOptimizedTreeWalks || was_visible_at_any_point ||
       visibility_bindings_depend_on_child_visibility_) {
     for (auto& child : children_)
       dirty |= child->DoBeginFrame(head_pose);
@@ -664,7 +665,7 @@
   should_recur |= IsOrWillBeLocallyVisible();
 
   set_update_phase(kUpdatedBindings);
-  if (!should_recur)
+  if (!should_recur && kEnableOptimizedTreeWalks)
     return;
 
   for (auto& child : children_)
@@ -768,7 +769,7 @@
 }
 
 bool UiElement::SizeAndLayOut() {
-  if (!IsVisible())
+  if (!IsVisible() && kEnableOptimizedTreeWalks)
     return false;
   bool changed = false;
   for (auto& child : children_)
@@ -890,7 +891,8 @@
 }
 
 void UiElement::UpdateWorldSpaceTransform(bool parent_changed) {
-  if (!IsVisible() && !updated_visibility_this_frame_)
+  if (!IsVisible() && !updated_visibility_this_frame_ &&
+      kEnableOptimizedTreeWalks)
     return;
 
   bool changed = false;
diff --git a/chrome/common/client_hints/client_hints.cc b/chrome/common/client_hints/client_hints.cc
index 4b98509..60fc601 100644
--- a/chrome/common/client_hints/client_hints.cc
+++ b/chrome/common/client_hints/client_hints.cc
@@ -32,9 +32,9 @@
 
     // Found an exact match.
     DCHECK(ContentSettingsPattern::Wildcard() == rule.secondary_pattern);
-    DCHECK(rule.setting_value->is_dict());
+    DCHECK(rule.setting_value.is_dict());
     const base::Value* expiration_time =
-        rule.setting_value->FindKey("expiration_time");
+        rule.setting_value.FindKey("expiration_time");
     DCHECK(expiration_time->is_double());
 
     if (base::Time::Now().ToDoubleT() > expiration_time->GetDouble()) {
@@ -42,7 +42,7 @@
       return;
     }
 
-    const base::Value* list_value = rule.setting_value->FindKey("client_hints");
+    const base::Value* list_value = rule.setting_value.FindKey("client_hints");
     DCHECK(list_value->is_list());
     const base::Value::ListStorage& client_hints_list = list_value->GetList();
     for (const auto& client_hint : client_hints_list) {
diff --git a/chrome/common/extensions/DEPS b/chrome/common/extensions/DEPS
index 505f8e9..02c7d42b 100644
--- a/chrome/common/extensions/DEPS
+++ b/chrome/common/extensions/DEPS
@@ -3,6 +3,7 @@
   "+device/usb",  # For UsbDevicePermission
   "+extensions/grit",
   "+extensions/strings/grit",
+  "+extensions/test",
   "+ppapi/c",  # For various types.
   "+skia",
 ]
diff --git a/chrome/common/extensions/api/easy_unlock_private.idl b/chrome/common/extensions/api/easy_unlock_private.idl
index a9b9deb8d..dbd920e 100644
--- a/chrome/common/extensions/api/easy_unlock_private.idl
+++ b/chrome/common/extensions/api/easy_unlock_private.idl
@@ -237,12 +237,6 @@
         UnwrapSecureMessageOptions options,
         DataCallback callback);
 
-    // Saves the permit record for the local device.
-    // |permitAccess|: The permit record to be saved.
-    // |callback|: Called to indicate success or failure.
-    static void setPermitAccess(PermitRecord permitAccess,
-                                optional EmptyCallback callback);
-
     // Gets the permit record for the local device.
     static void getPermitAccess(GetPermitAccessCallback callback);
 
diff --git a/chrome/common/extensions/chrome_manifest_handlers.cc b/chrome/common/extensions/chrome_manifest_handlers.cc
index 64965ac9..bc1b4c0 100644
--- a/chrome/common/extensions/chrome_manifest_handlers.cc
+++ b/chrome/common/extensions/chrome_manifest_handlers.cc
@@ -60,7 +60,6 @@
   (new ThemeHandler)->Register();
   (new TtsEngineManifestHandler)->Register();
   (new UIOverridesHandler)->Register();
-  (new UpdateURLHandler)->Register();
   (new UrlHandlersParser)->Register();
   (new URLOverridesHandler)->Register();
 #if defined(OS_CHROMEOS)
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 36f590c..5f41500e 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -26,6 +26,7 @@
 #include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/value_builder.h"
+#include "extensions/test/test_extension_dir.h"
 #include "net/base/mime_sniffer.h"
 #include "net/dns/mock_host_resolver.h"
 #include "skia/ext/image_operations.h"
@@ -308,31 +309,49 @@
       crx_file::id_util::IdIsValid("abcdefghijklmnopabcdefghijklmno0"));
 }
 
-
 // This test ensures that the mimetype sniffing code stays in sync with the
 // actual crx files that we test other parts of the system with.
 TEST(ExtensionTest, MimeTypeSniffing) {
-  base::FilePath path;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("extensions").AppendASCII("good.crx");
+  auto get_mime_type_from_crx = [](const base::FilePath& file_path) {
+    SCOPED_TRACE(file_path.AsUTF8Unsafe());
 
-  std::string data;
-  ASSERT_TRUE(base::ReadFileToString(path, &data));
+    std::string data;
+    EXPECT_TRUE(base::ReadFileToString(file_path, &data));
 
-  std::string result;
-  EXPECT_TRUE(net::SniffMimeType(
-      data.c_str(), data.size(), GURL("http://www.example.com/foo.crx"),
-      std::string(), net::ForceSniffFileUrlsForHtml::kDisabled, &result));
-  EXPECT_EQ(std::string(Extension::kMimeType), result);
+    std::string result;
+    EXPECT_TRUE(net::SniffMimeType(
+        data.c_str(), data.size(), GURL("http://www.example.com/foo.crx"),
+        std::string(), net::ForceSniffFileUrlsForHtml::kDisabled, &result));
 
-  data.clear();
-  result.clear();
-  path = path.DirName().AppendASCII("bad_magic.crx");
-  ASSERT_TRUE(base::ReadFileToString(path, &data));
-  EXPECT_TRUE(net::SniffMimeType(
-      data.c_str(), data.size(), GURL("http://www.example.com/foo.crx"),
-      std::string(), net::ForceSniffFileUrlsForHtml::kDisabled, &result));
-  EXPECT_EQ("application/octet-stream", result);
+    return result;
+  };
+
+  base::FilePath dir_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &dir_path));
+  dir_path = dir_path.AppendASCII("extensions");
+
+  // First, test an extension packed a long time ago (but in this galaxy).
+  // Specifically, this package is using the crx2 format, whereas modern chrome
+  // uses crx3.
+  EXPECT_EQ(Extension::kMimeType,
+            get_mime_type_from_crx(dir_path.AppendASCII("good.crx")));
+
+  // Then, an extension whose crx has a bad magic number (it should be Cr24).
+  EXPECT_EQ("application/octet-stream",
+            get_mime_type_from_crx(dir_path.AppendASCII("bad_magic.crx")));
+
+  // Finally, an extension that we pack right. This. Instant.
+  // This verifies that the modern extensions Chrome packs are always
+  // recognized as the extension mime type.
+  // Regression test for https://crbug.com/831284.
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(R"(
+      {
+        "name": "New extension",
+        "version": "0.2",
+        "manifest_version": 2
+      })");
+  EXPECT_EQ(Extension::kMimeType, get_mime_type_from_crx(test_dir.Pack()));
 }
 
 TEST(ExtensionTest, WantsFileAccess) {
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 205a1b5..1cd2e64 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1171,6 +1171,17 @@
       error_description);
 }
 
+void ChromeContentRendererClient::GetErrorDescription(
+    const blink::WebURLRequest& failed_request,
+    const blink::WebURLError& error,
+    base::string16* error_description) {
+  GetErrorDescriptionInternal(
+      failed_request,
+      error_page::Error::NetError(error.url(), error.reason(),
+                                  error.has_copy_in_cache()),
+      error_description);
+}
+
 void ChromeContentRendererClient::PrepareErrorPageInternal(
     content::RenderFrame* render_frame,
     const WebURLRequest& failed_request,
@@ -1182,6 +1193,15 @@
       failed_request.GetCacheMode() == FetchCacheMode::kBypassCache;
   NetErrorHelper::Get(render_frame)
       ->PrepareErrorPage(error, is_post, is_ignoring_cache, error_html);
+  if (error_description)
+    GetErrorDescriptionInternal(failed_request, error, error_description);
+}
+
+void ChromeContentRendererClient::GetErrorDescriptionInternal(
+    const blink::WebURLRequest& failed_request,
+    const error_page::Error& error,
+    base::string16* error_description) {
+  bool is_post = failed_request.HttpMethod().Ascii() == "POST";
   if (error_description) {
     *error_description = error_page::LocalizedError::GetErrorDetails(
         error.domain(), error.reason(), is_post);
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index d584c0b..5f9de17 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -139,6 +139,10 @@
       std::string* error_html,
       base::string16* error_description) override;
 
+  void GetErrorDescription(const blink::WebURLRequest& failed_request,
+                           const blink::WebURLError& error,
+                           base::string16* error_description) override;
+
   void DeferMediaLoad(content::RenderFrame* render_frame,
                       bool has_played_media_before,
                       const base::Closure& closure) override;
@@ -280,6 +284,10 @@
                                 std::string* error_html,
                                 base::string16* error_description);
 
+  void GetErrorDescriptionInternal(const blink::WebURLRequest& failed_request,
+                                   const error_page::Error& error,
+                                   base::string16* error_description);
+
   // Time at which this object was created. This is very close to the time at
   // which the RendererMain function was entered.
   base::TimeTicks main_entry_time_;
diff --git a/chrome/renderer/content_settings_observer_browsertest.cc b/chrome/renderer/content_settings_observer_browsertest.cc
index beadeb0..6713ba9 100644
--- a/chrome/renderer/content_settings_observer_browsertest.cc
+++ b/chrome/renderer/content_settings_observer_browsertest.cc
@@ -174,7 +174,8 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
   ContentSettingsObserver* observer = ContentSettingsObserver::Get(
       view_->GetMainRenderFrame());
@@ -252,7 +253,8 @@
       content_setting_rules.image_rules;
   image_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
 
   ContentSettingsObserver* observer = ContentSettingsObserver::Get(
@@ -269,7 +271,8 @@
       ContentSettingPatternSource(
           ContentSettingsPattern::Wildcard(),
           ContentSettingsPattern::FromString(mock_observer.image_origin()),
-          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+          base::Value::FromUniquePtrValue(
+              content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
           std::string(), false));
 
   EXPECT_CALL(mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES,
@@ -291,7 +294,8 @@
       content_setting_rules.image_rules;
   image_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -308,7 +312,8 @@
       ContentSettingPatternSource(
           ContentSettingsPattern::Wildcard(),
           ContentSettingsPattern::FromString(mock_observer.image_origin()),
-          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+          base::Value::FromUniquePtrValue(
+              content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
           std::string(), false));
   EXPECT_CALL(mock_observer,
               OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES, base::string16()));
@@ -323,7 +328,8 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -345,7 +351,8 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -370,7 +377,8 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -402,7 +410,8 @@
   script_setting_rules.clear();
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), false));
   observer->SetContentSettingRules(&content_setting_rules);
 
@@ -444,7 +453,8 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -466,14 +476,16 @@
       content_setting_rules.script_rules;
   script_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
   // Block images.
   ContentSettingsForOneType& image_setting_rules =
       content_setting_rules.image_rules;
   image_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -508,7 +520,8 @@
       content_setting_rules.autoplay_rules;
   autoplay_setting_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+      base::Value::FromUniquePtrValue(
+          content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)),
       std::string(), false));
 
   ContentSettingsObserver* observer =
@@ -524,7 +537,8 @@
       ContentSettingPatternSource(
           ContentSettingsPattern::Wildcard(),
           ContentSettingsPattern::Wildcard(),
-          content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
+          base::Value::FromUniquePtrValue(
+              content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK)),
           std::string(), false));
 
   EXPECT_FALSE(observer->AllowAutoplay(true));
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.cc b/chrome/test/chromedriver/chrome/navigation_tracker.cc
index 83af346..a85ffe6 100644
--- a/chrome/test/chromedriver/chrome/navigation_tracker.cc
+++ b/chrome/test/chromedriver/chrome/navigation_tracker.cc
@@ -240,7 +240,8 @@
     pending_frame_set_.insert(frame_id);
     loading_state_ = kLoading;
 
-    if (browser_info_->major_version >= 63) {
+    if (browser_info_->major_version >= 63 &&
+        browser_info_->major_version < 67) {
       // Check if the document is really loading.
       base::DictionaryValue params;
       params.SetString("expression", "document.readyState");
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc
index c612029..9371145 100644
--- a/chrome/test/chromedriver/element_util.cc
+++ b/chrome/test/chromedriver/element_util.cc
@@ -159,6 +159,26 @@
     middle.Offset(region.Width() / 2, region.Height() / 2);
     status = VerifyElementClickable(
         frame, web_view, clickable_element_id, middle);
+    if (status.code() == kUnknownError &&
+        status.message().find("is not clickable") != std::string::npos) {
+      // Clicking at the target location isn't reaching the target element.
+      // One possible cause is a scroll event handler has shifted the element.
+      // Try again to get the updated location of the target element.
+      status = web_view->CallFunction(
+          frame,
+          webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW),
+          args, &result);
+      if (status.IsError())
+        return status;
+      if (!ParseFromValue(result.get(), &tmp_location)) {
+        return Status(kUnknownError,
+                      "failed to parse value of GET_LOCATION_IN_VIEW");
+      }
+      middle = tmp_location;
+      middle.Offset(region.Width() / 2, region.Height() / 2);
+      status =
+          VerifyElementClickable(frame, web_view, clickable_element_id, middle);
+    }
     if (status.IsError())
       return status;
   }
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 808fc80..14cb7a9 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -85,12 +85,16 @@
 _VERSION_SPECIFIC_FILTER['66'] = [
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2304
     'ChromeDriverSiteIsolation.testCanClickOOPIF',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350
+    'ChromeDriverTest.testSlowIFrame',
 ]
 
 _VERSION_SPECIFIC_FILTER['65'] = [
     # https://bugs.chromium.org/p/chromium/issues/detail?id=803678
     'ChromeDriverTest.testGoBackAndGoForward',
     'ChromeDriverTest.testAlertHandlingOnPageUnload',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350
+    'ChromeDriverTest.testSlowIFrame',
 ]
 
 _VERSION_SPECIFIC_FILTER['64'] = [
@@ -102,6 +106,8 @@
     'ChromeExtensionsCapabilityTest.testIFrameWithExtensionsSource',
     # https://bugs.chromium.org/p/chromium/issues/detail?id=746266
     'ChromeDriverSiteIsolation.testCanClickOOPIF',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350
+    'ChromeDriverTest.testSlowIFrame',
 ]
 
 _OS_SPECIFIC_FILTER = {}
@@ -229,12 +235,16 @@
         'ChromeDriverTest.testDoesntHangOnFragmentNavigation',
         # https://bugs.chromium.org/p/chromium/issues/detail?id=746266
         'ChromeDriverSiteIsolation.testCanClickOOPIF',
+        # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350
+        'ChromeDriverTest.testSlowIFrame',
     ]
 )
 _ANDROID_NEGATIVE_FILTER['chrome_beta'] = (
     _ANDROID_NEGATIVE_FILTER['chrome'] + [
         # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2025
         'ChromeDriverTest.testDoesntHangOnFragmentNavigation',
+        # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350
+        'ChromeDriverTest.testSlowIFrame',
     ]
 )
 _ANDROID_NEGATIVE_FILTER['chromium'] = (
@@ -1642,6 +1652,47 @@
     self._driver.Load(self._http_server.GetUrl('localhost')
                       + '/chromedriver/empty.html')
 
+  def testSlowIFrame(self):
+    """Verify ChromeDriver waits for slow frames to load.
+
+    Regression test for bugs
+    https://bugs.chromium.org/p/chromedriver/issues/detail?id=2198 and
+    https://bugs.chromium.org/p/chromedriver/issues/detail?id=2350.
+    """
+    def waitAndRespond():
+      # Send iframe contents slowly
+      time.sleep(2)
+      self._sync_server.RespondWithContent('<html>IFrame contents</html>')
+
+    self._http_server.SetDataForPath('/top.html',
+        """
+        <html><body>
+        <div id='top'>
+          <input id='button' type="button" onclick="run()" value='Click'>
+        </div>
+        <script>
+        function run() {
+          var iframe = document.createElement('iframe');
+          iframe.id = 'iframe';
+          iframe.setAttribute('src', '%s');
+          document.body.appendChild(iframe);
+        }
+        </script>
+        </body></html>""" % self._sync_server.GetUrl())
+    self._driver.Load(self._http_server.GetUrl() + '/top.html')
+    thread = threading.Thread(target=waitAndRespond)
+    thread.start()
+    self._driver.FindElement('id', 'button').Click()
+    # If ChromeDriver correctly waits for slow iframe to load, then
+    # SwitchToFrame succeeds, and element with id='top' won't be found.
+    # If ChromeDriver didn't wait for iframe load, then SwitchToFrame fails,
+    # we remain in top frame, and FindElement succeeds.
+    frame = self._driver.FindElement('id', 'iframe')
+    self._driver.SwitchToFrame(frame)
+    with self.assertRaises(chromedriver.NoSuchElement):
+      self._driver.FindElement('id', 'top')
+    thread.join()
+
 
 class ChromeDriverSiteIsolation(ChromeDriverBaseTestWithWebServer):
   """Tests for ChromeDriver with the new Site Isolation Chrome feature.
diff --git a/chrome/test/data/autofill/field_changing_name_during_fill.html b/chrome/test/data/autofill/field_changing_name_during_fill.html
new file mode 100644
index 0000000..e07338438
--- /dev/null
+++ b/chrome/test/data/autofill/field_changing_name_during_fill.html
@@ -0,0 +1,36 @@
+<!-- A page that is used to test that autofilling works on site wehere. -->
+<body>
+  <form name="addr1.1" id="form1" action="https://example.com/" method="post">
+    Name: <input type="text" name="firstname" id="firstname" autocomplete="given-name"><br>
+    Country: <select name="country" id="country" onchange="CountryChanged()">
+      <option value="CA">Canada</option>
+      <option value="US">United States</option>
+    </select> <br>
+    Address: <input type="text" name="address" id="address"><br>
+    City: <input type="text" name="city" id="city"><br>
+    State: <select name="state" id="state">
+      <option value="CA">CA</option>
+      <option value="MA">MA</option>
+      <option value="TX">TX</option>
+      <option value="DC">DC</option>
+    </select> <br>
+    Zip: <input name="zip" id="zip"> <br>
+    Company: <input name="company" id="company"> <br>
+    Email: <input name="email" id="email"> <br>
+    Phone: <input name="phone" id="phone"> <br>
+    <input type="reset" value="Reset">
+    <input type="submit" value="Submit" id="profile_submit">
+  </form>
+</body>
+<script>
+function CountryChanged() {
+  document.getElementById('state').name = 'provice';
+}
+
+function hasFilled() {
+  var phone_input = document.getElementById('phone');
+  if (phone_input) {
+    window.domAutomationController.send(phone_input.value != '');
+  }
+}
+</script>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/edit_commands_no_menu/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/edit_commands_no_menu/embedder.js
index 000dc198..f26d014d 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/edit_commands_no_menu/embedder.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/edit_commands_no_menu/embedder.js
@@ -38,7 +38,11 @@
     var response = data[0];
     if (response == 'channel-created') {
       channelCreationCallback();
-      chrome.test.sendMessage('connected');
+      // Schedule the 'connected' notification to the main test so that the
+      // postMessage scheduled in channelCreationCallback() is sent first.
+      setTimeout(function () {
+        chrome.test.sendMessage('connected');
+      }, 0);
       return;
     }
     console.log('response: ' + response);
diff --git a/chrome/test/data/extensions/platform_apps/web_view/focus/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/focus/embedder.js
index a70ffa35..cc24272 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/focus/embedder.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/focus/embedder.js
@@ -640,11 +640,8 @@
   window.addEventListener('message', function(e) {
     var data = JSON.parse(e.data);
     LOG('send window.message, data: ' + data);
-    if (data[0] == 'response-seenBlurAfterFocus') {
+    if (data[0] == 'response-seenBlurAfterFocus')
       chrome.test.sendMessage('TEST_STEP_PASSED');
-    } else {
-      chrome.test.sendMessage('TEST_STEP_FAILED');
-    }
   });
 }
 
diff --git a/chrome/test/data/webui/discards/discards_browsertest.js b/chrome/test/data/webui/discards/discards_browsertest.js
index 114a987..5e1308c 100644
--- a/chrome/test/data/webui/discards/discards_browsertest.js
+++ b/chrome/test/data/webui/discards/discards_browsertest.js
@@ -20,6 +20,7 @@
   let dummy1 = {
     title: 'title 1',
     tabUrl: 'http://urlone.com',
+    visibility: 0,
     isMedia: false,
     isDiscarded: false,
     isAutoDiscardable: false,
@@ -30,6 +31,7 @@
   let dummy2 = {
     title: 'title 2',
     tabUrl: 'http://urltwo.com',
+    visibility: 1,
     isMedia: true,
     isDiscarded: true,
     isAutoDiscardable: true,
@@ -38,8 +40,9 @@
     lastActiveSeconds: 1
   };
 
-  ['title', 'tabUrl', 'isMedia', 'isDiscarded', 'isAutoDiscardable',
-      'discardCount', 'utilityRank', 'lastActiveSeconds'].forEach((sortKey) => {
+  ['title', 'tabUrl', 'visibility', 'isMedia', 'isDiscarded',
+      'isAutoDiscardable', 'discardCount', 'utilityRank', 'lastActiveSeconds']
+      .forEach((sortKey) => {
     assertTrue(
         discards.compareTabDiscardsInfos(sortKey, dummy1, dummy2) < 0);
     assertTrue(
diff --git a/chromecast/public/avsettings.h b/chromecast/public/avsettings.h
index b6eec33..6678230 100644
--- a/chromecast/public/avsettings.h
+++ b/chromecast/public/avsettings.h
@@ -197,6 +197,33 @@
   // Returns true if successful.
   virtual bool KeepSystemAwake(int time_ms) = 0;
 
+  // Sets screen (backlight) brightness.
+  // |brightness|: Range is 0.0 (off) to 1.0 (max).
+  // |smooth|: If true, will gradually change brightness in a ramp. If true and
+  // unsupported, returns false and does nothing. If false, sets brightness
+  // immediately. If another ramp is already in progress, it is cancelled and a
+  // new one is started from the current brightness of the display.
+  // If the implementation rounds to discrete values, it should round up so that
+  // non-0 |brightness| values don't turn off the display.
+  // Returns false if set fails. Returns true otherwise.
+  // Not all displays support this function.
+  static bool SetDisplayBrightness(float brightness, bool smooth)
+      __attribute__((weak));
+
+  // Gets the current screen (backlight) brightness.
+  // |brightness|: Range is 0.0 (off) to 1.0 (max).
+  // Returns false and does not modify |brightness| if get fails.
+  // Returns true and sets |brightness| to the current brightness otherwise.
+  // Not all displays support this function.
+  static bool GetDisplayBrightness(float* brightness) __attribute__((weak));
+
+  // Gets the nits output by the display at 100% brightness.
+  // |nits|: The maximum brightness in nits.
+  // Returns false and does not modify |nits| if get fails.
+  // Returns true and sets |nits| on success.
+  // Not all displays support this function.
+  static bool GetDisplayMaxBrightnessNits(float* nits) __attribute__((weak));
+
   // Returns the type of volume control, i.e. MASTER_VOLUME, FIXED_VOLUME or
   // ATTENUATION_VOLUME. For example, normal TVs, devices of CEC audio
   // controls, and audio devices are master volume systems. The counter
diff --git a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc
index e6a5ef9..5db6e13 100644
--- a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc
+++ b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -600,8 +600,8 @@
 ProximityAuthWebUIHandler::IneligibleDeviceToDictionary(
     const cryptauth::IneligibleDevice& ineligible_device) {
   std::unique_ptr<base::ListValue> ineligibility_reasons(new base::ListValue());
-  for (const std::string& reason : ineligible_device.reasons()) {
-    ineligibility_reasons->AppendString(reason);
+  for (const auto& reason : ineligible_device.reasons()) {
+    ineligibility_reasons->AppendInteger(reason);
   }
 
   std::unique_ptr<base::DictionaryValue> device_dictionary =
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index cc9ab8a..262132f3 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -834,17 +834,6 @@
   // are appended to the end of the form and are not visible.
   for (size_t i = 0; i < control_elements->size(); ++i) {
     WebFormControlElement* element = &(*control_elements)[i];
-
-    if (element->NameForAutofill().Utf16() != data.fields[i].name) {
-      // This case should be reachable only for pathological websites, which
-      // rename form fields while the user is interacting with the Autofill
-      // popup.  I (isherman) am not aware of any such websites, and so am
-      // optimistically including a NOTREACHED().  If you ever trip this check,
-      // please file a bug against me.
-      NOTREACHED();
-      continue;
-    }
-
     bool is_initiating_element = (*element == initiating_element);
 
     // Only autofill empty fields (or those with the field's default value
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 8b7eb464..59a67de 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -235,6 +235,7 @@
     "//components/pref_registry",
     "//components/prefs",
     "//components/security_state/core",
+    "//components/signin/core/browser:signin_metrics",
     "//components/strings",
     "//components/sync",
     "//components/variations/net",
diff --git a/components/autofill/core/browser/DEPS b/components/autofill/core/browser/DEPS
index e50f9cc..fa356fa 100644
--- a/components/autofill/core/browser/DEPS
+++ b/components/autofill/core/browser/DEPS
@@ -6,6 +6,12 @@
   "+components/metrics",
   "+components/policy",
   "+components/security_state",
+
+  # Autofill depends on //services/identity/public/cpp for its core Google
+  # identity dependencies, but depends on this isolated file for recording
+  # some browser-specific signin metrics.
+  "+components/signin/core/browser/signin_metrics.h",
+
   "+components/sync",
   "+components/variations",
   "+components/version_info",
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index cfeb20c..445ba1f 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -12,9 +12,6 @@
 #include "base/command_line.h"
 #include "base/i18n/case_conversion.h"
 #include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/user_metrics.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -26,6 +23,7 @@
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/common/autofill_util.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -41,7 +39,7 @@
          frontend_id == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE;
 }
 
-} // anonymous namespace
+}  // namespace
 
 AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager,
                                                    AutofillDriver* driver)
@@ -143,8 +141,8 @@
     signin_promo_suggestion.frontend_id =
         POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO;
     suggestions.push_back(signin_promo_suggestion);
-    base::RecordAction(
-        base::UserMetricsAction("Signin_Impression_FromAutofillDropdown"));
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN);
   }
 
 #if !defined(OS_ANDROID)
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index e597fc5..e774148 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -86,6 +86,16 @@
   return source_id;
 }
 
+// Reduce FormSignature space (in UKM) to a small range for privacy reasons.
+int64_t HashFormSignature(autofill::FormSignature form_signature) {
+  return static_cast<uint64_t>(form_signature) % 1021;
+}
+
+// Reduce FieldSignature space (in UKM) to a small range for privacy reasons.
+int64_t HashFieldSignature(autofill::FieldSignature field_signature) {
+  return static_cast<uint64_t>(field_signature) % 1021;
+}
+
 }  // namespace
 
 // First, translates |field_type| to the corresponding logical |group| from
@@ -1699,8 +1709,8 @@
   ukm::builders::Autofill_FieldFillStatus(source_id_)
       .SetMillisecondsSinceFormParsed(
           MillisecondsSinceFormParsed(form.form_parsed_timestamp()))
-      .SetFormSignature(static_cast<int64_t>(form.form_signature()))
-      .SetFieldSignature(static_cast<int64_t>(field.GetFieldSignature()))
+      .SetFormSignature(HashFormSignature(form.form_signature()))
+      .SetFieldSignature(HashFieldSignature(field.GetFieldSignature()))
       .SetValidationEvent(static_cast<int64_t>(metric_type))
       .SetIsAutofilled(static_cast<int64_t>(field.is_autofilled))
       .SetWasPreviouslyAutofilled(
@@ -1727,8 +1737,8 @@
   ukm::builders::Autofill_FieldTypeValidation(source_id_)
       .SetMillisecondsSinceFormParsed(
           MillisecondsSinceFormParsed(form_parsed_timestamp))
-      .SetFormSignature(static_cast<int64_t>(form_signature))
-      .SetFieldSignature(static_cast<int64_t>(field_signature))
+      .SetFormSignature(HashFormSignature(form_signature))
+      .SetFieldSignature(HashFieldSignature(field_signature))
       .SetValidationEvent(static_cast<int64_t>(metric_type))
       .SetPredictionSource(static_cast<int64_t>(prediction_source))
       .SetPredictedType(static_cast<int64_t>(predicted_type))
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index e573cf1..fab467f3 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -73,6 +73,10 @@
 using ExpectedUkmMetrics =
     std::vector<std::vector<std::pair<const char*, int64_t>>>;
 
+int64_t Collapse(uint64_t sig) {
+  return sig % 1021;
+}
+
 void VerifyDeveloperEngagementUkm(
     const ukm::TestAutoSetUkmRecorder& ukm_recorder,
     const FormData& form,
@@ -145,11 +149,10 @@
 
 void AppendFieldFillStatusUkm(const FormData& form,
                               ExpectedUkmMetrics* expected_metrics) {
-  int64_t form_signature = static_cast<int64_t>(CalculateFormSignature(form));
+  int64_t form_signature = Collapse(CalculateFormSignature(form));
   int64_t metric_type = static_cast<int64_t>(AutofillMetrics::TYPE_SUBMISSION);
   for (const FormFieldData& field : form.fields) {
-    int64_t field_signature =
-        static_cast<int64_t>(CalculateFieldSignatureForField(field));
+    int64_t field_signature = Collapse(CalculateFieldSignatureForField(field));
     expected_metrics->push_back(
         {{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
          {UkmFieldFillStatusType::kFormSignatureName, form_signature},
@@ -169,7 +172,7 @@
   ASSERT_EQ(heuristic_types.size(), form.fields.size());
   ASSERT_EQ(server_types.size(), form.fields.size());
   ASSERT_EQ(actual_types.size(), form.fields.size());
-  int64_t form_signature = static_cast<int64_t>(CalculateFormSignature(form));
+  int64_t form_signature = Collapse(CalculateFormSignature(form));
   int64_t metric_type = static_cast<int64_t>(AutofillMetrics::TYPE_SUBMISSION);
   std::vector<int64_t> prediction_sources{
       AutofillMetrics::PREDICTION_SOURCE_HEURISTIC,
@@ -177,8 +180,7 @@
       AutofillMetrics::PREDICTION_SOURCE_OVERALL};
   for (size_t i = 0; i < form.fields.size(); ++i) {
     const FormFieldData& field = form.fields[i];
-    int64_t field_signature =
-        static_cast<int64_t>(CalculateFieldSignatureForField(field));
+    int64_t field_signature = Collapse(CalculateFieldSignatureForField(field));
     for (int64_t source : prediction_sources) {
       int64_t predicted_type = static_cast<int64_t>(
           (source == AutofillMetrics::PREDICTION_SOURCE_SERVER
diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc
index 991543e4..721ab43 100644
--- a/components/content_settings/core/browser/content_settings_utils.cc
+++ b/components/content_settings/core/browser/content_settings_utils.cc
@@ -129,8 +129,9 @@
   // all origins.
   rules->image_rules.push_back(ContentSettingPatternSource(
       ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      ContentSettingToValue(CONTENT_SETTING_ALLOW), std::string(),
-      map->is_incognito()));
+      base::Value::FromUniquePtrValue(
+          ContentSettingToValue(CONTENT_SETTING_ALLOW)),
+      std::string(), map->is_incognito()));
 #endif
   map->GetSettingsForOneType(
       CONTENT_SETTINGS_TYPE_JAVASCRIPT,
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
index e25769dc..47a277e9 100644
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -697,8 +697,7 @@
   while (rule_iterator->HasNext()) {
     const content_settings::Rule& rule = rule_iterator->Next();
     settings->push_back(ContentSettingPatternSource(
-        rule.primary_pattern, rule.secondary_pattern,
-        std::make_unique<base::Value>(rule.value->Clone()),
+        rule.primary_pattern, rule.secondary_pattern, rule.value->Clone(),
         kProviderNamesSourceMap[provider_type].provider_name, incognito));
   }
 }
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
index 94d49a3..1b60d31e 100644
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -107,7 +107,7 @@
 ContentSettingPatternSource::ContentSettingPatternSource(
     const ContentSettingsPattern& primary_pattern,
     const ContentSettingsPattern& secondary_pattern,
-    std::unique_ptr<base::Value> setting_value,
+    base::Value setting_value,
     const std::string& source,
     bool incognito)
     : primary_pattern(primary_pattern),
@@ -127,8 +127,7 @@
     const ContentSettingPatternSource& other) {
   primary_pattern = other.primary_pattern;
   secondary_pattern = other.secondary_pattern;
-  if (other.setting_value)
-    setting_value = std::make_unique<base::Value>(other.setting_value->Clone());
+  setting_value = other.setting_value.Clone();
   source = other.source;
   incognito = other.incognito;
   return *this;
@@ -137,7 +136,7 @@
 ContentSettingPatternSource::~ContentSettingPatternSource() {}
 
 ContentSetting ContentSettingPatternSource::GetContentSetting() const {
-  return content_settings::ValueToContentSetting(setting_value.get());
+  return content_settings::ValueToContentSetting(&setting_value);
 }
 
 RendererContentSettingRules::RendererContentSettingRules() {}
diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h
index cf4af86..b1bb1a5 100644
--- a/components/content_settings/core/common/content_settings.h
+++ b/components/content_settings/core/common/content_settings.h
@@ -45,7 +45,7 @@
 struct ContentSettingPatternSource {
   ContentSettingPatternSource(const ContentSettingsPattern& primary_pattern,
                               const ContentSettingsPattern& secondary_patttern,
-                              std::unique_ptr<base::Value> setting_value,
+                              base::Value setting_value,
                               const std::string& source,
                               bool incognito);
   ContentSettingPatternSource(const ContentSettingPatternSource& other);
@@ -57,7 +57,7 @@
 
   ContentSettingsPattern primary_pattern;
   ContentSettingsPattern secondary_pattern;
-  std::unique_ptr<base::Value> setting_value;
+  base::Value setting_value;
   std::string source;
   bool incognito;
 };
diff --git a/components/content_settings/core/common/content_settings_struct_traits.cc b/components/content_settings/core/common/content_settings_struct_traits.cc
index f777c85..f3426dde 100644
--- a/components/content_settings/core/common/content_settings_struct_traits.cc
+++ b/components/content_settings/core/common/content_settings_struct_traits.cc
@@ -86,10 +86,9 @@
     Read(content_settings::mojom::ContentSettingPatternSourceDataView data,
          ContentSettingPatternSource* out) {
   out->incognito = data.incognito();
-  out->setting_value = std::make_unique<base::Value>();
   return data.ReadPrimaryPattern(&out->primary_pattern) &&
          data.ReadSecondaryPattern(&out->secondary_pattern) &&
-         data.ReadSettingValue(out->setting_value.get()) &&
+         data.ReadSettingValue(&out->setting_value) &&
          data.ReadSource(&out->source);
 }
 
diff --git a/components/content_settings/core/common/content_settings_struct_traits.h b/components/content_settings/core/common/content_settings_struct_traits.h
index b50a1fa..0da14fd 100644
--- a/components/content_settings/core/common/content_settings_struct_traits.h
+++ b/components/content_settings/core/common/content_settings_struct_traits.h
@@ -100,7 +100,7 @@
 
   static const base::Value& setting_value(
       const ContentSettingPatternSource& r) {
-    return *r.setting_value;
+    return r.setting_value;
   }
 
   static const std::string& source(const ContentSettingPatternSource& r) {
diff --git a/components/crash/content/browser/BUILD.gn b/components/crash/content/browser/BUILD.gn
index 9e1e4c23..64761ea 100644
--- a/components/crash/content/browser/BUILD.gn
+++ b/components/crash/content/browser/BUILD.gn
@@ -43,7 +43,7 @@
 
   # This is not in the GYP build but this target includes breakpad client
   # headers, so add the dependency here.
-  if (is_posix && !is_ios) {
+  if ((is_posix && !is_ios) || is_fuchsia) {
     configs += [ "//third_party/breakpad:client_config" ]
     public_configs = [ "//third_party/breakpad:client_config" ]
   }
diff --git a/components/cryptauth/cryptauth_client_impl_unittest.cc b/components/cryptauth/cryptauth_client_impl_unittest.cc
index bcf4be2..960278d 100644
--- a/components/cryptauth/cryptauth_client_impl_unittest.cc
+++ b/components/cryptauth/cryptauth_client_impl_unittest.cc
@@ -238,7 +238,8 @@
   response_proto.add_eligible_devices();
   response_proto.mutable_eligible_devices(0)->set_public_key(kPublicKey1);
 
-  const std::string kIneligibilityReason = "You require more vespine gas.";
+  const cryptauth::IneligibilityReason kIneligibilityReason =
+      cryptauth::IneligibilityReason::UNKNOWN_INELIGIBILITY_REASON;
   response_proto.add_ineligible_devices();
   response_proto.mutable_ineligible_devices(0)
       ->mutable_device()
diff --git a/components/cryptauth/proto/cryptauth_api.proto b/components/cryptauth/proto/cryptauth_api.proto
index 5672f239..5aebfb3 100644
--- a/components/cryptauth/proto/cryptauth_api.proto
+++ b/components/cryptauth/proto/cryptauth_api.proto
@@ -36,6 +36,19 @@
   BROWSER = 4;
 }
 
+// MultiDevice features which may be supported and enabled on a device.
+enum SoftwareFeature {
+  UNKNOWN_FEATURE = 0;
+  BETTER_TOGETHER_HOST = 1;
+  BETTER_TOGETHER_CLIENT = 2;
+  EASY_UNLOCK_HOST = 3;
+  EASY_UNLOCK_CLIENT = 4;
+  MAGIC_TETHER_HOST = 5;
+  MAGIC_TETHER_CLIENT = 6;
+  SMS_CONNECT_HOST = 7;
+  SMS_CONNECT_CLIENT = 8;
+}
+
 // A seed used to feed an EID BLE advertisement for some time period. This
 // key is specific to the device being targeted by the advertisement.
 // Next ID: 4
@@ -87,6 +100,13 @@
 
   // Whether this is a "Pixel Experience" phone.
   optional bool pixel_phone = 11 [default = false];
+
+  // A list of multi-device software features supported by the device.
+  repeated SoftwareFeature supported_software_features = 12;
+
+  // A list of multi-device software features currently enabled (active) on the
+  // device.
+  repeated SoftwareFeature enabled_software_features = 13;
 }
 
 // Determine if the calling device is allowed to promote the SmartLock
@@ -136,6 +156,14 @@
 
   // Information about the requesting device and its platform.
   optional DeviceClassifier device_classifier = 6;
+
+  // The version of the setup protocol that the calling device expects to use.
+  optional int32 protocol_version = 7;
+
+  // The feature for which eligibility should be checked. Note that this RPC is
+  // overloaded instead of adding new RPCs due to the ongoing V2 transition.
+  // See go/unified-better-together-cryptauth for more details.
+  optional SoftwareFeature feature = 8 [default = EASY_UNLOCK_HOST];
 }
 
 // Response containing a list of devices that could be made Unlock Keys
@@ -267,7 +295,7 @@
   // Fields corresponding to screenlock type/features and hardware features
   // should be numbered in the 400 range.
 
-  // Is this device using  a secure screenlock (e.g., pattern or pin unlock).
+  // Is this device using  a secure screenlock (e.g., pattern or pin unlock)
   optional bool using_secure_screenlock = 400 [default = false];
 
   // Is auto-unlocking the screenlock (e.g., when at "home") supported?
@@ -282,10 +310,37 @@
   // Is the Bluetooth (classic) radio on?
   optional bool bluetooth_radio_enabled = 404 [default = false];
 
-  // The enrollment session id this is sent with.
+  // Does the device hardware support a mobile data connection?
+  optional bool mobile_data_supported = 405 [default = false];
+
+  // Does the device support tethering?
+  optional bool tethering_supported = 406 [default = false];
+
+  // Does the device have a BLE radio?
+  optional bool ble_radio_supported = 407 [default = false];
+
+  // Is the device a "Pixel Experience" Android device?
+  optional bool pixel_experience = 408 [default = false];
+
+  // Is the device running in the ARC++ container on a chromebook?
+  optional bool arc_plus_plus = 409 [default = false];
+
+  // Is the value set in |using_secure_screenlock| reliable? On some Android
+  // devices, the platform API to get the screenlock state is not trustworthy.
+  // See b/32212161.
+  optional bool is_screenlock_state_flaky = 410 [default = false];
+
+  // A list of multi-device software features supported by the device.
+  repeated SoftwareFeature supported_software_features = 411;
+
+  // A list of multi-device software features currently enabled (active) on the
+  // device.
+  repeated SoftwareFeature enabled_software_features = 412;
+
+  // The enrollment session id this is sent with
   optional bytes enrollment_session_id = 1000;
 
-  // A copy of the user's OAuth token.
+  // A copy of the user's OAuth token
   optional string oauth_token = 1001;
 }
 
@@ -319,18 +374,53 @@
   repeated ExternalDeviceInfo devices = 1;
 }
 
+// Reasons why the server thinks a certain device is not eligible to be an
+// EasyUnlock key.
+enum IneligibilityReason {
+  UNKNOWN_INELIGIBILITY_REASON = 0;
+
+  // The screen is larger than 6.9 inches (which most likely means this is
+  // a tablet).
+  SCREEN_TOO_LARGE = 1;
+
+  // The device has reported that it does not support bluetooth.
+  BLUETOOTH_NOT_SUPPORTED = 2;
+
+  // The devices last known credentials are no longer valid.
+  INVALID_CREDENTIALS = 3;
+
+  // The device has reported that it does not support auto-unlocking.
+  AUTO_UNLOCKING_NOT_SUPPORTED = 4;
+
+  // We think the device is offline.
+  DEVICE_OFFLINE = 5;
+
+  // The database entry for this device was not updated in the last
+  // max_last_update_time_delta_millis (see FindEligibleUnlockDevicesRequest).
+  NO_RECENT_UPDATES = 6;
+
+  // Operating system version is not accepted.
+  BAD_OS_VERSION = 7;
+
+  // SmartLock client software version is not accepted.
+  BAD_DEVICE_SOFTWARE_VERSION = 8;
+
+  // Feature is not in supported_software_features for this device.
+  FEATURE_UNSUPPORTED = 9;
+}
+
 // A device that the server thinks is not eligible to be an unlock key, and the
 // reason for this.
 message IneligibleDevice {
   // The device that is not eligible to be an unlock key.
   optional ExternalDeviceInfo device = 1;
 
-  // The reasons why the server thinks it is not an unlock key. NOTE: for now,
-  // this list of reasons will contain exactly one element. It is a repeated
-  // field because, in principle, there can be more than one reason that makes a
-  // device not eligible to be an unlock key, and we want to be able to add
-  // multiple reasons in the future.
-  repeated string reasons = 2;
+  // The reasons why the server thinks it is not an unlock key.
+  // NOTE: for now, this list of reasons will contain exactly one element.
+  // It is a repeated field because, in principle, there can be more than
+  // one reason that makes a device not eligible to be an unlock key,
+  // and we want to be able to add multiple reasons in the future.
+  repeated IneligibilityReason reasons = 2;
 }
 
 // A list of "reasons" that can be provided for calling server-side APIs.
@@ -512,6 +602,15 @@
 
   // Information about the requesting device and its platform.
   optional DeviceClassifier device_classifier = 4;
+
+  // The feature for which enabled state should be toggled. Note that this RPC
+  // is overloaded instead of adding new RPCs due to the ongoing V2 transition.
+  // See go/unified-better-together-cryptauth for more details.
+  optional SoftwareFeature feature = 5 [default = EASY_UNLOCK_HOST];
+
+  // True if enabling one device for this feature should disable all others on
+  // the account.
+  optional bool is_exclusive = 6 [default = true];
 }
 
 message ToggleEasyUnlockResponse {
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index cc3c98b..88f8092 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -177,6 +177,7 @@
     "//services/network/public/cpp",
     "//services/network/public/mojom",
     "//third_party/icu/",
+    "//third_party/protobuf:protobuf_lite",
     "//ui/gfx",
   ]
 }
@@ -245,6 +246,7 @@
   }
 
   deps = [
+    ":explore_protos",
     ":ntp_snippets",
     ":test_support",
     "//base",
diff --git a/components/ntp_snippets/DEPS b/components/ntp_snippets/DEPS
index 3834fe61..33dd6c9 100644
--- a/components/ntp_snippets/DEPS
+++ b/components/ntp_snippets/DEPS
@@ -31,6 +31,7 @@
   "+services/network/public/cpp",
   "+services/network/public/mojom",
   "+services/network/test",
+  "+third_party/protobuf",
   "+ui/base",
   "+ui/gfx",
 ]
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
index 07d1b1b..280ed4a 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
@@ -15,12 +15,13 @@
 #include "components/ntp_snippets/remote/cached_image_fetcher.h"
 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
+#include "contextual_content_suggestions_service_proxy.h"
 #include "ui/gfx/image/image.h"
 
 namespace ntp_snippets {
 
-using contextual_suggestions::ContextualSuggestionsMetricsReporter;
 using contextual_suggestions::Cluster;
+using contextual_suggestions::ContextualSuggestionsMetricsReporterProvider;
 using contextual_suggestions::FetchClustersCallback;
 
 ContextualContentSuggestionsService::ContextualContentSuggestionsService(
@@ -28,23 +29,18 @@
         contextual_suggestions_fetcher,
     std::unique_ptr<CachedImageFetcher> image_fetcher,
     std::unique_ptr<RemoteSuggestionsDatabase> contextual_suggestions_database,
-    std::unique_ptr<ContextualSuggestionsMetricsReporter> metrics_reporter)
+    std::unique_ptr<ContextualSuggestionsMetricsReporterProvider>
+        metrics_reporter_provider)
     : contextual_suggestions_database_(
           std::move(contextual_suggestions_database)),
       contextual_suggestions_fetcher_(
           std::move(contextual_suggestions_fetcher)),
       image_fetcher_(std::move(image_fetcher)),
-      metrics_reporter_(std::move(metrics_reporter)),
-      last_ukm_source_id_(ukm::kInvalidSourceId) {}
+      metrics_reporter_provider_(std::move(metrics_reporter_provider)) {}
 
 ContextualContentSuggestionsService::~ContextualContentSuggestionsService() =
     default;
 
-// TODO(pnoland): remove this
-void ContextualContentSuggestionsService::FetchContextualSuggestions(
-    const GURL& url,
-    FetchContextualSuggestionsCallback callback) {}
-
 void ContextualContentSuggestionsService::FetchContextualSuggestionClusters(
     const GURL& url,
     FetchClustersCallback callback) {
@@ -77,26 +73,13 @@
   FetchContextualSuggestionImage(suggestion_id, image_url, std::move(callback));
 }
 
-void ContextualContentSuggestionsService::ReportEvent(
-    ukm::SourceId ukm_source_id,
-    contextual_suggestions::ContextualSuggestionsEvent event) {
-  DCHECK(ukm_source_id != ukm::kInvalidSourceId);
-
-  // Flush the previous page (if any) and setup the new page.
-  if (ukm_source_id != last_ukm_source_id_) {
-    if (last_ukm_source_id_ != ukm::kInvalidSourceId)
-      metrics_reporter_->Flush();
-    last_ukm_source_id_ = ukm_source_id;
-    metrics_reporter_->SetupForPage(ukm_source_id);
-  }
-
-  metrics_reporter_->RecordEvent(event);
+std::unique_ptr<
+    contextual_suggestions::ContextualContentSuggestionsServiceProxy>
+ContextualContentSuggestionsService::CreateProxy() {
+  return std::make_unique<
+      contextual_suggestions::ContextualContentSuggestionsServiceProxy>(
+      this, metrics_reporter_provider_->CreateMetricsReporter());
 }
 
-void ContextualContentSuggestionsService::Shutdown() {
-  if (last_ukm_source_id_ != ukm::kInvalidSourceId)
-    metrics_reporter_->Flush();
-  last_ukm_source_id_ = ukm::kInvalidSourceId;
-}
 
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
index ae2c849..df47ac4 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
@@ -20,6 +20,10 @@
 #include "components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 
+namespace contextual_suggestions {
+class ContextualContentSuggestionsServiceProxy;
+}
+
 namespace ntp_snippets {
 
 using contextual_suggestions::Cluster;
@@ -32,7 +36,6 @@
 // for contextual suggestion, using caching.
 class ContextualContentSuggestionsService : public KeyedService {
  public:
-
   ContextualContentSuggestionsService(
       std::unique_ptr<ContextualSuggestionsFetcher>
           contextual_suggestions_fetcher,
@@ -40,20 +43,10 @@
       std::unique_ptr<RemoteSuggestionsDatabase>
           contextual_suggestions_database,
       std::unique_ptr<
-          contextual_suggestions::ContextualSuggestionsMetricsReporter>
-          metrics_reporter);
+          contextual_suggestions::ContextualSuggestionsMetricsReporterProvider>
+          metrics_reporter_provider);
   ~ContextualContentSuggestionsService() override;
 
-  using FetchContextualSuggestionsCallback =
-      base::OnceCallback<void(Status status_code,
-                              const GURL& url,
-                              std::vector<ContentSuggestion> suggestions)>;
-
-  // Asynchronously fetches contextual suggestions for the given URL.
-  virtual void FetchContextualSuggestions(
-      const GURL& url,
-      FetchContextualSuggestionsCallback callback);
-
   // Asynchronously fetches contextual suggestions for the given URL.
   virtual void FetchContextualSuggestionClusters(
       const GURL& url,
@@ -72,13 +65,9 @@
       const ContentSuggestion::ID& suggestion_id,
       ImageFetchedCallback callback);
 
-  // Used to report events using various metrics (e.g. UMA, UKM).
-  virtual void ReportEvent(
-      ukm::SourceId sourceId,
-      contextual_suggestions::ContextualSuggestionsEvent event);
-
-  // KeyedService overrides.
-  void Shutdown() override;
+  std::unique_ptr<
+      contextual_suggestions::ContextualContentSuggestionsServiceProxy>
+  CreateProxy();
 
  private:
   // Cache for images of contextual suggestions, needed by CachedImageFetcher.
@@ -89,12 +78,9 @@
 
   std::unique_ptr<CachedImageFetcher> image_fetcher_;
 
-  std::unique_ptr<contextual_suggestions::ContextualSuggestionsMetricsReporter>
-      metrics_reporter_;
-
-  // The most recent SourceId in use by metrics_reporter_, or
-  // ukm::kInvalidSourceId.
-  ukm::SourceId last_ukm_source_id_;
+  std::unique_ptr<
+      contextual_suggestions::ContextualSuggestionsMetricsReporterProvider>
+      metrics_reporter_provider_;
 
   // Look up by ContentSuggestion::ID::id_within_category() aka std::string to
   // get image URL.
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc
index 7c45128..e461c3b 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc
@@ -26,8 +26,12 @@
 
 ContextualContentSuggestionsServiceProxy::
     ContextualContentSuggestionsServiceProxy(
-        ntp_snippets::ContextualContentSuggestionsService* service)
-    : service_(service), weak_ptr_factory_(this) {}
+        ntp_snippets::ContextualContentSuggestionsService* service,
+        std::unique_ptr<ContextualSuggestionsMetricsReporter> metrics_reporter)
+    : service_(service),
+      metrics_reporter_(std::move(metrics_reporter)),
+      last_ukm_source_id_(ukm::kInvalidSourceId),
+      weak_ptr_factory_(this) {}
 
 ContextualContentSuggestionsServiceProxy::
     ~ContextualContentSuggestionsServiceProxy() {}
@@ -81,7 +85,23 @@
 void ContextualContentSuggestionsServiceProxy::ReportEvent(
     ukm::SourceId ukm_source_id,
     ContextualSuggestionsEvent event) {
-  service_->ReportEvent(ukm_source_id, event);
+  DCHECK(ukm_source_id != ukm::kInvalidSourceId);
+
+  // Flush the previous page (if any) and setup the new page.
+  if (ukm_source_id != last_ukm_source_id_) {
+    if (last_ukm_source_id_ != ukm::kInvalidSourceId)
+      metrics_reporter_->Flush();
+    last_ukm_source_id_ = ukm_source_id;
+    metrics_reporter_->SetupForPage(ukm_source_id);
+  }
+
+  metrics_reporter_->RecordEvent(event);
+}
+
+void ContextualContentSuggestionsServiceProxy::FlushMetrics() {
+  if (last_ukm_source_id_ != ukm::kInvalidSourceId)
+    metrics_reporter_->Flush();
+  last_ukm_source_id_ = ukm::kInvalidSourceId;
 }
 
 void ContextualContentSuggestionsServiceProxy::CacheSuggestions(
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h
index 6a788eb..cc3b2fe 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h
@@ -28,8 +28,9 @@
   using ClustersCallback = ntp_snippets::FetchClustersCallback;
   using Cluster = ntp_snippets::Cluster;
 
-  explicit ContextualContentSuggestionsServiceProxy(
-      ntp_snippets::ContextualContentSuggestionsService* service);
+  ContextualContentSuggestionsServiceProxy(
+      ntp_snippets::ContextualContentSuggestionsService* service,
+      std::unique_ptr<ContextualSuggestionsMetricsReporter> metrics_reporter);
   ~ContextualContentSuggestionsServiceProxy();
 
   // Fetches contextual suggestions for a given |url|.
@@ -53,6 +54,9 @@
   // Reports user interface event to the service.
   void ReportEvent(ukm::SourceId, ContextualSuggestionsEvent event);
 
+  // Ensures that all metrics are properly flushed.
+  void FlushMetrics();
+
  private:
   void CacheSuggestions(ClustersCallback callback,
                         std::string peek_text,
@@ -62,6 +66,14 @@
   // Cache of contextual suggestions.
   std::map<std::string, ntp_snippets::ContextualSuggestion> suggestions_;
 
+  // Sink for reporting metrics for this proxy.
+  std::unique_ptr<contextual_suggestions::ContextualSuggestionsMetricsReporter>
+      metrics_reporter_;
+
+  // The most recent SourceId in use by metrics_reporter_, or
+  // ukm::kInvalidSourceId.
+  ukm::SourceId last_ukm_source_id_;
+
   // Weak pointer factory to cancel pending callbacks.
   base::WeakPtrFactory<ContextualContentSuggestionsServiceProxy>
       weak_ptr_factory_;
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc
index a5e171b..580c8df7 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h"
 #include "components/ntp_snippets/remote/cached_image_fetcher.h"
 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -91,8 +92,10 @@
 
 void ContextualContentSuggestionsServiceProxyTest::SetUp() {
   service_ = std::make_unique<FakeContextualContentSuggestionsService>();
+  auto metrics_reporter =
+      std::make_unique<ContextualSuggestionsMetricsReporter>();
   proxy_ = std::make_unique<ContextualContentSuggestionsServiceProxy>(
-      service_.get());
+      service_.get(), std::move(metrics_reporter));
 }
 
 TEST_F(ContextualContentSuggestionsServiceProxyTest,
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
index e2b8c4bf..8b958c3 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
@@ -29,6 +29,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
+using contextual_suggestions::ClusterBuilder;
 using testing::_;
 using testing::AllOf;
 using testing::ElementsAre;
@@ -41,12 +42,36 @@
 
 namespace {
 
-// TODO(pnoland): Re-implement for new fetcher.
+class MockClustersCallback {
+ public:
+  void Done(std::string peek_text, std::vector<Cluster> clusters) {
+    EXPECT_FALSE(has_run);
+    has_run = true;
+    response_peek_text = peek_text;
+    response_clusters = std::move(clusters);
+  }
+
+  bool has_run = false;
+  std::string response_peek_text;
+  std::vector<Cluster> response_clusters;
+};
+
+// Always fetches the result that was set by SetFakeResponse.
 class FakeContextualSuggestionsFetcher : public ContextualSuggestionsFetcher {
  public:
   void FetchContextualSuggestionsClusters(
       const GURL& url,
-      FetchClustersCallback callback) override {}
+      FetchClustersCallback callback) override {
+    std::move(callback).Run("peek text", std::move(fake_suggestions_));
+    fake_suggestions_.clear();
+  }
+
+  void SetFakeResponse(std::vector<Cluster> fake_suggestions) {
+    fake_suggestions_ = std::move(fake_suggestions);
+  }
+
+ private:
+  std::vector<Cluster> fake_suggestions_;
 };
 
 // Always fetches a fake image if the given URL is valid.
@@ -78,13 +103,13 @@
     std::unique_ptr<FakeContextualSuggestionsFetcher> fetcher =
         std::make_unique<FakeContextualSuggestionsFetcher>();
     fetcher_ = fetcher.get();
-    auto metrics_reporter = std::make_unique<
-        contextual_suggestions::ContextualSuggestionsMetricsReporter>();
+    auto metrics_reporter_provider = std::make_unique<
+        contextual_suggestions::ContextualSuggestionsMetricsReporterProvider>();
     source_ = std::make_unique<ContextualContentSuggestionsService>(
         std::move(fetcher),
         std::make_unique<FakeCachedImageFetcher>(&pref_service_),
         std::unique_ptr<RemoteSuggestionsDatabase>(),
-        std::move(metrics_reporter));
+        std::move(metrics_reporter_provider));
   }
 
   FakeContextualSuggestionsFetcher* fetcher() { return fetcher_; }
@@ -115,4 +140,28 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(ContextualContentSuggestionsServiceTest,
+       ShouldFetchContextualSuggestionsClusters) {
+  MockClustersCallback mock_callback;
+  std::vector<Cluster> clusters;
+  GURL context_url("http://www.from.url");
+
+  clusters.emplace_back(ClusterBuilder("Title")
+                            .AddSuggestion(SuggestionBuilder(context_url)
+                                               .Title("Title1")
+                                               .PublisherName("from.url")
+                                               .Snippet("Summary")
+                                               .ImageId("abc")
+                                               .Build())
+                            .Build());
+
+  fetcher()->SetFakeResponse(std::move(clusters));
+  source()->FetchContextualSuggestionClusters(
+      context_url, base::BindOnce(&MockClustersCallback::Done,
+                                  base::Unretained(&mock_callback)));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(mock_callback.has_run);
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc b/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
index 0186f278..401652e7 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
@@ -16,8 +16,12 @@
 #include "components/ntp_snippets/contextual/proto/get_pivots_response.pb.h"
 #include "components/variations/net/variations_http_headers.h"
 #include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
+
+using base::Base64Encode;
 
 namespace contextual_suggestions {
 
@@ -25,8 +29,92 @@
 
 static constexpr char kFetchEndpoint[] =
     "https://www.google.com/httpservice/web/ExploreService/GetPivots/";
+
+static constexpr int kNumberOfSuggestionsToFetch = 10;
+static constexpr int kMinNumberOfClusters = 1;
+static constexpr int kMaxNumberOfClusters = 5;
+
+ContextualSuggestion ItemToSuggestion(const PivotItem& item) {
+  PivotDocument document = item.document();
+
+  return SuggestionBuilder(GURL(document.url().raw_url()))
+      .Title(document.title())
+      .Snippet(document.summary())
+      .PublisherName(document.site_name())
+      .ImageId(document.image().id().encrypted_docid())
+      .FaviconImageId(document.favicon_image().id().encrypted_docid())
+      .Build();
 }
 
+Cluster PivotToCluster(const PivotCluster& pivot) {
+  ClusterBuilder cluster_builder(pivot.label().label());
+  for (PivotItem item : pivot.item()) {
+    cluster_builder.AddSuggestion(ItemToSuggestion(item));
+  }
+
+  return cluster_builder.Build();
+}
+
+std::vector<Cluster> ClustersFromResponse(
+    const GetPivotsResponse& response_proto) {
+  std::vector<Cluster> clusters;
+  Pivots pivots = response_proto.pivots();
+
+  if (pivots.item_size() > 0) {
+    // If the first item is a cluster, we can assume they all are.
+    if (pivots.item()[0].has_cluster()) {
+      clusters.reserve(response_proto.pivots().item_size());
+      for (auto item : response_proto.pivots().item()) {
+        if (item.has_cluster()) {
+          PivotCluster pivot_cluster = item.cluster();
+          clusters.emplace_back(PivotToCluster(pivot_cluster));
+        }
+      }
+    } else if (pivots.item()[0].has_document()) {
+      Cluster single_cluster;
+      for (auto item : pivots.item()) {
+        single_cluster.suggestions.emplace_back(ItemToSuggestion(item));
+      }
+      clusters.emplace_back(std::move(single_cluster));
+    }
+  }
+
+  return clusters;
+}
+
+std::string PeekTextFromResponse(const GetPivotsResponse& response_proto) {
+  return response_proto.pivots().peek_text().text();
+}
+
+const std::string SerializedPivotsRequest(const std::string& url,
+                                          const std::string& bcp_language) {
+  GetPivotsRequest pivot_request;
+
+  SearchApiRequestContext* search_context = pivot_request.mutable_context();
+  search_context->mutable_localization_context()->set_spoken_language(
+      bcp_language);
+
+  GetPivotsQuery* query = pivot_request.mutable_query();
+  query->add_context()->set_url(url);
+
+  PivotDocumentParams* params = query->mutable_document_params();
+  params->set_enabled(true);
+  params->set_num(kNumberOfSuggestionsToFetch);
+  params->set_enable_images(true);
+  params->set_image_aspect_ratio(PivotDocumentParams::SQUARE);
+
+  PivotClusteringParams* cluster_params = query->mutable_clustering_params();
+  cluster_params->set_enabled(true);
+  cluster_params->set_min(kMinNumberOfClusters);
+  cluster_params->set_max(kMaxNumberOfClusters);
+
+  query->mutable_peek_text_params()->set_enabled(true);
+
+  return pivot_request.SerializeAsString();
+}
+
+}  // namespace
+
 ContextualSuggestionsFetch::ContextualSuggestionsFetch(
     const GURL& url,
     const std::string& bcp_language_code)
@@ -41,18 +129,117 @@
 
 void ContextualSuggestionsFetch::Start(
     FetchClustersCallback callback,
-    const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory) {}
+    const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory) {
+  request_completed_callback_ = std::move(callback);
+  url_loader_ = MakeURLLoader();
+  url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+      loader_factory.get(),
+      base::BindOnce(&ContextualSuggestionsFetch::OnURLLoaderComplete,
+                     base::Unretained(this)));
+}
 
 std::unique_ptr<network::SimpleURLLoader>
 ContextualSuggestionsFetch::MakeURLLoader() const {
-  return nullptr;
+  // TODO(pnoland, https://crbug.com/831693): Update this once there's an
+  // opt-out setting.
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("ntp_contextual_suggestions_fetch",
+                                          R"(
+        semantics {
+          sender: "Contextual Suggestions Fetch"
+          description:
+            "Chromium can show contextual suggestions that are related to the "
+            "currently visited page."
+          trigger:
+            "Triggered when a page is visited and stayed on for more than a "
+            "few seconds."
+          data:
+            "The URL of the current tab and the ui language."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "This feature can be disabled by the flag "
+            "enable-contextual-suggestions-bottom-sheet."
+          policy_exception_justification: "Not implemented. The feature is "
+          "currently Android-only and disabled for all enterprise users. "
+          "A policy will be added before enabling for enterprise users."
+        })");
+
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+
+  resource_request->url = GURL(GetFetchEndpoint());
+  // TODO(pnoland): include cookies once the suggestions endpoint can make use
+  // of them.
+  resource_request->load_flags =
+      net::LOAD_BYPASS_CACHE | net::LOAD_DO_NOT_SAVE_COOKIES |
+      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
+  resource_request->headers = MakeHeaders();
+  resource_request->method = "GET";
+
+  auto simple_loader = network::SimpleURLLoader::Create(
+      std::move(resource_request), traffic_annotation);
+  simple_loader->SetAllowHttpErrorResults(true);
+  return simple_loader;
 }
 
 net::HttpRequestHeaders ContextualSuggestionsFetch::MakeHeaders() const {
-  return net::HttpRequestHeaders();
+  net::HttpRequestHeaders headers;
+  std::string serialized_request_body =
+      SerializedPivotsRequest(url_.spec(), bcp_language_code_);
+  std::string base64_encoded_body;
+  base::Base64UrlEncode(serialized_request_body,
+                        base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+                        &base64_encoded_body);
+  headers.SetHeader("X-Protobuffer-Request-Payload", base64_encoded_body);
+  variations::AppendVariationHeaders(url_, variations::InIncognito::kNo,
+                                     variations::SignedIn::kNo, &headers);
+
+  UMA_HISTOGRAM_COUNTS_1M(
+      "ContextualSuggestions.FetchRequestProtoSizeKB",
+      static_cast<int>(base64_encoded_body.length() / 1024));
+
+  return headers;
 }
 
 void ContextualSuggestionsFetch::OnURLLoaderComplete(
-    std::unique_ptr<std::string> result) {}
+    std::unique_ptr<std::string> result) {
+  std::vector<Cluster> clusters;
+  std::string peek_text;
+
+  base::UmaHistogramSparse("ContextualSuggestions.FetchErrorCode",
+                           url_loader_->NetError());
+
+  if (result) {
+    int32_t response_code =
+        url_loader_->ResponseInfo()->headers->response_code();
+
+    if (response_code == net::HTTP_OK) {
+      // The response comes in the format (length, bytes) where length is a
+      // varint32 encoded int. Rather than hand-rolling logic to skip the
+      // length(which we don't actually need), we use EncodedInputStream to
+      // skip past it, then parse the remainder of the stream.
+      google::protobuf::io::CodedInputStream coded_stream(
+          reinterpret_cast<const uint8_t*>(result->data()), result->length());
+      uint32_t response_size;
+      if (coded_stream.ReadVarint32(&response_size) && response_size != 0) {
+        GetPivotsResponse response_proto;
+        if (response_proto.MergePartialFromCodedStream(&coded_stream)) {
+          clusters = ClustersFromResponse(response_proto);
+          peek_text = PeekTextFromResponse(response_proto);
+        }
+      }
+    }
+
+    UMA_HISTOGRAM_COUNTS_1M("ContextualSuggestions.FetchResponseSizeKB",
+                            static_cast<int>(result->length() / 1024));
+
+    base::UmaHistogramSparse("ContextualSuggestions.FetchResponseCode",
+                             response_code);
+  }
+
+  std::move(request_completed_callback_).Run(peek_text, std::move(clusters));
+}
 
 }  // namespace contextual_suggestions
\ No newline at end of file
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
index de1b72ee..91677e7 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
@@ -12,21 +12,34 @@
     const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory,
     const std::string& application_language_code)
     : loader_factory_(loader_factory),
-      bcp_language_code_(application_language_code) {
-  // Use loader_factory_ to suppress unused variable compiler warning.
-  loader_factory_.get();
-}
+      bcp_language_code_(application_language_code) {}
 
 ContextualSuggestionsFetcherImpl::~ContextualSuggestionsFetcherImpl() = default;
 
 void ContextualSuggestionsFetcherImpl::FetchContextualSuggestionsClusters(
     const GURL& url,
-    FetchClustersCallback callback) {}
+    FetchClustersCallback callback) {
+  auto fetch =
+      std::make_unique<ContextualSuggestionsFetch>(url, bcp_language_code_);
+  ContextualSuggestionsFetch* fetch_unowned = fetch.get();
+  pending_requests_.emplace(std::move(fetch));
+
+  FetchClustersCallback internal_callback = base::BindOnce(
+      &ContextualSuggestionsFetcherImpl::FetchFinished, base::Unretained(this),
+      fetch_unowned, std::move(callback));
+  fetch_unowned->Start(std::move(internal_callback), loader_factory_);
+}
 
 void ContextualSuggestionsFetcherImpl::FetchFinished(
     ContextualSuggestionsFetch* fetch,
     FetchClustersCallback callback,
     std::string peek_text,
-    std::vector<Cluster> clusters) {}
+    std::vector<Cluster> clusters) {
+  auto fetch_iterator = pending_requests_.find(fetch);
+  CHECK(fetch_iterator != pending_requests_.end());
+  pending_requests_.erase(fetch_iterator);
+
+  std::move(callback).Run(peek_text, std::move(clusters));
+}
 
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
index 5805b4a..a476f1b 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
@@ -43,7 +43,7 @@
                      std::string peek_text,
                      std::vector<Cluster> clusters);
 
-  const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory_;
+  const scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
   /// BCP47 formatted language code to use.
   const std::string bcp_language_code_;
 
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
index 72af7f5..4fb8248 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
@@ -4,21 +4,435 @@
 
 #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h"
 
+#include <utility>
+#include <vector>
+
+#include "base/base64.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/ntp_snippets/contextual/proto/chrome_search_api_request_context.pb.h"
+#include "components/ntp_snippets/contextual/proto/get_pivots_request.pb.h"
+#include "components/ntp_snippets/contextual/proto/get_pivots_response.pb.h"
+#include "net/http/http_status_code.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ntp_snippets {
 
+using contextual_suggestions::ClusterBuilder;
+using contextual_suggestions::ExploreContext;
+using contextual_suggestions::GetPivotsQuery;
+using contextual_suggestions::GetPivotsRequest;
+using contextual_suggestions::GetPivotsResponse;
+using contextual_suggestions::ImageId;
+using contextual_suggestions::PivotCluster;
+using contextual_suggestions::PivotClusteringParams;
+using contextual_suggestions::PivotDocument;
+using contextual_suggestions::PivotDocumentParams;
+using contextual_suggestions::PivotItem;
+using contextual_suggestions::Pivots;
+using network::SharedURLLoaderFactory;
+using network::TestURLLoaderFactory;
+using testing::ElementsAre;
+
+namespace {
+
+class MockClustersCallback {
+ public:
+  void Done(std::string peek_text, std::vector<Cluster> clusters) {
+    EXPECT_FALSE(has_run);
+    has_run = true;
+    response_peek_text = peek_text;
+    response_clusters = std::move(clusters);
+  }
+
+  bool has_run = false;
+  std::string response_peek_text;
+  std::vector<Cluster> response_clusters;
+};
+
+// TODO(pnoland): de-dupe this and the identical class in
+// feed_networking_host_unittest.cc
+class TestSharedURLLoaderFactory : public SharedURLLoaderFactory {
+ public:
+  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
+                            int32_t routing_id,
+                            int32_t request_id,
+                            uint32_t options,
+                            const network::ResourceRequest& url_request,
+                            network::mojom::URLLoaderClientPtr client,
+                            const net::MutableNetworkTrafficAnnotationTag&
+                                traffic_annotation) override {
+    test_factory_.CreateLoaderAndStart(std::move(request), routing_id,
+                                       request_id, options, url_request,
+                                       std::move(client), traffic_annotation);
+  }
+
+  std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  TestURLLoaderFactory* test_factory() { return &test_factory_; }
+
+ protected:
+  ~TestSharedURLLoaderFactory() override = default;
+
+ private:
+  TestURLLoaderFactory test_factory_;
+};
+
+Cluster DefaultCluster() {
+  return ClusterBuilder("Articles")
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.foobar.com"))
+                         .Title("Title")
+                         .PublisherName("cnn.com")
+                         .Snippet("Summary")
+                         .ImageId("abcdef")
+                         .Build())
+      .Build();
+}
+
+// Returns a single cluster with a single suggestion with preset values.
+std::vector<Cluster> DefaultClusters() {
+  std::vector<Cluster> clusters;
+
+  clusters.emplace_back(DefaultCluster());
+  return clusters;
+}
+
+void PopulateDocument(PivotDocument* document,
+                      const ContextualSuggestion& suggestion) {
+  document->mutable_url()->set_raw_url(suggestion.url.spec());
+  document->set_title(suggestion.title);
+  document->set_summary(suggestion.snippet);
+  document->set_site_name(suggestion.publisher_name);
+
+  ImageId* image_id = document->mutable_image()->mutable_id();
+  image_id->set_encrypted_docid(suggestion.image_id);
+}
+
+// Populates a GetPivotsResponse proto using |peek_text| and |clusters| and
+// returns that proto as a serialized string.
+std::string SerializedResponseProto(const std::string& peek_text,
+                                    std::vector<Cluster> clusters) {
+  GetPivotsResponse response_proto;
+  Pivots* pivots = response_proto.mutable_pivots();
+  pivots->mutable_peek_text()->set_text(peek_text);
+
+  for (const auto& cluster : clusters) {
+    PivotItem* root_item = pivots->add_item();
+    PivotCluster* pivot_cluster = root_item->mutable_cluster();
+    pivot_cluster->mutable_label()->set_label(cluster.title);
+    for (const ContextualSuggestion& suggestion : cluster.suggestions) {
+      PopulateDocument(pivot_cluster->add_item()->mutable_document(),
+                       suggestion);
+    }
+  }
+
+  // The fetch parsing logic expects the response to come as (length, bytes)
+  // where length is varint32 encoded, but ignores the actual length read.
+  // " " is a valid varint32(32) so this works for now.
+  // TODO(pnoland): Use a CodedOutputStream to prepend the actual size so that
+  // we're not relying on implementation details.
+  return " " + response_proto.SerializeAsString();
+}
+
+// Populates a GetPivotsResponse proto with a single, flat list of suggestions
+// from |single_cluster| and returns that proto as a serialized string.
+std::string SerializedResponseProto(const std::string& peek_text,
+                                    Cluster single_cluster) {
+  GetPivotsResponse response_proto;
+  Pivots* pivots = response_proto.mutable_pivots();
+  pivots->mutable_peek_text()->set_text(peek_text);
+
+  for (const ContextualSuggestion& suggestion : single_cluster.suggestions) {
+    PopulateDocument(pivots->add_item()->mutable_document(), suggestion);
+  }
+
+  // See explanation above for why we prepend " ".
+  return " " + response_proto.SerializeAsString();
+}
+
+void ExpectSuggestionsMatch(ContextualSuggestion actual,
+                            ContextualSuggestion expected) {
+  EXPECT_EQ(actual.id, expected.id);
+  EXPECT_EQ(actual.title, expected.title);
+  EXPECT_EQ(actual.url, expected.url);
+  EXPECT_EQ(actual.snippet, expected.snippet);
+  EXPECT_EQ(actual.publisher_name, expected.publisher_name);
+  EXPECT_EQ(actual.image_id, expected.image_id);
+  EXPECT_EQ(actual.favicon_image_id, expected.favicon_image_id);
+}
+
+void ExpectClustersMatch(Cluster actual, Cluster expected) {
+  EXPECT_EQ(actual.title, expected.title);
+  for (size_t i = 0; i < actual.suggestions.size(); i++) {
+    ExpectSuggestionsMatch(std::move(actual.suggestions[i]),
+                           std::move(expected.suggestions[i]));
+  }
+}
+
+void ExpectResponsesMatch(MockClustersCallback callback,
+                          std::string expected_peek_text,
+                          std::vector<Cluster> expected_clusters) {
+  EXPECT_EQ(callback.response_peek_text, expected_peek_text);
+  ASSERT_EQ(callback.response_clusters.size(), expected_clusters.size());
+  for (size_t i = 0; i < callback.response_clusters.size(); i++) {
+    ExpectClustersMatch(std::move(callback.response_clusters[i]),
+                        std::move(expected_clusters[i]));
+  }
+}
+
+}  // namespace
+
 class ContextualSuggestionsFetcherTest : public testing::Test {
  public:
-  ContextualSuggestionsFetcherTest() {}
+  ContextualSuggestionsFetcherTest() {
+    loader_factory_ = base::MakeRefCounted<TestSharedURLLoaderFactory>();
+    fetcher_ = std::make_unique<ContextualSuggestionsFetcherImpl>(
+        loader_factory_, "en");
+  }
 
-  ~ContextualSuggestionsFetcherTest() override {
+  ~ContextualSuggestionsFetcherTest() override {}
+
+  void SetFakeResponse(const std::string& response_data,
+                       net::HttpStatusCode response_code = net::HTTP_OK,
+                       network::URLLoaderCompletionStatus status =
+                           network::URLLoaderCompletionStatus()) {
+    GURL fetch_url(ContextualSuggestionsFetch::GetFetchEndpoint());
+    network::ResourceResponseHead head;
+    if (response_code >= 0) {
+      head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+          "HTTP/1.1 " + base::NumberToString(response_code));
+      status.decoded_body_length = response_data.length();
+    }
+
+    loader_factory_->test_factory()->AddResponse(fetch_url, head, response_data,
+                                                 status);
+  }
+
+  void SendAndAwaitResponse(const GURL& context_url,
+                            MockClustersCallback* callback) {
+    fetcher().FetchContextualSuggestionsClusters(
+        context_url, base::BindOnce(&MockClustersCallback::Done,
+                                    base::Unretained(callback)));
+    base::RunLoop().RunUntilIdle();
+  }
+
+  ContextualSuggestionsFetcher& fetcher() { return *fetcher_; }
+
+  TestURLLoaderFactory* test_factory() {
+    return loader_factory_->test_factory();
   }
 
  private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  scoped_refptr<TestSharedURLLoaderFactory> loader_factory_;
+  std::unique_ptr<ContextualSuggestionsFetcherImpl> fetcher_;
 
   DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsFetcherTest);
 };
 
+TEST_F(ContextualSuggestionsFetcherTest, SingleSuggestionResponse) {
+  MockClustersCallback callback;
+  SetFakeResponse(SerializedResponseProto("Peek Text", DefaultClusters()));
+
+  SendAndAwaitResponse(GURL("http://www.article.com"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  ExpectResponsesMatch(std::move(callback), "Peek Text", DefaultClusters());
+}
+
+TEST_F(ContextualSuggestionsFetcherTest,
+       MultipleSuggestionMultipleClusterResponse) {
+  std::vector<Cluster> clusters;
+  std::vector<Cluster> clusters_copy;
+  base::HistogramTester histogram_tester;
+
+  ClusterBuilder cluster1_builder("Category 1");
+  cluster1_builder
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.test.com"))
+                         .Title("Title1")
+                         .PublisherName("test.com")
+                         .Snippet("Summary 1")
+                         .ImageId("abc")
+                         .Build())
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.foobar.com"))
+                         .Title("Title2")
+                         .PublisherName("foobar.com")
+                         .Snippet("Summary 2")
+                         .ImageId("def")
+                         .Build());
+
+  ClusterBuilder cluster2_builder("Category 2");
+  cluster2_builder
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.barbaz.com"))
+                         .Title("Title3")
+                         .PublisherName("barbaz.com")
+                         .Snippet("Summary 3")
+                         .ImageId("ghi")
+                         .Build())
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.cnn.com"))
+                         .Title("Title4")
+                         .PublisherName("cnn.com")
+                         .Snippet("Summary 4")
+                         .ImageId("jkl")
+                         .Build())
+      .AddSuggestion(SuggestionBuilder(GURL("http://www.slate.com"))
+                         .Title("Title5")
+                         .PublisherName("slate.com")
+                         .Snippet("Summary 5")
+                         .ImageId("mno")
+                         .Build());
+  ClusterBuilder c1_copy = cluster1_builder;
+  ClusterBuilder c2_copy = cluster2_builder;
+
+  clusters.emplace_back(cluster1_builder.Build());
+  clusters.emplace_back(cluster2_builder.Build());
+
+  clusters_copy.emplace_back(c1_copy.Build());
+  clusters_copy.emplace_back(c2_copy.Build());
+
+  SetFakeResponse(SerializedResponseProto("Peek Text", std::move(clusters)));
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  ExpectResponsesMatch(std::move(callback), "Peek Text",
+                       std::move(clusters_copy));
+
+  histogram_tester.ExpectTotalCount("ContextualSuggestions.FetchResponseSizeKB",
+                                    1);
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, FlatResponse) {
+  SetFakeResponse(SerializedResponseProto("Peek Text", DefaultCluster()));
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  // There's no title for the flat/unclustered response case, since there's no
+  // PivotCluster to copy it from. So we clear the expected title.
+  std::vector<Cluster> expected_clusters = DefaultClusters();
+  expected_clusters[0].title = "";
+  ExpectResponsesMatch(std::move(callback), "Peek Text",
+                       std::move(expected_clusters));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, RequestHeaderSetCorrectly) {
+  net::HttpRequestHeaders headers;
+  base::RunLoop interceptor_run_loop;
+  base::HistogramTester histogram_tester;
+
+  test_factory()->SetInterceptor(
+      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
+        headers = request.headers;
+        interceptor_run_loop.Quit();
+      }));
+  SetFakeResponse(SerializedResponseProto("Peek Text", DefaultClusters()));
+
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  interceptor_run_loop.Run();
+
+  std::string protobuf_header;
+  ASSERT_TRUE(
+      headers.GetHeader("X-Protobuffer-Request-Payload", &protobuf_header));
+
+  std::string decoded_header_value;
+  base::Base64Decode(protobuf_header, &decoded_header_value);
+  GetPivotsRequest request;
+  ASSERT_TRUE(request.ParseFromString(decoded_header_value));
+
+  EXPECT_EQ(request.context().localization_context().spoken_language(), "en");
+  EXPECT_EQ(request.query().context()[0].url(), "http://www.article.com/");
+  EXPECT_TRUE(request.query().document_params().enabled());
+  EXPECT_EQ(request.query().document_params().num(), 10);
+  EXPECT_TRUE(request.query().document_params().enable_images());
+  EXPECT_TRUE(request.query().clustering_params().enabled());
+  EXPECT_TRUE(request.query().peek_text_params().enabled());
+
+  histogram_tester.ExpectTotalCount(
+      "ContextualSuggestions.FetchRequestProtoSizeKB", 1);
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, ProtocolError) {
+  MockClustersCallback callback;
+  base::HistogramTester histogram_tester;
+
+  SetFakeResponse("", net::HTTP_NOT_FOUND);
+  SendAndAwaitResponse(GURL("http://www.article.com"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  EXPECT_EQ(callback.response_clusters.size(), 0u);
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("ContextualSuggestions.FetchResponseCode"),
+      ElementsAre(base::Bucket(/*min=*/net::HTTP_NOT_FOUND, /*count=*/1)));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, NetworkError) {
+  MockClustersCallback callback;
+  base::HistogramTester histogram_tester;
+
+  SetFakeResponse(
+      "", net::HTTP_OK,
+      network::URLLoaderCompletionStatus(net::ERR_CERT_COMMON_NAME_INVALID));
+  SendAndAwaitResponse(GURL("http://www.article.com"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  EXPECT_EQ(callback.response_clusters.size(), 0u);
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("ContextualSuggestions.FetchErrorCode"),
+      ElementsAre(base::Bucket(
+          /*min=*/net::ERR_CERT_COMMON_NAME_INVALID, /*count=*/1)));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, EmptyResponse) {
+  SetFakeResponse(SerializedResponseProto("", Cluster()));
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  EXPECT_EQ(callback.response_clusters.size(), 0u);
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, ResponseWithUnsetFields) {
+  GetPivotsResponse response;
+  Pivots* pivots = response.mutable_pivots();
+  pivots->add_item()->mutable_document();
+  pivots->add_item();
+
+  SetFakeResponse(" " + response.SerializeAsString());
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  std::vector<Cluster> expected_clusters;
+  expected_clusters.emplace_back(
+      ClusterBuilder("")
+          .AddSuggestion(SuggestionBuilder(GURL()).Build())
+          .AddSuggestion(SuggestionBuilder(GURL()).Build())
+          .Build());
+
+  EXPECT_TRUE(callback.has_run);
+  EXPECT_EQ(callback.response_clusters.size(), 1u);
+  ExpectResponsesMatch(std::move(callback), "", std::move(expected_clusters));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, CorruptResponse) {
+  SetFakeResponse("unparseable proto string");
+  MockClustersCallback callback;
+  SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
+
+  EXPECT_TRUE(callback.has_run);
+  EXPECT_EQ(callback.response_clusters.size(), 0u);
+}
 
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.cc b/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.cc
index 1111ed2..f3f4b600 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.cc
@@ -10,6 +10,17 @@
 
 namespace contextual_suggestions {
 
+ContextualSuggestionsMetricsReporterProvider::
+    ContextualSuggestionsMetricsReporterProvider() = default;
+
+ContextualSuggestionsMetricsReporterProvider::
+    ~ContextualSuggestionsMetricsReporterProvider() = default;
+
+std::unique_ptr<ContextualSuggestionsMetricsReporter>
+ContextualSuggestionsMetricsReporterProvider::CreateMetricsReporter() {
+  return std::make_unique<ContextualSuggestionsMetricsReporter>();
+}
+
 ContextualSuggestionsMetricsReporter::ContextualSuggestionsMetricsReporter()
     : sheet_peeked_(false),
       sheet_opened_(false),
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h b/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h
index fd62f5f..4d98194 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_metrics_reporter.h
@@ -62,6 +62,24 @@
   kMaxValue = SUGGESTION_CLICKED,
 };
 
+class ContextualSuggestionsMetricsReporter;
+
+// Class producing |ContextualSuggestionsMetricsReporter| instances. It enables
+// classes like |ContextualContentSuggestionService| to produce metrics
+// reporters when needed, e.g. creation of service proxy, without knowing how to
+// initialize them.
+class ContextualSuggestionsMetricsReporterProvider {
+ public:
+  ContextualSuggestionsMetricsReporterProvider();
+  virtual ~ContextualSuggestionsMetricsReporterProvider();
+
+  virtual std::unique_ptr<ContextualSuggestionsMetricsReporter>
+  CreateMetricsReporter();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsMetricsReporterProvider);
+};
+
 // Tracks various UKM and UMA metrics based on reports of events that take place
 // within the Contextual Suggestions component.
 //
diff --git a/components/ntp_snippets/contextual/proto/get_pivots_request.proto b/components/ntp_snippets/contextual/proto/get_pivots_request.proto
index fa3f986..48cb0c5 100644
--- a/components/ntp_snippets/contextual/proto/get_pivots_request.proto
+++ b/components/ntp_snippets/contextual/proto/get_pivots_request.proto
@@ -31,6 +31,9 @@
   // Parameters related to clustering pivot items (documents, queries,
   // questions, etc.).
   optional PivotClusteringParams clustering_params = 6;
+
+  // Parameters related to peek text.
+  optional PivotPeekTextParams peek_text_params = 7;
 }
 
 // One piece of historical context in the user's exploration session.
@@ -75,3 +78,9 @@
   // Maximum number of clusters we should return.
   optional int32 max = 3;
 }
+
+// Parameters related to the peek text.
+message PivotPeekTextParams {
+  // Whether or not to return peek text.
+  optional bool enabled = 1 [default = false];
+}
\ No newline at end of file
diff --git a/components/password_manager/content/common/credential_manager_mojom_traits.cc b/components/password_manager/content/common/credential_manager_mojom_traits.cc
index 4d073b7..e5793d1 100644
--- a/components/password_manager/content/common/credential_manager_mojom_traits.cc
+++ b/components/password_manager/content/common/credential_manager_mojom_traits.cc
@@ -88,9 +88,17 @@
           password_manager::CredentialManagerError::PASSWORDSTOREUNAVAILABLE;
       return true;
     case password_manager::mojom::CredentialManagerError::NOT_ALLOWED:
-    case password_manager::mojom::CredentialManagerError::NOT_SUPPORTED:
+    case password_manager::mojom::CredentialManagerError::
+        AUTHENTICATOR_CRITERIA_UNSUPPORTED:
+    case password_manager::mojom::CredentialManagerError::ALGORITHM_UNSUPPORTED:
+    case password_manager::mojom::CredentialManagerError::
+        EMPTY_ALLOW_CREDENTIALS:
+    case password_manager::mojom::CredentialManagerError::
+        USER_VERIFICATION_UNSUPPORTED:
     case password_manager::mojom::CredentialManagerError::INVALID_DOMAIN:
-    case password_manager::mojom::CredentialManagerError::INVALID_STATE:
+    case password_manager::mojom::CredentialManagerError::CREDENTIAL_EXCLUDED:
+    case password_manager::mojom::CredentialManagerError::
+        CREDENTIAL_NOT_RECOGNIZED:
     case password_manager::mojom::CredentialManagerError::NOT_IMPLEMENTED:
     case password_manager::mojom::CredentialManagerError::NOT_FOCUSED:
     case password_manager::mojom::CredentialManagerError::UNKNOWN:
diff --git a/components/policy/resources/policy_templates_zh-CN.xtb b/components/policy/resources/policy_templates_zh-CN.xtb
index b53f341..df38992b2 100644
--- a/components/policy/resources/policy_templates_zh-CN.xtb
+++ b/components/policy/resources/policy_templates_zh-CN.xtb
@@ -2427,6 +2427,15 @@
 <translation id="9112897538922695510">可让您注册一个协议处理程序列表。此政策只能是推荐的政策。属性|protocol|应设为“mailto”等协议,属性|url|应设为处理该协议的应用采用的网址格式。该格式中可以包含“%s”(如果有,将被替换为所处理的网址)。
 
           通过政策注册的协议处理程序会与用户注册的协议处理程序合并到一起,两种处理程序都可使用。用户可以通过安装新的默认处理程序来覆盖通过政策安装的协议处理程序,但无法卸载通过政策注册的协议处理程序。</translation>
+<translation id="9123211093995421438">指定 <ph name="PRODUCT_OS_NAME" />随时可从稳定版回滚到的里程碑的数量下限。
+
+      对于由消费者注册的设备,默认值为 0;对于由企业注册的设备,默认值为 4(大约半年)。
+
+      设置此政策可使回滚防护机制在至少这么多个里程碑内不起作用。
+
+      将此政策设为较小的值会产生永久性的效果:即使之后再将此政策设为较大的值,设备可能也无法回滚到更早的版本。
+
+      实际的回滚可能性或许还取决于设备型号和关键的漏洞补丁程序。</translation>
 <translation id="913195841488580904">阻止访问网址列表</translation>
 <translation id="9135033364005346124">启用“<ph name="CLOUD_PRINT_NAME" />”代理</translation>
 <translation id="9136253551939494882">一种白名单,用于控制用户可以配置和使用哪些快速解锁模式来解锁屏幕。
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp
index 0f0e6ef..e9cf574 100644
--- a/components/policy_strings.grdp
+++ b/components/policy_strings.grdp
@@ -237,6 +237,10 @@
   <message name="IDS_POLICY_TOOL_TITLE" desc="Admin page title and the title of the section that lists policies.">
     Policy management
   </message>
+  <message name="IDS_EXPORT_POLICIES_LINUX" desc="Button that exports the current session policy
+  in linux format.">
+    Export Linux
+  </message>
   <message name="IDS_POLICY_TOOL_EDIT" desc="Label for the button to change policy value in current session.">
     Edit
   </message>
diff --git a/components/printing/browser/print_composite_client.cc b/components/printing/browser/print_composite_client.cc
index d5bd4ab..65f6635 100644
--- a/components/printing/browser/print_composite_client.cc
+++ b/components/printing/browser/print_composite_client.cc
@@ -283,6 +283,7 @@
   }
   mojom::PdfCompositorPtr compositor;
   connector_->BindInterface(mojom::kServiceName, &compositor);
+  compositor->SetWebContentsURL(web_contents()->GetLastCommittedURL());
   return compositor;
 }
 
diff --git a/components/printing/resources/print_preview_page.html b/components/printing/resources/print_preview_page.html
index a7fe785..e53c845 100644
--- a/components/printing/resources/print_preview_page.html
+++ b/components/printing/resources/print_preview_page.html
@@ -47,6 +47,10 @@
     padding-right: 0.7cm;
   }
 
+  .grow {
+    flex: auto;
+  }
+
   .text {
     font-size: 8px;
     overflow: hidden;
@@ -70,8 +74,7 @@
     <div class='date text left'></div>
     <div class='title text center'></div>`;
   footer.innerHTML = options['footerTemplate'] || `
-    <div class='url text left'></div>
-    <div class='center'></div>
+    <div class='url text left grow'></div>
     <div class='text right'>
       <span class='pageNumber'></span>/<span class='totalPages'></span>
     </div>`;
diff --git a/components/printing/service/BUILD.gn b/components/printing/service/BUILD.gn
index 4168528..6f7b8af 100644
--- a/components/printing/service/BUILD.gn
+++ b/components/printing/service/BUILD.gn
@@ -17,6 +17,7 @@
 
   deps = [
     "//base",
+    "//components/crash/core/common:crash_key",
     "//components/discardable_memory/client",
     "//components/discardable_memory/public/interfaces",
     "//content/public/child",
@@ -56,6 +57,7 @@
       ":service",
       "//base/test:test_support",
       "//cc/paint:paint",
+      "//components/crash/core/common:crash_key",
       "//components/printing/service/public/interfaces",
       "//mojo/common",
       "//services/service_manager/public/cpp:service_test_support",
diff --git a/components/printing/service/DEPS b/components/printing/service/DEPS
index e4486618..f050f35 100644
--- a/components/printing/service/DEPS
+++ b/components/printing/service/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+cc/paint",
+  "+components/crash/core/common/crash_key.h",
   "+components/discardable_memory/client",
   "+content/public/child",  # Windows direct write proxy access.
   "+content/public/utility",
diff --git a/components/printing/service/pdf_compositor_impl.cc b/components/printing/service/pdf_compositor_impl.cc
index eb3799b..387e8334 100644
--- a/components/printing/service/pdf_compositor_impl.cc
+++ b/components/printing/service/pdf_compositor_impl.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/memory/shared_memory_handle.h"
 #include "base/stl_util.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
 #include "components/printing/service/public/cpp/pdf_service_mojo_utils.h"
 #include "mojo/public/cpp/system/platform_handle.h"
@@ -96,6 +97,13 @@
                            std::move(callback));
 }
 
+void PdfCompositorImpl::SetWebContentsURL(const GURL& url) {
+  // Record the most recent url we tried to print. This should be sufficient
+  // for users using print preview by default.
+  static crash_reporter::CrashKeyString<1024> crash_key("main-frame-url");
+  crash_key.Set(url.spec());
+}
+
 void PdfCompositorImpl::UpdateRequestsWithSubframeInfo(
     uint64_t frame_guid,
     const std::vector<uint64_t>& pending_subframes) {
diff --git a/components/printing/service/pdf_compositor_impl.h b/components/printing/service/pdf_compositor_impl.h
index 809055e4..72960244 100644
--- a/components/printing/service/pdf_compositor_impl.h
+++ b/components/printing/service/pdf_compositor_impl.h
@@ -49,6 +49,7 @@
       mojo::ScopedSharedBufferHandle serialized_content,
       const ContentToFrameMap& subframe_content_map,
       mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) override;
+  void SetWebContentsURL(const GURL& url) override;
 
  protected:
   // This is the uniform underlying type for both
diff --git a/components/printing/service/pdf_compositor_impl_unittest.cc b/components/printing/service/pdf_compositor_impl_unittest.cc
index cae20e7..f2b24b99 100644
--- a/components/printing/service/pdf_compositor_impl_unittest.cc
+++ b/components/printing/service/pdf_compositor_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/callback.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/printing/service/pdf_compositor_impl.h"
 #include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -61,6 +62,22 @@
   bool is_ready_;
 };
 
+class PdfCompositorImplCrashKeyTest : public PdfCompositorImplTest {
+ public:
+  PdfCompositorImplCrashKeyTest() {}
+  ~PdfCompositorImplCrashKeyTest() override {}
+
+  void SetUp() override {
+    crash_reporter::ResetCrashKeysForTesting();
+    crash_reporter::InitializeCrashKeys();
+  }
+
+  void TearDown() override { crash_reporter::ResetCrashKeysForTesting(); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PdfCompositorImplCrashKeyTest);
+};
+
 TEST_F(PdfCompositorImplTest, IsReadyToComposite) {
   PdfCompositorImpl impl("unittest", nullptr);
   // Frame 2 and 3 are painted.
@@ -345,4 +362,13 @@
   testing::Mock::VerifyAndClearExpectations(&impl);
 }
 
+TEST_F(PdfCompositorImplCrashKeyTest, SetCrashKey) {
+  PdfCompositorImpl impl("unittest", nullptr);
+  std::string url_str("https://www.example.com/");
+  GURL url(url_str);
+  impl.SetWebContentsURL(url);
+
+  EXPECT_EQ(crash_reporter::GetCrashKeyValue("main-frame-url"), url_str);
+}
+
 }  // namespace printing
diff --git a/components/printing/service/public/interfaces/BUILD.gn b/components/printing/service/public/interfaces/BUILD.gn
index 1efdb194..b9162a6 100644
--- a/components/printing/service/public/interfaces/BUILD.gn
+++ b/components/printing/service/public/interfaces/BUILD.gn
@@ -8,4 +8,7 @@
   sources = [
     "pdf_compositor.mojom",
   ]
+  public_deps = [
+    "//url/mojom:url_mojom_gurl",
+  ]
 }
diff --git a/components/printing/service/public/interfaces/pdf_compositor.mojom b/components/printing/service/public/interfaces/pdf_compositor.mojom
index ca9ba7a..202d289a 100644
--- a/components/printing/service/public/interfaces/pdf_compositor.mojom
+++ b/components/printing/service/public/interfaces/pdf_compositor.mojom
@@ -4,6 +4,8 @@
 
 module printing.mojom;
 
+import "url/mojom/url.mojom";
+
 const string kServiceName = "pdf_compositor";
 
 interface PdfCompositor {
@@ -23,7 +25,7 @@
   // |frame_guid| is this subframe's global unique id.
   NotifyUnavailableSubframe(uint64 frame_guid);
 
-  // Add the content of a subframe for composition.
+  // Adds the content of a subframe for composition.
   // |frame_guid| is this subframe's global unique id.
   // |serialized_content| points to a buffer of a serialized Skia picture which
   //                      has the painted content of this frame.
@@ -32,7 +34,7 @@
   AddSubframeContent(uint64 frame_guid, handle<shared_buffer> serialized_content,
                      map<uint32, uint64> subframe_content_info);
 
-  // Request to composite a page and convert it into a PDF file.
+  // Requests to composite a page and convert it into a PDF file.
   // |frame_guid| is the global unique id of the frame to be composited.
   // |page_num| is zero-based sequence number of page.
   // |sk_handle| points to a buffer of a Skia MultiPictureDocument which has
@@ -44,10 +46,14 @@
                      map<uint32, uint64> subframe_content_info)
       => (Status status, handle<shared_buffer>? pdf_handle);
 
-  // Request to composite the entire document and convert it into a PDF file.
+  // Requests to composite the entire document and convert it into a PDF file.
   // All the arguments carry the same meaning as CompositePageToPdf() above,
   // except this call doesn't have |page_num|.
   CompositeDocumentToPdf(uint64 frame_guid, handle<shared_buffer> sk_handle,
                          map<uint32, uint64> subframe_content_info)
       => (Status status, handle<shared_buffer>? pdf_handle);
+
+  // Sets the URL which is committed in the main frame of the WebContents,
+  // for use in crash diagnosis.
+  SetWebContentsURL(url.mojom.Url url);
 };
diff --git a/components/safe_browsing/base_ui_manager.cc b/components/safe_browsing/base_ui_manager.cc
index a927403..04cd59e 100644
--- a/components/safe_browsing/base_ui_manager.cc
+++ b/components/safe_browsing/base_ui_manager.cc
@@ -113,11 +113,6 @@
 
 BaseUIManager::BaseUIManager() {}
 
-void BaseUIManager::StopOnIOThread(bool shutdown) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  return;
-}
-
 BaseUIManager::~BaseUIManager() {}
 
 bool BaseUIManager::IsWhitelisted(const UnsafeResource& resource) {
diff --git a/components/safe_browsing/base_ui_manager.h b/components/safe_browsing/base_ui_manager.h
index 0477734..b349f00 100644
--- a/components/safe_browsing/base_ui_manager.h
+++ b/components/safe_browsing/base_ui_manager.h
@@ -34,12 +34,6 @@
 
   BaseUIManager();
 
-  // Called to stop or shutdown operations on the io_thread. This may be called
-  // multiple times during the life of the UIManager. Should be called
-  // on IO thread. If shutdown is true, the manager is disabled permanently.
-  // This currently is a no-op in the base class.
-  virtual void StopOnIOThread(bool shutdown);
-
   // Called on the UI thread to display an interstitial page.
   // |url| is the url of the resource that matches a safe browsing list.
   // If the request contained a chain of redirects, |url| is the last url
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index c96c513e..c180ac3 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -28,6 +28,20 @@
   ]
 }
 
+# Split into its own target to allow browser clients of the Identity Service to
+# record browser-specific signin metrics without having to depend on all of
+# //components/signin/core/browser.
+static_library("signin_metrics") {
+  sources = [
+    "signin_metrics.cc",
+    "signin_metrics.h",
+  ]
+  public_deps = [
+    "//base",
+    "//google_apis",
+  ]
+}
+
 static_library("browser") {
   sources = [
     "about_signin_internals.cc",
@@ -84,8 +98,6 @@
     "signin_manager.h",
     "signin_manager_base.cc",
     "signin_manager_base.h",
-    "signin_metrics.cc",
-    "signin_metrics.h",
     "signin_pref_names.cc",
     "signin_pref_names.h",
     "signin_status_metrics_provider.cc",
@@ -109,6 +121,7 @@
   public_deps = [
     ":account_info",
     ":signin_buildflags",
+    ":signin_metrics",
     "//base",
     "//components/content_settings/core/browser",
     "//components/content_settings/core/common",
@@ -214,6 +227,7 @@
     "signin_header_helper_unittest.cc",
     "signin_investigator_unittest.cc",
     "signin_manager_unittest.cc",
+    "signin_metrics_unittest.cc",
     "signin_status_metrics_provider_unittest.cc",
     "webdata/token_service_table_unittest.cc",
   ]
diff --git a/components/signin/core/browser/signin_metrics.cc b/components/signin/core/browser/signin_metrics.cc
index b90fe34..947a20c 100644
--- a/components/signin/core/browser/signin_metrics.cc
+++ b/components/signin/core/browser/signin_metrics.cc
@@ -61,13 +61,13 @@
 }
 
 void LogSigninAccessPointStarted(AccessPoint access_point) {
-  LogSigninAccessPointStarted(
-      access_point, signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
+  LogSigninAccessPointStarted(access_point,
+                              PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
 }
 
 void LogSigninAccessPointCompleted(AccessPoint access_point) {
-  LogSigninAccessPointCompleted(
-      access_point, signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
+  LogSigninAccessPointCompleted(access_point,
+                                PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
 }
 
 void LogSigninAccessPointStarted(AccessPoint access_point,
@@ -232,7 +232,7 @@
 
 void LogSigninConfirmHistogramValue(ConfirmationUsage action) {
   UMA_HISTOGRAM_ENUMERATION("Signin.OneClickConfirmation", action,
-                            signin_metrics::HISTOGRAM_CONFIRM_MAX);
+                            HISTOGRAM_CONFIRM_MAX);
 }
 
 void LogXDevicePromoEligible(CrossDevicePromoEligibility metric) {
@@ -300,103 +300,301 @@
 // User actions
 // --------------------------------------------------------------
 
-void RecordSigninUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point) {
+void RecordSigninUserActionForAccessPoint(AccessPoint access_point) {
   switch (access_point) {
-    case signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE:
+    case AccessPoint::ACCESS_POINT_START_PAGE:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromStartPage"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_NTP_LINK:
+    case AccessPoint::ACCESS_POINT_NTP_LINK:
       base::RecordAction(base::UserMetricsAction("Signin_Signin_FromNTP"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_MENU:
+    case AccessPoint::ACCESS_POINT_MENU:
       base::RecordAction(base::UserMetricsAction("Signin_Signin_FromMenu"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
+    case AccessPoint::ACCESS_POINT_SETTINGS:
       base::RecordAction(base::UserMetricsAction("Signin_Signin_FromSettings"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SUPERVISED_USER:
+    case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromSupervisedUser"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
+    case AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromExtensionInstallBubble"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS:
+    case AccessPoint::ACCESS_POINT_EXTENSIONS:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromExtensions"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
+    case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromAppsPageLink"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
+    case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromBookmarkBubble"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+    case AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromBookmarkManager"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
+    case AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromAvatarBubbleSignin"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER:
+    case AccessPoint::ACCESS_POINT_USER_MANAGER:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromUserManager"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_DEVICES_PAGE:
+    case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromDevicesPage"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_CLOUD_PRINT:
+    case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromCloudPrint"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_CONTENT_AREA:
+    case AccessPoint::ACCESS_POINT_CONTENT_AREA:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromContentArea"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
+    case AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromSigninPromo"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
+    case AccessPoint::ACCESS_POINT_RECENT_TABS:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromRecentTabs"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN:
+    case AccessPoint::ACCESS_POINT_UNKNOWN:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromUnknownAccessPoint"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
+    case AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromPasswordBubble"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
+    case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromAutofillDropdown"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
+    case AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromNTPContentSuggestions"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
+    case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromReSigninInfobar"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+    case AccessPoint::ACCESS_POINT_TAB_SWITCHER:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromTabSwitcher"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING:
+    case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING:
       base::RecordAction(
           base::UserMetricsAction("Signin_Signin_FromForceSigninWarning"));
       break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_MAX:
+    case AccessPoint::ACCESS_POINT_MAX:
+      NOTREACHED();
+      break;
+  }
+}
+
+void RecordSigninImpressionUserActionForAccessPoint(AccessPoint access_point) {
+  switch (access_point) {
+    case AccessPoint::ACCESS_POINT_START_PAGE:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromStartPage"));
+      break;
+    case AccessPoint::ACCESS_POINT_NTP_LINK:
+      base::RecordAction(base::UserMetricsAction("Signin_Impression_FromNTP"));
+      break;
+    case AccessPoint::ACCESS_POINT_MENU:
+      base::RecordAction(base::UserMetricsAction("Signin_Impression_FromMenu"));
+      break;
+    case AccessPoint::ACCESS_POINT_SETTINGS:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromSettings"));
+      break;
+    case AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_Impression_FromExtensionInstallBubble"));
+      break;
+    case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromAppsPageLink"));
+      break;
+    case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromBookmarkBubble"));
+      break;
+    case AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromBookmarkManager"));
+      break;
+    case AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromAvatarBubbleSignin"));
+      break;
+    case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromDevicesPage"));
+      break;
+    case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromCloudPrint"));
+      break;
+    case AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromSigninPromo"));
+      break;
+    case AccessPoint::ACCESS_POINT_RECENT_TABS:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromRecentTabs"));
+      break;
+    case AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromPasswordBubble"));
+      break;
+    case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromAutofillDropdown"));
+      break;
+    case AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_Impression_FromNTPContentSuggestions"));
+      break;
+    case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromReSigninInfobar"));
+      break;
+    case AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_Impression_FromTabSwitcher"));
+      break;
+    case AccessPoint::ACCESS_POINT_CONTENT_AREA:
+    case AccessPoint::ACCESS_POINT_EXTENSIONS:
+    case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING:
+    case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
+    case AccessPoint::ACCESS_POINT_USER_MANAGER:
+    case AccessPoint::ACCESS_POINT_UNKNOWN:
+      NOTREACHED() << "Signin_Impression_From* user actions"
+                   << " are not recorded for access_point "
+                   << static_cast<int>(access_point);
+      break;
+    case AccessPoint::ACCESS_POINT_MAX:
+      NOTREACHED();
+      break;
+  }
+}
+
+void RecordSigninImpressionWithAccountUserActionForAccessPoint(
+    AccessPoint access_point,
+    bool with_account) {
+  switch (access_point) {
+    case AccessPoint::ACCESS_POINT_SETTINGS:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromSettings"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromSettings"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromExtensionInstallBubble"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromExtensionInstallBubble"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromBookmarkBubble"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromBookmarkBubble"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromBookmarkManager"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromBookmarkManager"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromAvatarBubbleSignin"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromAvatarBubbleSignin"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_RECENT_TABS:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromRecentTabs"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromRecentTabs"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromPasswordBubble"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromPasswordBubble"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromTabSwitcher"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromTabSwitcher"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
+      if (with_account) {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithAccount_FromNTPContentSuggestions"));
+      } else {
+        base::RecordAction(base::UserMetricsAction(
+            "Signin_ImpressionWithNoAccount_FromNTPContentSuggestions"));
+      }
+      break;
+    case AccessPoint::ACCESS_POINT_START_PAGE:
+    case AccessPoint::ACCESS_POINT_NTP_LINK:
+    case AccessPoint::ACCESS_POINT_MENU:
+    case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
+    case AccessPoint::ACCESS_POINT_EXTENSIONS:
+    case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
+    case AccessPoint::ACCESS_POINT_USER_MANAGER:
+    case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
+    case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
+    case AccessPoint::ACCESS_POINT_CONTENT_AREA:
+    case AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
+    case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
+    case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
+    case AccessPoint::ACCESS_POINT_UNKNOWN:
+    case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING:
+      NOTREACHED() << "Signin_Impression{With|WithNo}Account_From* user actions"
+                   << " are not recorded for access_point "
+                   << static_cast<int>(access_point)
+                   << " as it does not support a personalized sign-in promo.";
+      break;
+    case AccessPoint::ACCESS_POINT_MAX:
       NOTREACHED();
       break;
   }
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h
index 8414c94..1368fc2 100644
--- a/components/signin/core/browser/signin_metrics.h
+++ b/components/signin/core/browser/signin_metrics.h
@@ -401,8 +401,15 @@
 // -----------------------------------------------------------------------------
 
 // Records corresponding sign in user action for an access point.
-void RecordSigninUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point);
+void RecordSigninUserActionForAccessPoint(AccessPoint access_point);
+
+// Records |Signin_ImpressionWithAccount_From*| user action.
+void RecordSigninImpressionUserActionForAccessPoint(AccessPoint access_point);
+
+// Records |Signin_Impression{With|No}Account_From*| user action.
+void RecordSigninImpressionWithAccountUserActionForAccessPoint(
+    AccessPoint access_point,
+    bool with_account);
 
 }  // namespace signin_metrics
 
diff --git a/components/signin/core/browser/signin_metrics_unittest.cc b/components/signin/core/browser/signin_metrics_unittest.cc
new file mode 100644
index 0000000..fc0cb0a
--- /dev/null
+++ b/components/signin/core/browser/signin_metrics_unittest.cc
@@ -0,0 +1,157 @@
+// 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/signin/core/browser/signin_metrics.h"
+
+#include <string>
+#include <vector>
+
+#include "base/test/user_action_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace signin_metrics {
+
+namespace {
+
+const AccessPoint kAccessPointsThatSupportImpression[] = {
+    AccessPoint::ACCESS_POINT_START_PAGE,
+    AccessPoint::ACCESS_POINT_NTP_LINK,
+    AccessPoint::ACCESS_POINT_MENU,
+    AccessPoint::ACCESS_POINT_SETTINGS,
+    AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
+    AccessPoint::ACCESS_POINT_APPS_PAGE_LINK,
+    AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+    AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER,
+    AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
+    AccessPoint::ACCESS_POINT_DEVICES_PAGE,
+    AccessPoint::ACCESS_POINT_CLOUD_PRINT,
+    AccessPoint::ACCESS_POINT_SIGNIN_PROMO,
+    AccessPoint::ACCESS_POINT_RECENT_TABS,
+    AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE,
+    AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN,
+    AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS,
+    AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR,
+    AccessPoint::ACCESS_POINT_TAB_SWITCHER};
+
+const AccessPoint kAccessPointsThatSupportImpressionWithAccount[] = {
+    AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER,
+    AccessPoint::ACCESS_POINT_RECENT_TABS,
+    AccessPoint::ACCESS_POINT_SETTINGS,
+    AccessPoint::ACCESS_POINT_TAB_SWITCHER,
+    AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
+    AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
+    AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE,
+    AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
+    AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS};
+
+class SigninMetricsTest : public ::testing::Test {
+ public:
+  static std::string GetAccessPointDescription(AccessPoint access_point) {
+    switch (access_point) {
+      case AccessPoint::ACCESS_POINT_START_PAGE:
+        return "StartPage";
+      case AccessPoint::ACCESS_POINT_NTP_LINK:
+        return "NTP";
+      case AccessPoint::ACCESS_POINT_MENU:
+        return "Menu";
+      case AccessPoint::ACCESS_POINT_SETTINGS:
+        return "Settings";
+      case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
+        return "SupervisedUser";
+      case AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
+        return "ExtensionInstallBubble";
+      case AccessPoint::ACCESS_POINT_EXTENSIONS:
+        return "Extensions";
+      case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
+        return "AppsPageLink";
+      case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
+        return "BookmarkBubble";
+      case AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+        return "BookmarkManager";
+      case AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
+        return "AvatarBubbleSignin";
+      case AccessPoint::ACCESS_POINT_USER_MANAGER:
+        return "UserManager";
+      case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
+        return "DevicesPage";
+      case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
+        return "CloudPrint";
+      case AccessPoint::ACCESS_POINT_CONTENT_AREA:
+        return "ContentArea";
+      case AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
+        return "SigninPromo";
+      case AccessPoint::ACCESS_POINT_RECENT_TABS:
+        return "RecentTabs";
+      case AccessPoint::ACCESS_POINT_UNKNOWN:
+        return "UnknownAccessPoint";
+      case AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
+        return "PasswordBubble";
+      case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
+        return "AutofillDropdown";
+      case AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
+        return "NTPContentSuggestions";
+      case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
+        return "ReSigninInfobar";
+      case AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+        return "TabSwitcher";
+      case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING:
+        return "ForceSigninWarning";
+      case AccessPoint::ACCESS_POINT_MAX:
+        NOTREACHED();
+        return "";
+    }
+    NOTREACHED();
+    return "";
+  }
+
+  static std::vector<AccessPoint> GetAllAccessPoints() {
+    std::vector<AccessPoint> access_points;
+    for (int ap = 0; ap < static_cast<int>(AccessPoint::ACCESS_POINT_MAX);
+         ++ap) {
+      access_points.push_back(static_cast<AccessPoint>(ap));
+    }
+    return access_points;
+  }
+};
+
+TEST_F(SigninMetricsTest, RecordSigninUserActionForAccessPoint) {
+  for (const AccessPoint& ap : GetAllAccessPoints()) {
+    base::UserActionTester user_action_tester;
+    RecordSigninUserActionForAccessPoint(ap);
+    EXPECT_EQ(1, user_action_tester.GetActionCount(
+                     "Signin_Signin_From" + GetAccessPointDescription(ap)));
+  }
+}
+
+TEST_F(SigninMetricsTest, RecordSigninImpressionUserAction) {
+  for (const AccessPoint& ap : kAccessPointsThatSupportImpression) {
+    base::UserActionTester user_action_tester;
+    RecordSigninImpressionUserActionForAccessPoint(ap);
+    EXPECT_EQ(1, user_action_tester.GetActionCount(
+                     "Signin_Impression_From" + GetAccessPointDescription(ap)));
+  }
+}
+
+TEST_F(SigninMetricsTest, RecordSigninImpressionWithAccountUserAction) {
+  for (const AccessPoint& ap : kAccessPointsThatSupportImpressionWithAccount) {
+    base::UserActionTester user_action_tester;
+    RecordSigninImpressionWithAccountUserActionForAccessPoint(ap, true);
+    EXPECT_EQ(1, user_action_tester.GetActionCount(
+                     "Signin_ImpressionWithAccount_From" +
+                     GetAccessPointDescription(ap)));
+  }
+}
+
+TEST_F(SigninMetricsTest, RecordSigninImpressionWithNoAccountUserAction) {
+  for (const AccessPoint& ap : kAccessPointsThatSupportImpressionWithAccount) {
+    base::UserActionTester user_action_tester;
+    RecordSigninImpressionWithAccountUserActionForAccessPoint(ap, false);
+    EXPECT_EQ(1, user_action_tester.GetActionCount(
+                     "Signin_ImpressionWithNoAccount_From" +
+                     GetAccessPointDescription(ap)));
+  }
+}
+
+}  // namespace
+}  // namespace signin_metrics
diff --git a/components/strings/components_strings_zh-CN.xtb b/components/strings/components_strings_zh-CN.xtb
index 22f14b6..9f27a73 100644
--- a/components/strings/components_strings_zh-CN.xtb
+++ b/components/strings/components_strings_zh-CN.xtb
@@ -495,6 +495,7 @@
 <translation id="4325863107915753736">找不到文章</translation>
 <translation id="4326324639298822553">请检查您的信用卡到期日期,然后重试</translation>
 <translation id="4331708818696583467">不安全</translation>
+<translation id="4340982228985273705">系统检测到,此计算机不是由企业管理,因此政策只能自动安装 Chrome 网上应用店中托管的扩展程序。对应的 Chrome 网上应用店更新网址为“<ph name="CWS_UPDATE_URL" />”。</translation>
 <translation id="4346197816712207223">接受的信用卡</translation>
 <translation id="4356973930735388585">此网站上的攻击者可能会试图在您的计算机上安装危险程序,以窃取或删除您的信息(例如:照片、密码、通讯内容和信用卡信息)。</translation>
 <translation id="4372948949327679948">应使用<ph name="VALUE_TYPE" />值。</translation>
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index f84f851..74400c86 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -12,6 +12,16 @@
 
 namespace syncer {
 
+void FakeSyncService::SetAuthenticatedAccountInfo(
+    const AccountInfo& account_info) {
+  account_info_ = account_info;
+}
+AccountInfo FakeSyncService::GetAuthenticatedAccountInfo() const {
+  return account_info_;
+}
+
+// Dummy methods
+
 FakeSyncService::FakeSyncService()
     : error_(GoogleServiceAuthError::NONE),
       user_share_(std::make_unique<UserShare>()) {}
@@ -205,10 +215,6 @@
 void FakeSyncService::GetAllNodes(
     const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback) {}
 
-AccountInfo FakeSyncService::GetAuthenticatedAccountInfo() const {
-  return AccountInfo();
-}
-
 GlobalIdMapper* FakeSyncService::GetGlobalIdMapper() const {
   return nullptr;
 }
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index d06f73c..1efece9 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <utility>
 
+#include "components/signin/core/browser/account_info.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/engine/cycle/sync_cycle_snapshot.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -28,7 +29,11 @@
     error_ = std::move(error);
   }
 
+  void SetAuthenticatedAccountInfo(const AccountInfo& account_info);
+  AccountInfo GetAuthenticatedAccountInfo() const override;
+
  private:
+  // Dummy methods.
   // SyncService implementation.
   bool IsFirstSetupComplete() const override;
   bool IsSyncAllowed() const override;
@@ -88,7 +93,6 @@
   base::WeakPtr<JsController> GetJsController() override;
   void GetAllNodes(const base::Callback<void(std::unique_ptr<base::ListValue>)>&
                        callback) override;
-  AccountInfo GetAuthenticatedAccountInfo() const override;
   GlobalIdMapper* GetGlobalIdMapper() const override;
 
   // DataTypeEncryptionHandler implementation.
@@ -102,6 +106,8 @@
   GURL sync_service_url_;
   std::string unrecoverable_error_message_;
   std::unique_ptr<UserShare> user_share_;
+
+  AccountInfo account_info_;
 };
 
 }  // namespace syncer
diff --git a/components/sync/user_events/DEPS b/components/sync/user_events/DEPS
index 4333254..7aaea56 100644
--- a/components/sync/user_events/DEPS
+++ b/components/sync/user_events/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/keyed_service/core",
+  "+components/signin/core/browser",
   "+components/sync/base",
   "+components/sync/driver",
   "+components/sync/model",
diff --git a/components/sync/user_events/user_event_service_impl_unittest.cc b/components/sync/user_events/user_event_service_impl_unittest.cc
index 55257af..dd838ac 100644
--- a/components/sync/user_events/user_event_service_impl_unittest.cc
+++ b/components/sync/user_events/user_event_service_impl_unittest.cc
@@ -50,7 +50,7 @@
 
 std::unique_ptr<UserEventSpecifics> AsConsent(
     std::unique_ptr<UserEventSpecifics> specifics) {
-  specifics->mutable_user_consent();
+  specifics->mutable_user_consent()->set_account_id("account_id");
   return specifics;
 }
 
@@ -61,6 +61,7 @@
   return specifics;
 }
 
+// TODO(vitaliii): Merge this into FakeSyncService and use it instead.
 class TestSyncService : public FakeSyncService {
  public:
   TestSyncService(bool is_engine_initialized,
@@ -101,7 +102,7 @@
         ModelTypeStoreTestUtil::FactoryForInMemoryStoreForTest(),
         RecordingModelTypeChangeProcessor::CreateProcessorAndAssignRawPointer(
             &processor_),
-        &mapper_);
+        &mapper_, &sync_service_);
   }
 
   TestSyncService* sync_service() { return &sync_service_; }
diff --git a/components/sync/user_events/user_event_sync_bridge.cc b/components/sync/user_events/user_event_sync_bridge.cc
index 4fea75d..ec090f1 100644
--- a/components/sync/user_events/user_event_sync_bridge.cc
+++ b/components/sync/user_events/user_event_sync_bridge.cc
@@ -15,6 +15,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "components/signin/core/browser/account_info.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/mutable_data_batch.h"
@@ -70,11 +71,14 @@
 UserEventSyncBridge::UserEventSyncBridge(
     OnceModelTypeStoreFactory store_factory,
     std::unique_ptr<ModelTypeChangeProcessor> change_processor,
-    GlobalIdMapper* global_id_mapper)
+    GlobalIdMapper* global_id_mapper,
+    SyncService* sync_service)
     : ModelTypeSyncBridge(std::move(change_processor)),
       global_id_mapper_(global_id_mapper),
+      sync_service_(sync_service),
       is_sync_starting_or_started_(false) {
   DCHECK(global_id_mapper_);
+  DCHECK(sync_service_);
   std::move(store_factory)
       .Run(USER_EVENTS, base::BindOnce(&UserEventSyncBridge::OnStoreCreated,
                                        base::AsWeakPtr(this)));
@@ -152,6 +156,7 @@
 void UserEventSyncBridge::OnSyncStarting(
     const ModelErrorHandler& error_handler,
     const ModelTypeChangeProcessor::StartCallback& start_callback) {
+  DCHECK(!GetAuthenticatedAccountId().empty());
   change_processor()->OnSyncStarting(std::move(error_handler), start_callback);
 
   bool was_sync_starting_or_started = is_sync_starting_or_started_;
@@ -232,7 +237,8 @@
     auto specifics = std::make_unique<UserEventSpecifics>();
     if (specifics->ParseFromString(r.value) &&
         specifics->event_case() ==
-            UserEventSpecifics::EventCase::kUserConsent) {
+            UserEventSpecifics::EventCase::kUserConsent &&
+        specifics->user_consent().account_id() == GetAuthenticatedAccountId()) {
       RecordUserEventImpl(std::move(specifics));
     }
   }
@@ -240,6 +246,8 @@
 
 void UserEventSyncBridge::RecordUserEvent(
     std::unique_ptr<UserEventSpecifics> specifics) {
+  DCHECK(!specifics->has_user_consent() ||
+         !specifics->user_consent().account_id().empty());
   if (change_processor()->IsTrackingMetadata()) {
     RecordUserEventImpl(std::move(specifics));
     return;
@@ -380,4 +388,8 @@
   }
 }
 
+std::string UserEventSyncBridge::GetAuthenticatedAccountId() const {
+  return sync_service_->GetAuthenticatedAccountInfo().account_id;
+}
+
 }  // namespace syncer
diff --git a/components/sync/user_events/user_event_sync_bridge.h b/components/sync/user_events/user_event_sync_bridge.h
index f72ef074..a9797a3 100644
--- a/components/sync/user_events/user_event_sync_bridge.h
+++ b/components/sync/user_events/user_event_sync_bridge.h
@@ -14,6 +14,7 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
+#include "components/sync/driver/sync_service.h"
 #include "components/sync/model/model_type_change_processor.h"
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/model/model_type_sync_bridge.h"
@@ -26,7 +27,8 @@
   UserEventSyncBridge(
       OnceModelTypeStoreFactory store_factory,
       std::unique_ptr<ModelTypeChangeProcessor> change_processor,
-      GlobalIdMapper* global_id_mapper);
+      GlobalIdMapper* global_id_mapper,
+      SyncService* sync_service);
   ~UserEventSyncBridge() override;
 
   // ModelTypeSyncBridge implementation.
@@ -82,6 +84,8 @@
 
   void HandleGlobalIdChange(int64_t old_global_id, int64_t new_global_id);
 
+  std::string GetAuthenticatedAccountId() const;
+
   // Persistent storage for in flight events. Should remain quite small, as we
   // delete upon commit confirmation.
   std::unique_ptr<ModelTypeStore> store_;
@@ -96,6 +100,7 @@
       in_flight_nav_linked_events_;
 
   GlobalIdMapper* global_id_mapper_;
+  SyncService* sync_service_;
 
   bool is_sync_starting_or_started_;
 
diff --git a/components/sync/user_events/user_event_sync_bridge_unittest.cc b/components/sync/user_events/user_event_sync_bridge_unittest.cc
index dce08e4..243f549b 100644
--- a/components/sync/user_events/user_event_sync_bridge_unittest.cc
+++ b/components/sync/user_events/user_event_sync_bridge_unittest.cc
@@ -25,7 +25,9 @@
 namespace {
 
 using sync_pb::UserEventSpecifics;
+using testing::_;
 using testing::ElementsAre;
+using testing::Eq;
 using testing::Invoke;
 using testing::IsEmpty;
 using testing::IsNull;
@@ -36,7 +38,6 @@
 using testing::SaveArg;
 using testing::SizeIs;
 using testing::UnorderedElementsAre;
-using testing::_;
 using WriteBatch = ModelTypeStore::WriteBatch;
 
 MATCHER_P(MatchesUserEvent, expected, "") {
@@ -100,7 +101,8 @@
   UserEventSyncBridgeTest() {
     bridge_ = std::make_unique<UserEventSyncBridge>(
         ModelTypeStoreTestUtil::FactoryForInMemoryStoreForTest(),
-        mock_processor_.CreateForwardingProcessor(), &test_global_id_mapper_);
+        mock_processor_.CreateForwardingProcessor(), &test_global_id_mapper_,
+        &fake_sync_service_);
     ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(true));
     ON_CALL(*processor(), DisableSync()).WillByDefault(Invoke([this]() {
       bridge_->ApplyDisableSyncChanges(WriteBatch::CreateMetadataChangeList());
@@ -115,6 +117,7 @@
 
   UserEventSyncBridge* bridge() { return bridge_.get(); }
   MockModelTypeChangeProcessor* processor() { return &mock_processor_; }
+  FakeSyncService* sync_service() { return &fake_sync_service_; }
   TestGlobalIdMapper* mapper() { return &test_global_id_mapper_; }
 
   std::map<std::string, sync_pb::EntitySpecifics> GetAllData() {
@@ -170,6 +173,7 @@
   std::unique_ptr<UserEventSyncBridge> bridge_;
   testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
   TestGlobalIdMapper test_global_id_mapper_;
+  FakeSyncService fake_sync_service_;
   base::MessageLoop message_loop_;
 };
 
@@ -204,11 +208,12 @@
 }
 
 TEST_F(UserEventSyncBridgeTest, DisableSyncShouldKeepConsents) {
-  UserEventSpecifics user_consent_specifics(CreateSpecifics(2u, 2u, 2u));
-  auto* consent = user_consent_specifics.mutable_user_consent();
+  UserEventSpecifics user_event_specifics(CreateSpecifics(2u, 2u, 2u));
+  auto* consent = user_event_specifics.mutable_user_consent();
   consent->set_feature(UserEventSpecifics::UserConsent::CHROME_SYNC);
+  consent->set_account_id("account_id");
   bridge()->RecordUserEvent(
-      std::make_unique<UserEventSpecifics>(user_consent_specifics));
+      std::make_unique<UserEventSpecifics>(user_event_specifics));
   ASSERT_THAT(GetAllData(), SizeIs(1));
 
   EXPECT_CALL(*processor(), DisableSync());
@@ -218,7 +223,7 @@
 
   // User consent specific must be persisted when sync is disabled.
   EXPECT_THAT(GetAllData(),
-              ElementsAre(Pair(_, MatchesUserEvent(user_consent_specifics))));
+              ElementsAre(Pair(_, MatchesUserEvent(user_event_specifics))));
 }
 
 TEST_F(UserEventSyncBridgeTest, MultipleRecords) {
@@ -351,9 +356,9 @@
   base::RunLoop().RunUntilIdle();
 
   UserEventSpecifics consent1 = CreateSpecifics(1u, 1u, 1u);
-  consent1.mutable_user_consent();
+  consent1.mutable_user_consent()->set_account_id("account_id");
   UserEventSpecifics consent2 = CreateSpecifics(2u, 2u, 2u);
-  consent2.mutable_user_consent();
+  consent2.mutable_user_consent()->set_account_id("account_id");
   UserEventSpecifics specifics1 = CreateSpecifics(3u, 3u, 3u);
   UserEventSpecifics specifics2 = CreateSpecifics(4u, 4u, 4u);
 
@@ -366,7 +371,7 @@
             store_init_type = type;
             store_init_callback = std::move(callback);
           }),
-      processor()->CreateForwardingProcessor(), mapper());
+      processor()->CreateForwardingProcessor(), mapper(), sync_service());
 
   // Record events before the store is created. Only the consent will be
   // buffered, the other event is dropped.
@@ -381,7 +386,11 @@
   std::move(store_init_callback)
       .Run(/*error=*/base::nullopt,
            ModelTypeStoreTestUtil::CreateInMemoryStoreForTest(store_init_type));
+  base::RunLoop().RunUntilIdle();
 
+  AccountInfo info;
+  info.account_id = "account_id";
+  sync_service()->SetAuthenticatedAccountInfo(info);
   late_init_bridge.OnSyncStarting(/*error_handler=*/base::DoNothing(),
                                   /*start_callback=*/base::DoNothing());
 
@@ -403,7 +412,7 @@
 TEST_F(UserEventSyncBridgeTest,
        ShouldReportPreviouslyPersistedConsentsWhenSyncIsReenabled) {
   UserEventSpecifics consent = CreateSpecifics(1u, 1u, 1u);
-  consent.mutable_user_consent();
+  consent.mutable_user_consent()->set_account_id("account_id");
 
   bridge()->RecordUserEvent(std::make_unique<UserEventSpecifics>(consent));
 
@@ -415,6 +424,9 @@
   ASSERT_THAT(GetAllData(), SizeIs(1));
 
   // Reenable sync.
+  AccountInfo info;
+  info.account_id = "account_id";
+  sync_service()->SetAuthenticatedAccountInfo(info);
   ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(true));
   std::string storage_key;
   EXPECT_CALL(*processor(), DoPut(_, _, _)).WillOnce(SaveArg<0>(&storage_key));
@@ -424,7 +436,7 @@
   // The bridge may asynchronously query the store to choose what to resubmit.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_THAT(storage_key, GetStorageKey(consent));
+  EXPECT_THAT(storage_key, Eq(GetStorageKey(consent)));
 }
 
 TEST_F(UserEventSyncBridgeTest,
@@ -433,7 +445,7 @@
   base::RunLoop().RunUntilIdle();
 
   UserEventSpecifics consent = CreateSpecifics(1u, 1u, 1u);
-  consent.mutable_user_consent();
+  consent.mutable_user_consent()->set_account_id("account_id");
 
   ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(false));
   ModelType store_init_type;
@@ -444,9 +456,12 @@
             store_init_type = type;
             store_init_callback = std::move(callback);
           }),
-      processor()->CreateForwardingProcessor(), mapper());
+      processor()->CreateForwardingProcessor(), mapper(), sync_service());
 
   // Sync is active, but the store is not ready yet.
+  AccountInfo info;
+  info.account_id = "account_id";
+  sync_service()->SetAuthenticatedAccountInfo(info);
   EXPECT_CALL(*processor(), DoModelReadyToSync(_, _)).Times(0);
   late_init_bridge.OnSyncStarting(/*error_handler=*/base::DoNothing(),
                                   /*start_callback=*/base::DoNothing());
@@ -477,7 +492,7 @@
   // The bridge may asynchronously query the store to choose what to resubmit.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_THAT(storage_key, GetStorageKey(consent));
+  EXPECT_THAT(storage_key, Eq(GetStorageKey(consent)));
 }
 
 TEST_F(UserEventSyncBridgeTest,
@@ -486,7 +501,7 @@
   base::RunLoop().RunUntilIdle();
 
   UserEventSpecifics consent = CreateSpecifics(1u, 1u, 1u);
-  consent.mutable_user_consent();
+  consent.mutable_user_consent()->set_account_id("account_id");
 
   ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(false));
   ModelType store_init_type;
@@ -497,7 +512,7 @@
             store_init_type = type;
             store_init_callback = std::move(callback);
           }),
-      processor()->CreateForwardingProcessor(), mapper());
+      processor()->CreateForwardingProcessor(), mapper(), sync_service());
 
   // Initialize the store.
   std::unique_ptr<ModelTypeStore> store =
@@ -522,6 +537,9 @@
            ModelTypeStoreTestUtil::CreateInMemoryStoreForTest(store_init_type));
   base::RunLoop().RunUntilIdle();
 
+  AccountInfo info;
+  info.account_id = "account_id";
+  sync_service()->SetAuthenticatedAccountInfo(info);
   late_init_bridge.OnSyncStarting(/*error_handler=*/base::DoNothing(),
                                   /*start_callback=*/base::DoNothing());
 
@@ -530,7 +548,56 @@
   // The bridge may asynchronously query the store to choose what to resubmit.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_THAT(storage_key, GetStorageKey(consent));
+  EXPECT_THAT(storage_key, Eq(GetStorageKey(consent)));
+}
+
+TEST_F(UserEventSyncBridgeTest, ShouldSubmitPersistedConsentOnlyIfSameAccount) {
+  AccountInfo info;
+  info.account_id = "first_account";
+  sync_service()->SetAuthenticatedAccountInfo(info);
+  UserEventSpecifics user_event_specifics(CreateSpecifics(2u, 2u, 2u));
+  auto* consent = user_event_specifics.mutable_user_consent();
+  consent->set_account_id("first_account");
+  bridge()->RecordUserEvent(
+      std::make_unique<UserEventSpecifics>(user_event_specifics));
+  ASSERT_THAT(GetAllData(), SizeIs(1));
+
+  EXPECT_CALL(*processor(), DisableSync());
+  bridge()->DisableSync();
+  // The bridge may asynchronously query the store to choose what to delete.
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_THAT(GetAllData(),
+              ElementsAre(Pair(_, MatchesUserEvent(user_event_specifics))));
+
+  // A new user signs in and enables sync.
+  info.account_id = "second_account";
+  sync_service()->SetAuthenticatedAccountInfo(info);
+
+  // The previous account consent should not be resubmited, because the new sync
+  // account is different.
+  EXPECT_CALL(*processor(), DoPut(_, _, _)).Times(0);
+  ON_CALL(*processor(), IsTrackingMetadata()).WillByDefault(Return(true));
+  bridge()->OnSyncStarting(/*error_handler=*/base::DoNothing(),
+                           /*start_callback=*/base::DoNothing());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_CALL(*processor(), DisableSync());
+  bridge()->DisableSync();
+  base::RunLoop().RunUntilIdle();
+
+  // The previous user signs in again and enables sync.
+  info.account_id = "first_account";
+  sync_service()->SetAuthenticatedAccountInfo(info);
+
+  std::string storage_key;
+  EXPECT_CALL(*processor(), DoPut(_, _, _)).WillOnce(SaveArg<0>(&storage_key));
+  bridge()->OnSyncStarting(/*error_handler=*/base::DoNothing(),
+                           /*start_callback=*/base::DoNothing());
+  // The bridge may asynchronously query the store to choose what to resubmit.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_THAT(storage_key, Eq(GetStorageKey(user_event_specifics)));
 }
 
 }  // namespace
diff --git a/components/visitedlink/test/visitedlink_unittest.cc b/components/visitedlink/test/visitedlink_unittest.cc
index c52317b..6e2b903 100644
--- a/components/visitedlink/test/visitedlink_unittest.cc
+++ b/components/visitedlink/test/visitedlink_unittest.cc
@@ -34,6 +34,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -528,11 +529,11 @@
         add_event_count_(0),
         reset_event_count_(0),
         completely_reset_event_count_(0),
-        new_table_count_(0),
-        binding_(this) {}
+        new_table_count_(0) {}
 
   void Bind(mojo::ScopedMessagePipeHandle handle) {
-    binding_.Bind(mojom::VisitedLinkNotificationSinkRequest(std::move(handle)));
+    binding_.AddBinding(
+        this, mojom::VisitedLinkNotificationSinkRequest(std::move(handle)));
   }
 
   void WaitForUpdate() {
@@ -543,7 +544,7 @@
 
   void WaitForNoUpdate() { binding_.FlushForTesting(); }
 
-  mojo::Binding<mojom::VisitedLinkNotificationSink>& binding() {
+  mojo::BindingSet<mojom::VisitedLinkNotificationSink>& binding() {
     return binding_;
   }
 
@@ -588,7 +589,9 @@
   int new_table_count_;
 
   base::Closure quit_closure_;
-  mojo::Binding<mojom::VisitedLinkNotificationSink> binding_;
+  mojo::BindingSet<mojom::VisitedLinkNotificationSink> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(VisitCountingContext);
 };
 
 // Stub out as little as possible, borrowing from RenderProcessHost.
@@ -835,11 +838,13 @@
   VisitRelayingRenderProcessHost different_process_host(&different_context,
                                                         &counting_context);
 
+  size_t old_size = counting_context.binding().size();
   content::NotificationService::current()->Notify(
       content::NOTIFICATION_RENDERER_PROCESS_CREATED,
       content::Source<content::RenderProcessHost>(&different_process_host),
       content::NotificationService::NoDetails());
-  EXPECT_FALSE(counting_context.binding().is_bound());
+  size_t new_size = counting_context.binding().size();
+  EXPECT_EQ(old_size, new_size);
 }
 
 class VisitedLinkCompletelyResetEventTest : public VisitedLinkEventsTest {
diff --git a/components/viz/service/display/surface_aggregator_pixeltest.cc b/components/viz/service/display/surface_aggregator_pixeltest.cc
index 7b90734..5491915 100644
--- a/components/viz/service/display/surface_aggregator_pixeltest.cc
+++ b/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -93,9 +93,9 @@
   auto root_frame =
       CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
 
-  LocalSurfaceId root_local_surface_id = allocator_.GenerateId();
-  SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id);
-  support_->SubmitCompositorFrame(root_local_surface_id, std::move(root_frame));
+  SurfaceId root_surface_id(support_->frame_sink_id(), allocator_.GenerateId());
+  support_->SubmitCompositorFrame(allocator_.GetCurrentLocalSurfaceId(),
+                                  std::move(root_frame));
 
   SurfaceAggregator aggregator(manager_.surface_manager(),
                                resource_provider_.get(), true);
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc
index d812980e..45b17814 100644
--- a/components/viz/service/display_embedder/gpu_display_provider.cc
+++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -130,7 +130,7 @@
       output_surface = std::make_unique<GLOutputSurfaceOzone>(
           std::move(context_provider), surface_handle,
           synthetic_begin_frame_source.get(), gpu_memory_buffer_manager_.get(),
-          GL_TEXTURE_2D, GL_RGB);
+          GL_TEXTURE_2D, GL_BGRA_EXT);
 #elif defined(OS_MACOSX)
       output_surface = std::make_unique<GLOutputSurfaceMac>(
           std::move(context_provider), surface_handle,
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 9da04f9..d1e6e7d2 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -94,6 +94,33 @@
 
 #endif  // OS_POSIX
 
+#if defined(OS_LINUX)
+#include "base/native_library.h"
+#include "base/rand_util.h"
+#include "content/common/font_config_ipc_linux.h"
+#include "content/public/common/common_sandbox_support_linux.h"
+#include "third_party/blink/public/platform/web_font_render_style.h"
+#include "third_party/boringssl/src/include/openssl/crypto.h"
+#include "third_party/boringssl/src/include/openssl/rand.h"
+#include "third_party/skia/include/ports/SkFontConfigInterface.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkFontMgr_android.h"
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/common/pepper_plugin_list.h"
+#include "content/public/common/pepper_plugin_info.h"
+#endif
+
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+#include "content/public/common/cdm_info.h"
+#include "content/public/common/content_client.h"
+#endif
+
+#if BUILDFLAG(ENABLE_WEBRTC)
+#include "third_party/webrtc_overrides/init_webrtc.h"  // nogncheck
+#endif
+#endif  // OS_LINUX
+
 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
 #include "content/public/gpu/content_gpu_client.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -305,6 +332,109 @@
 }
 #endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
 
+#if defined(OS_LINUX)
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+// Loads the (native) libraries but does not initialize them (i.e., does not
+// call PPP_InitializeModule). This is needed by the zygote on Linux to get
+// access to the plugins before entering the sandbox.
+void PreloadPepperPlugins() {
+  std::vector<PepperPluginInfo> plugins;
+  ComputePepperPluginList(&plugins);
+  for (const auto& plugin : plugins) {
+    if (!plugin.is_internal) {
+      base::NativeLibraryLoadError error;
+      base::NativeLibrary library =
+          base::LoadNativeLibrary(plugin.path, &error);
+      VLOG_IF(1, !library) << "Unable to load plugin " << plugin.path.value()
+                           << " " << error.ToString();
+
+      ignore_result(library);  // Prevent release-mode warning.
+    }
+  }
+}
+#endif
+
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+// Loads registered library CDMs but does not initialize them. This is needed by
+// the zygote on Linux to get access to the CDMs before entering the sandbox.
+void PreloadLibraryCdms() {
+  std::vector<CdmInfo> cdms;
+  GetContentClient()->AddContentDecryptionModules(&cdms, nullptr);
+  for (const auto& cdm : cdms) {
+    base::NativeLibraryLoadError error;
+    base::NativeLibrary library = base::LoadNativeLibrary(cdm.path, &error);
+    VLOG_IF(1, !library) << "Unable to load CDM " << cdm.path.value()
+                         << " (error: " << error.ToString() << ")";
+    ignore_result(library);  // Prevent release-mode warning.
+  }
+}
+#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
+
+#if BUILDFLAG(USE_ZYGOTE_HANDLE)
+void PreSandboxInit() {
+#if defined(ARCH_CPU_ARM_FAMILY)
+  // On ARM, BoringSSL requires access to /proc/cpuinfo to determine processor
+  // features. Query this before entering the sandbox.
+  CRYPTO_library_init();
+#endif
+
+  // Pass BoringSSL a copy of the /dev/urandom file descriptor so RAND_bytes
+  // will work inside the sandbox.
+  RAND_set_urandom_fd(base::GetUrandomFD());
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+  // Ensure access to the Pepper plugins before the sandbox is turned on.
+  PreloadPepperPlugins();
+#endif
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+  // Ensure access to the library CDMs before the sandbox is turned on.
+  PreloadLibraryCdms();
+#endif
+#if BUILDFLAG(ENABLE_WEBRTC)
+  InitializeWebRtcModule();
+#endif
+
+  SkFontConfigInterface::SetGlobal(new FontConfigIPC(GetSandboxFD()))->unref();
+
+  // Set the android SkFontMgr for blink. We need to ensure this is done
+  // before the sandbox is initialized to allow the font manager to access
+  // font configuration files on disk.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kAndroidFontsPath)) {
+    std::string android_fonts_dir =
+        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+            switches::kAndroidFontsPath);
+
+    if (android_fonts_dir.size() > 0 && android_fonts_dir.back() != '/')
+      android_fonts_dir += '/';
+
+    SkFontMgr_Android_CustomFonts custom;
+    custom.fSystemFontUse =
+        SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
+    custom.fBasePath = android_fonts_dir.c_str();
+
+    std::string font_config;
+    std::string fallback_font_config;
+    if (android_fonts_dir.find("kitkat") != std::string::npos) {
+      font_config = android_fonts_dir + "system_fonts.xml";
+      fallback_font_config = android_fonts_dir + "fallback_fonts.xml";
+      custom.fFallbackFontsXml = fallback_font_config.c_str();
+    } else {
+      font_config = android_fonts_dir + "fonts.xml";
+      custom.fFallbackFontsXml = nullptr;
+    }
+    custom.fFontsXml = font_config.c_str();
+    custom.fIsolated = true;
+
+    blink::WebFontRenderStyle::SetSkiaFontManager(
+        SkFontMgr_New_Android(&custom));
+  }
+}
+#endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
+
+#endif  // OS_LINUX
+
 }  // namespace
 
 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
@@ -393,6 +523,10 @@
     media::InitializeMediaLibrary();
   }
 
+#if defined(OS_LINUX)
+  PreSandboxInit();
+#endif
+
   // This function call can return multiple times, once per fork().
   if (!ZygoteMain(std::move(zygote_fork_delegates)))
     return 1;
diff --git a/content/browser/child_process_security_policy_browsertest.cc b/content/browser/child_process_security_policy_browsertest.cc
index 412b31f5..a308f42 100644
--- a/content/browser/child_process_security_policy_browsertest.cc
+++ b/content/browser/child_process_security_policy_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_path.h"
 #include "build/build_config.h"
 #include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -46,8 +47,8 @@
 
   NavigateToURL(shell(), url);
   EXPECT_EQ(
-      ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size(),
-          1U);
+      RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
+      ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size());
 
   WebContents* web_contents = shell()->web_contents();
   content::RenderProcessHostWatcher exit_observer(
@@ -58,7 +59,7 @@
 
   web_contents->GetController().Reload(ReloadType::NORMAL, true);
   EXPECT_EQ(
-      1U,
+      RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
       ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size());
 }
 
diff --git a/content/browser/devtools/devtools_url_interceptor_request_job.cc b/content/browser/devtools/devtools_url_interceptor_request_job.cc
index 8851a3a2..3c9d31b7 100644
--- a/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -669,10 +669,14 @@
 
 bool DevToolsURLInterceptorRequestJob::GetMimeType(
     std::string* mime_type) const {
+  if (sub_request_) {
+    sub_request_->request()->GetMimeType(mime_type);
+    return true;
+  }
   const net::HttpResponseHeaders* response_headers = GetHttpResponseHeaders();
-  if (!response_headers)
-    return false;
-  return response_headers->GetMimeType(mime_type);
+  if (response_headers)
+    return response_headers->GetMimeType(mime_type);
+  return false;
 }
 
 bool DevToolsURLInterceptorRequestJob::GetCharset(std::string* charset) {
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 23235d3..ee48fdd3 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -30,6 +30,7 @@
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/renderer_host/display_util.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/web_contents/web_contents_view.h"
 #include "content/common/frame_messages.h"
@@ -7817,6 +7818,79 @@
   EXPECT_EQ(0U, entry->root_node()->children[0]->children.size());
 }
 
+// This test supplements SpareRenderProcessHostUnitTest to verify that the spare
+// RenderProcessHost is actually used in cross-process navigations.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+                       UtilizationOfSpareRenderProcessHost) {
+  GURL first_url = embedded_test_server()->GetURL("a.com", "/title1.html");
+  GURL second_url = embedded_test_server()->GetURL("b.com", "/title2.html");
+  RenderProcessHost* prev_spare = nullptr;
+  RenderProcessHost* curr_spare = nullptr;
+  RenderProcessHost* prev_host = nullptr;
+  RenderProcessHost* curr_host = nullptr;
+
+  // In the current implementation the spare is not warmed-up until the first
+  // real navigation.  It might be okay to change that in the future.
+  curr_spare = RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  curr_host = shell()->web_contents()->GetMainFrame()->GetProcess();
+  EXPECT_FALSE(curr_spare);
+
+  // Navigate to the first URL.
+  prev_host = curr_host;
+  prev_spare = curr_spare;
+  EXPECT_TRUE(NavigateToURL(shell(), first_url));
+  curr_spare = RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  curr_host = shell()->web_contents()->GetMainFrame()->GetProcess();
+  EXPECT_NE(curr_spare, curr_host);
+  // No process swap when navigating away from the initial blank page.
+  EXPECT_EQ(prev_host, curr_host);
+  // We should always keep a spare RenderProcessHost around in site-per-process
+  // mode.  We don't assert what should happen in other scenarios (to give
+  // flexibility to platform-specific decisions - e.g. on the desktop there
+  // might be no spare outside of site-per-process, but on Android the spare
+  // might still be opportunistically warmed up).
+  if (AreAllSitesIsolatedForTesting())
+    EXPECT_TRUE(curr_spare);
+
+  // Perform a cross-site omnibox navigation.
+  prev_host = curr_host;
+  prev_spare = curr_spare;
+  EXPECT_TRUE(NavigateToURL(shell(), second_url));
+  curr_spare = RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  curr_host = shell()->web_contents()->GetMainFrame()->GetProcess();
+  // The cross-site omnibox navigation should swap processes.
+  EXPECT_NE(prev_host, curr_host);
+  // If present, the spare RenderProcessHost should have been be used.
+  if (prev_spare)
+    EXPECT_EQ(prev_spare, curr_host);
+  // A new spare should be warmed-up in site-per-process mode.
+  if (AreAllSitesIsolatedForTesting()) {
+    EXPECT_TRUE(curr_spare);
+    EXPECT_NE(prev_spare, curr_spare);
+  }
+
+  // Perform a back navigation.
+  prev_host = curr_host;
+  prev_spare = curr_spare;
+  TestNavigationObserver back_load_observer(shell()->web_contents());
+  NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+      shell()->web_contents()->GetController());
+  controller.GoBack();
+  back_load_observer.Wait();
+  curr_spare = RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  curr_host = shell()->web_contents()->GetMainFrame()->GetProcess();
+  // The cross-site back navigation should swap processes.
+  EXPECT_NE(prev_host, curr_host);
+  // If present, the spare RenderProcessHost should have been used.
+  if (prev_spare)
+    EXPECT_EQ(prev_spare, curr_host);
+  // A new spare should be warmed-up in site-per-process mode.
+  if (AreAllSitesIsolatedForTesting()) {
+    EXPECT_TRUE(curr_spare);
+    EXPECT_NE(prev_spare, curr_spare);
+  }
+}
+
 class NavigationControllerControllableResponseBrowserTest
     : public ContentBrowserTest {
  protected:
diff --git a/content/browser/frame_host/navigation_entry_screenshot_manager.cc b/content/browser/frame_host/navigation_entry_screenshot_manager.cc
index 0e40ca12..0b8b2df 100644
--- a/content/browser/frame_host/navigation_entry_screenshot_manager.cc
+++ b/content/browser/frame_host/navigation_entry_screenshot_manager.cc
@@ -93,8 +93,10 @@
 }
 
 void NavigationEntryScreenshotManager::TakeScreenshot() {
-  if (OverscrollConfig::GetMode() != OverscrollConfig::Mode::kParallaxUi)
+  if (OverscrollConfig::GetHistoryNavigationMode() !=
+      OverscrollConfig::HistoryNavigationMode::kParallaxUi) {
     return;
+  }
 
   NavigationEntryImpl* entry = owner_->GetLastCommittedEntry();
   if (!entry)
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 0d9c8ac..9d8ca86d 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -803,6 +803,15 @@
   speculative_site_instance_ =
       site_instance->HasProcess() ? site_instance : nullptr;
 
+  // If the new site instance doesn't yet have a process, then tell the
+  // SpareRenderProcessHostManager so it can decide whether to start warming up
+  // the spare at this time (note that the actual behavior depends on
+  // RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes).
+  if (!site_instance->HasProcess()) {
+    RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
+        site_instance->GetBrowserContext());
+  }
+
   // Check what the process of the SiteInstance is. It will be passed to the
   // NavigationHandle, and informed to expect a navigation to the redirected
   // URL.
@@ -1407,6 +1416,12 @@
       std::move(body_), common_params_, request_params_, is_view_source_,
       std::move(subresource_loader_params_), std::move(subresource_overrides_),
       devtools_navigation_token_);
+
+  // Give SpareRenderProcessHostManager a heads-up about the most recently used
+  // BrowserContext.  This is mostly needed to make sure the spare is warmed-up
+  // if it wasn't done in RenderProcessHostImpl::GetProcessHostForSiteInstance.
+  RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
+      render_frame_host->GetSiteInstance()->GetBrowserContext());
 }
 
 NavigationRequest::ContentSecurityPolicyCheckResult
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 682e5d6..33678d6 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1033,9 +1033,10 @@
     CHECK_NE(new_instance, current_instance);
 
   if (new_instance == current_instance) {
-    // If we're navigating to the same site instance, we won't need to use any
-    // spare RenderProcessHost.
-    RenderProcessHostImpl::CleanupSpareRenderProcessHost();
+    // If we're navigating to the same site instance, we won't need to use the
+    // current spare RenderProcessHost.
+    RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
+        browser_context);
   }
 
   // Double-check that the new SiteInstance is associated with the right
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 8c5afa6..90579b15 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
 #include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/view_messages.h"
@@ -198,6 +199,7 @@
   }
 
  protected:
+  ScopedMockRenderProcessHostFactory rph_factory_;
   TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<BrowserContext> browser_context_;
   MockRenderWidgetHostDelegate delegate_;
@@ -215,6 +217,7 @@
 
  private:
   viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest);
 };
 
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 0e759ef..7af0771 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -22,6 +22,7 @@
 #include "components/viz/common/features.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
@@ -54,10 +55,20 @@
   return command_line->HasSwitch(switches::kForceGpuRasterization);
 }
 
+gpu::GpuFeatureStatus SafeGetFeatureStatus(GpuDataManagerImpl* manager,
+                                           gpu::GpuFeatureType feature) {
+  if (!manager->IsGpuFeatureInfoAvailable()) {
+    // The GPU process probably crashed during startup, but we can't
+    // assert this as the test bots are slow, and recording the crash
+    // is racy. Be robust and just say that all features are disabled.
+    return gpu::kGpuFeatureStatusDisabled;
+  }
+  return manager->GetFeatureStatus(feature);
+}
+
 gpu::GpuFeatureStatus GetGpuCompositingStatus() {
-  gpu::GpuFeatureStatus status =
-      GpuDataManagerImpl::GetInstance()->GetFeatureStatus(
-          gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
+  gpu::GpuFeatureStatus status = SafeGetFeatureStatus(
+      GpuDataManagerImpl::GetInstance(), gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
 #if defined(USE_AURA) || defined(OS_MACOSX)
   if (status == gpu::kGpuFeatureStatusEnabled &&
       ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled()) {
@@ -71,11 +82,11 @@
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
-  DCHECK(manager->IsGpuFeatureInfoAvailable());
 
   const GpuFeatureData kGpuFeatureData[] = {
       {"2d_canvas",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
+       SafeGetFeatureStatus(manager,
+                            gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
        command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
        "Accelerated 2D canvas is unavailable: either disabled via blacklist or"
        " the command line.",
@@ -88,36 +99,37 @@
        " and hardware acceleration will be unavailable.",
        true},
       {"webgl",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL),
+       SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL),
        command_line.HasSwitch(switches::kDisableWebGL),
        "WebGL has been disabled via blacklist or the command line.", false},
-      {"flash_3d", manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH3D),
+      {"flash_3d", SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_FLASH3D),
        command_line.HasSwitch(switches::kDisableFlash3d),
        "Using 3d in flash has been disabled, either via blacklist, about:flags "
        "or"
        " the command line.",
        true},
       {"flash_stage3d",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+       SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
        command_line.HasSwitch(switches::kDisableFlashStage3d),
        "Using Stage3d in Flash has been disabled, either via blacklist,"
        " about:flags or the command line.",
        true},
       {"flash_stage3d_baseline",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE),
+       SafeGetFeatureStatus(manager,
+                            gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE),
        command_line.HasSwitch(switches::kDisableFlashStage3d),
        "Using Stage3d Baseline profile in Flash has been disabled, either"
        " via blacklist, about:flags or the command line.",
        true},
       {"video_decode",
-       manager->GetFeatureStatus(
-           gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
+       SafeGetFeatureStatus(manager,
+                            gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
        command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
        "Accelerated video decode has been disabled, either via blacklist,"
        " about:flags or the command line.",
        true},
       {"rasterization",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION),
+       SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION),
        (command_line.HasSwitch(switches::kDisableGpuRasterization) &&
         !IsForceGpuRasterizationEnabled()),
        "Accelerated rasterization has been disabled, either via blacklist,"
@@ -137,7 +149,7 @@
        "line.",
        false},
       {"webgl2",
-       manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2),
+       SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2),
        (command_line.HasSwitch(switches::kDisableWebGL) ||
         command_line.HasSwitch(switches::kDisableWebGL2)),
        "WebGL2 has been disabled via blacklist or the command line.", false},
diff --git a/content/browser/memory/memory_coordinator_impl_browsertest.cc b/content/browser/memory/memory_coordinator_impl_browsertest.cc
index 7df902f..9966aaf 100644
--- a/content/browser/memory/memory_coordinator_impl_browsertest.cc
+++ b/content/browser/memory/memory_coordinator_impl_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/browser_main_loop.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -34,7 +35,20 @@
 IN_PROC_BROWSER_TEST_F(MemoryCoordinatorImplBrowserTest, HandleAdded) {
   GURL url = GetTestUrl("", "simple_page.html");
   NavigateToURL(shell(), url);
-  size_t num_children = MemoryCoordinatorImpl::GetInstance()->children().size();
+
+  size_t num_children = 0;
+  for (auto const& it : MemoryCoordinatorImpl::GetInstance()->children()) {
+    int process_id = it.first;
+
+    // Ignore the spare process.
+    RenderProcessHost* spare_process =
+        RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+    if (spare_process && process_id == spare_process->GetID())
+      continue;
+
+    num_children++;
+  }
+
   EXPECT_EQ(1u, num_children);
 }
 
diff --git a/content/browser/power_monitor_browsertest.cc b/content/browser/power_monitor_browsertest.cc
index 57faba8..76132c1 100644
--- a/content/browser/power_monitor_browsertest.cc
+++ b/content/browser/power_monitor_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/utility_process_host.h"
 #include "content/browser/utility_process_host_client.h"
 #include "content/public/browser/browser_thread.h"
@@ -108,10 +109,15 @@
                         mojo::ScopedMessagePipeHandle handle,
                         const service_manager::BindSourceInfo& source_info) {
     if (source_info.identity.name() == mojom::kRendererServiceName) {
-      ++request_count_from_renderer_;
-
-      DCHECK(renderer_bound_closure_);
-      std::move(renderer_bound_closure_).Run();
+      // We can receive binding requests for the spare RenderProcessHost - this
+      // might happen before the test has provided the
+      // |renderer_bound_closure_|.
+      if (renderer_bound_closure_) {
+        ++request_count_from_renderer_;
+        std::move(renderer_bound_closure_).Run();
+      } else {
+        DCHECK(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+      }
     } else if (source_info.identity.name() == mojom::kUtilityServiceName) {
       ++request_count_from_utility_;
 
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index c7d3556..cdc42a2 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -19,7 +19,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/scoped_overscroll_mode.h"
+#include "content/public/test/scoped_overscroll_modes.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
@@ -857,7 +857,8 @@
 // This only happens in the gesture nav with parallax effect.
 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
                        HiddenAfterOverscroll) {
-  ScopedOverscrollMode scoped_mode(OverscrollConfig::Mode::kParallaxUi);
+  ScopedHistoryNavigationMode scoped_mode(
+      OverscrollConfig::HistoryNavigationMode::kParallaxUi);
 
   // Set the page up.
   ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
diff --git a/content/browser/renderer_host/overscroll_configuration.cc b/content/browser/renderer_host/overscroll_configuration.cc
index d7030f70..ddfc631b1 100644
--- a/content/browser/renderer_host/overscroll_configuration.cc
+++ b/content/browser/renderer_host/overscroll_configuration.cc
@@ -11,9 +11,13 @@
 
 namespace {
 
-bool g_is_mode_initialized = false;
-content::OverscrollConfig::Mode g_mode =
-    content::OverscrollConfig::Mode::kSimpleUi;
+bool g_is_history_navigation_mode_initialized = false;
+content::OverscrollConfig::HistoryNavigationMode g_history_navigation_mode =
+    content::OverscrollConfig::HistoryNavigationMode::kSimpleUi;
+
+bool g_is_ptr_mode_initialized = false;
+content::OverscrollConfig::PullToRefreshMode g_ptr_mode =
+    content::OverscrollConfig::PullToRefreshMode::kDisabled;
 
 const float kThresholdCompleteTouchpad = 0.3f;
 const float kThresholdCompleteTouchscreen = 0.25f;
@@ -42,21 +46,36 @@
 namespace content {
 
 // static
-OverscrollConfig::Mode OverscrollConfig::GetMode() {
-  if (g_is_mode_initialized)
-    return g_mode;
-
-  g_is_mode_initialized = true;
+OverscrollConfig::HistoryNavigationMode
+OverscrollConfig::GetHistoryNavigationMode() {
+  if (g_is_history_navigation_mode_initialized)
+    return g_history_navigation_mode;
 
   const std::string mode =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kOverscrollHistoryNavigation);
   if (mode == "0")
-    g_mode = Mode::kDisabled;
+    g_history_navigation_mode = HistoryNavigationMode::kDisabled;
   else if (mode == "1")
-    g_mode = Mode::kParallaxUi;
+    g_history_navigation_mode = HistoryNavigationMode::kParallaxUi;
+  g_is_history_navigation_mode_initialized = true;
+  return g_history_navigation_mode;
+}
 
-  return g_mode;
+// static
+OverscrollConfig::PullToRefreshMode OverscrollConfig::GetPullToRefreshMode() {
+  if (g_is_ptr_mode_initialized)
+    return g_ptr_mode;
+
+  const std::string mode =
+      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kPullToRefresh);
+  if (mode == "1")
+    g_ptr_mode = PullToRefreshMode::kEnabled;
+  else if (mode == "2")
+    g_ptr_mode = PullToRefreshMode::kEnabledTouchschreen;
+  g_is_ptr_mode_initialized = true;
+  return g_ptr_mode;
 }
 
 // static
@@ -84,15 +103,28 @@
 }
 
 // static
-void OverscrollConfig::SetMode(Mode mode) {
-  g_mode = mode;
-  g_is_mode_initialized = true;
+void OverscrollConfig::SetHistoryNavigationMode(HistoryNavigationMode mode) {
+  g_history_navigation_mode = mode;
+  g_is_history_navigation_mode_initialized = true;
 }
 
 // static
-void OverscrollConfig::ResetMode() {
-  g_is_mode_initialized = false;
-  g_mode = OverscrollConfig::Mode::kSimpleUi;
+void OverscrollConfig::ResetHistoryNavigationMode() {
+  g_is_history_navigation_mode_initialized = false;
+  g_history_navigation_mode =
+      OverscrollConfig::HistoryNavigationMode::kSimpleUi;
+}
+
+// static
+void OverscrollConfig::SetPullToRefreshMode(PullToRefreshMode mode) {
+  g_ptr_mode = mode;
+  g_is_ptr_mode_initialized = true;
+}
+
+// static
+void OverscrollConfig::ResetPullToRefreshMode() {
+  g_is_ptr_mode_initialized = false;
+  g_ptr_mode = OverscrollConfig::PullToRefreshMode::kDisabled;
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index e267395..fac640e4 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -17,11 +17,6 @@
 
 namespace {
 
-bool IsPullToRefreshEnabled() {
-  return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-             switches::kPullToRefresh) == "1";
-}
-
 bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
   DCHECK(blink::WebInputEvent::IsGestureEventType(event.GetType()));
   const blink::WebGestureEvent& gesture =
@@ -465,9 +460,15 @@
 
   // The vertical overscroll is used for pull-to-refresh. Enable it only if
   // pull-to-refresh is enabled.
-  if ((new_mode == OVERSCROLL_SOUTH || new_mode == OVERSCROLL_NORTH) &&
-      !IsPullToRefreshEnabled())
-    new_mode = OVERSCROLL_NONE;
+  if (new_mode == OVERSCROLL_SOUTH || new_mode == OVERSCROLL_NORTH) {
+    auto ptr_mode = OverscrollConfig::GetPullToRefreshMode();
+    if (ptr_mode == OverscrollConfig::PullToRefreshMode::kDisabled ||
+        (ptr_mode ==
+             OverscrollConfig::PullToRefreshMode::kEnabledTouchschreen &&
+         is_touchpad)) {
+      new_mode = OVERSCROLL_NONE;
+    }
+  }
 
   if (overscroll_mode_ == OVERSCROLL_NONE) {
     SetOverscrollMode(new_mode, is_touchpad ? OverscrollSource::TOUCHPAD
diff --git a/content/browser/renderer_host/overscroll_controller_unittest.cc b/content/browser/renderer_host/overscroll_controller_unittest.cc
index 28237f0a..3d2314d 100644
--- a/content/browser/renderer_host/overscroll_controller_unittest.cc
+++ b/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/containers/queue.h"
 #include "content/browser/renderer_host/overscroll_controller_delegate.h"
 #include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/public/test/scoped_overscroll_modes.h"
 #include "content/test/test_overscroll_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_input_event.h"
@@ -68,6 +69,18 @@
     return controller_->WillHandleEvent(*current_event_);
   }
 
+  // Creates and sends a gesture-fling-start event to the overscroll controller.
+  // Returns |true| if the event is consumed by the overscroll controller.
+  bool SimulateGestureFlingStart(float velocity_x,
+                                 float velocity_y,
+                                 blink::WebGestureDevice device) {
+    DCHECK(!current_event_);
+    current_event_ = std::make_unique<blink::WebGestureEvent>(
+        SyntheticWebGestureEventBuilder::BuildFling(velocity_x, velocity_y,
+                                                    device));
+    return controller_->WillHandleEvent(*current_event_);
+  }
+
   // Notifies the overscroll controller that the current event is ACKed.
   void SimulateAck(bool processed) {
     DCHECK(current_event_);
@@ -101,7 +114,7 @@
 // initiated, overscroll will not initiate anymore.
 TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
   // Simulate a mouse-wheel, ACK it as not processed, simulate the corresponding
-  // gesture scroll-update event, and ACK it is not processed. Since it is not
+  // gesture scroll-update event, and ACK it as not processed. Since it is not
   // passing the start threshold, no overscroll should happen.
   EXPECT_FALSE(SimulateMouseWheel(10, 0));
   SimulateAck(false);
@@ -167,4 +180,148 @@
       100, 0, blink::kWebGestureDeviceTouchpad, true));
 }
 
+// Verifies that when pull-to-refresh is disabled, it is not triggered for
+// neither touchpad nor touchscreen.
+TEST_F(OverscrollControllerTest, PullToRefreshDisabled) {
+  ScopedPullToRefreshMode scoped_mode(
+      OverscrollConfig::PullToRefreshMode::kDisabled);
+
+  // Simulate a touchpad gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should not be
+  // triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchpad, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchpad zero-velocity fling-start which would normally end
+  // pull-to-refresh, and ACK it as not processed. Nothing should happen.
+  EXPECT_FALSE(
+      SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should not be
+  // triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchscreen, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-end which would normally end
+  // pull-to-refresh, and ACK it as not processed. Nothing should happen.
+  EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
+                                    blink::kWebGestureDeviceTouchscreen));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
+// Verifies that when pull-to-refresh is enabled, it is triggered for both
+// touchpad and touchscreen.
+TEST_F(OverscrollControllerTest, PullToRefreshEnabled) {
+  ScopedPullToRefreshMode scoped_mode(
+      OverscrollConfig::PullToRefreshMode::kEnabled);
+
+  // Simulate a touchpad gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should be triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchpad, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
+  EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
+  EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchpad zero-velocity fling-start and ACK it as not processed..
+  // It should abort pull-to-refresh.
+  EXPECT_FALSE(
+      SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should be triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchscreen, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
+  EXPECT_EQ(OverscrollSource::TOUCHSCREEN, controller_source());
+  EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-end and ACK it as not processed. It
+  // should abort pull-to-refresh.
+  EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
+                                    blink::kWebGestureDeviceTouchscreen));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
+// Verifies that when pull-to-refresh is enabled only for touchscreen, it is
+// triggered for touchscreen but not for touchpad.
+TEST_F(OverscrollControllerTest, PullToRefreshEnabledTouchscreen) {
+  ScopedPullToRefreshMode scoped_mode(
+      OverscrollConfig::PullToRefreshMode::kEnabledTouchschreen);
+
+  // Simulate a touchpad gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should not be
+  // triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchpad, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchpad zero-velocity fling-start which would normally end
+  // pull-to-refresh, and ACK it as not processed. Nothing should happen.
+  EXPECT_FALSE(
+      SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-update event that passes the start
+  // threshold and ACK it as not processed. Pull-to-refresh should be triggered.
+  EXPECT_FALSE(SimulateGestureScrollUpdate(
+      0, 80, blink::kWebGestureDeviceTouchscreen, false));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
+  EXPECT_EQ(OverscrollSource::TOUCHSCREEN, controller_source());
+  EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a touchscreen gesture scroll-end and ACK it as not processed. It
+  // should abort pull-to-refresh.
+  EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
+                                    blink::kWebGestureDeviceTouchscreen));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index b0f4813e..820687c 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -45,17 +45,6 @@
 namespace content {
 namespace {
 
-int RenderProcessHostCount() {
-  RenderProcessHost::iterator hosts = RenderProcessHost::AllHostsIterator();
-  int count = 0;
-  while (!hosts.IsAtEnd()) {
-    if (hosts.GetCurrentValue()->HasConnection())
-      count++;
-    hosts.Advance();
-  }
-  return count;
-}
-
 std::unique_ptr<net::test_server::HttpResponse> HandleBeacon(
     const net::test_server::HttpRequest& request) {
   if (request.relative_url != "/beacon")
@@ -125,6 +114,8 @@
 // suitable host, but otherwise tries to reuse processes.
 class NonSpareRendererContentBrowserClient : public TestContentBrowserClient {
  public:
+  NonSpareRendererContentBrowserClient() = default;
+
   bool IsSuitableHost(RenderProcessHost* process_host,
                       const GURL& site_url) override {
     return RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() !=
@@ -135,6 +126,14 @@
                                          const GURL& url) override {
     return true;
   }
+
+  bool ShouldUseSpareRenderProcessHost(BrowserContext* browser_context,
+                                       const GURL& site_url) override {
+    return false;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NonSpareRendererContentBrowserClient);
 };
 
 // Sometimes the renderer process's ShutdownRequest (corresponding to the
@@ -183,7 +182,7 @@
   // Make it believe it's a guest.
   reinterpret_cast<RenderProcessHostImpl*>(rph)->
       set_is_for_guests_only_for_testing(true);
-  EXPECT_EQ(1, RenderProcessHostCount());
+  EXPECT_EQ(1, RenderProcessHost::GetCurrentRenderProcessCountForTesting());
 
   // Navigate to a different page.
   GURL::Replacements replace_host;
@@ -193,7 +192,7 @@
   NavigateToURL(CreateBrowser(), another_url);
 
   // Expect that we got another process (the guest renderer was not reused).
-  EXPECT_EQ(2, RenderProcessHostCount());
+  EXPECT_EQ(2, RenderProcessHost::GetCurrentRenderProcessCountForTesting());
 }
 
 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostTaken) {
@@ -212,9 +211,18 @@
   EXPECT_EQ(spare_renderer,
             window->web_contents()->GetMainFrame()->GetProcess());
 
-  // The spare render process host should no longer be available.
-  EXPECT_EQ(nullptr,
+  // The old spare render process host should no longer be available.
+  EXPECT_NE(spare_renderer,
             RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+
+  // Check if a fresh spare is available (depending on the operating mode).
+  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+    EXPECT_NE(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  } else {
+    EXPECT_EQ(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostNotTaken) {
@@ -232,11 +240,16 @@
   EXPECT_NE(spare_renderer,
             window->web_contents()->GetMainFrame()->GetProcess());
 
-  // The spare RenderProcessHost should have been cleaned up. Note this
-  // behavior is identical to what would have happened if the RenderProcessHost
-  // were taken.
-  EXPECT_EQ(nullptr,
-            RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  // Check if a fresh spare is available (depending on the operating mode).
+  // Note this behavior is identical to what would have happened if the
+  // RenderProcessHost were taken.
+  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+    EXPECT_NE(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  } else {
+    EXPECT_EQ(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostKilled) {
@@ -295,8 +308,10 @@
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
   Shell* new_window = CreateBrowser();
   NavigateToURL(new_window, test_url);
-  // The spare RPH should have been dropped during CreateBrowser() and given to
-  // the new window.
+  // Outside of RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes mode, the
+  // spare RPH should have been dropped during CreateBrowser() and given to the
+  // new window.  OTOH, even in the IsSpareProcessKeptAtAllTimes mode, the spare
+  // shouldn't be created because of the low process limit.
   EXPECT_EQ(nullptr,
             RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
   EXPECT_EQ(spare_renderer,
@@ -321,15 +336,19 @@
       RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
   EXPECT_NE(nullptr, spare_renderer);
 
-  // This should resuse the existing process and cause the spare renderer to be
-  // dropped.
+  // This should reuse the existing process.
   Shell* new_browser = CreateBrowser();
   EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
             new_browser->web_contents()->GetMainFrame()->GetProcess());
   EXPECT_NE(spare_renderer,
             new_browser->web_contents()->GetMainFrame()->GetProcess());
-  EXPECT_EQ(nullptr,
-            RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+    EXPECT_NE(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  } else {
+    EXPECT_EQ(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  }
 
   // The launcher thread reads state from browser_client, need to wait for it to
   // be done before resetting the browser client. crbug.com/742533.
@@ -357,6 +376,17 @@
   // down.
 }
 
+// Verifies that the spare renderer maintained by SpareRenderProcessHostManager
+// is correctly destroyed when closing the last content shell.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRendererDuringClosing) {
+  content::RenderProcessHost::WarmupSpareRenderProcessHost(
+      shell()->web_contents()->GetBrowserContext());
+  shell()->web_contents()->Close();
+
+  // The verification is that there are no DCHECKs or UaF anywhere during test
+  // tear down.
+}
+
 // Class that simulates the fact that some //content embedders (e.g. by
 // overriding ChromeContentBrowserClient::GetStoragePartitionConfigForSite) can
 // cause BrowserContext::GetDefaultStoragePartition(browser_context) to differ
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 4920257..3e6f43de 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -280,6 +280,10 @@
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
 namespace content {
+
+using CheckOriginLockResult =
+    ChildProcessSecurityPolicyImpl::CheckOriginLockResult;
+
 namespace {
 
 const RenderProcessHostFactory* g_render_process_host_factory_ = nullptr;
@@ -588,48 +592,56 @@
     // launch time, but this cannot be done for spare RenderProcessHosts, which
     // are started before it is known which navigation might use them.  So, a
     // spare RenderProcessHost should not be used in such cases.
-    if (!GetContentClient()->browser()->ShouldUseSpareRenderProcessHost(
-            browser_context, site_instance->GetSiteURL()))
-      return nullptr;
+    bool should_use_spare =
+        GetContentClient()->browser()->ShouldUseSpareRenderProcessHost(
+            browser_context, site_instance->GetSiteURL());
 
     // Get the StoragePartition for |site_instance|.  Note that this might be
     // different than the default StoragePartition for |browser_context|.
     StoragePartition* site_storage =
         BrowserContext::GetStoragePartition(browser_context, site_instance);
-    if (!spare_render_process_host_ ||
-        browser_context != spare_render_process_host_->GetBrowserContext() ||
-        site_storage != spare_render_process_host_->GetStoragePartition() ||
-        is_for_guests_only) {
-      // As a new RenderProcessHost will almost certainly be created, we cleanup
-      // the non-matching one so as not to waste resources.
+
+    RenderProcessHost* returned_process = nullptr;
+    if (spare_render_process_host_ &&
+        browser_context == spare_render_process_host_->GetBrowserContext() &&
+        site_storage == spare_render_process_host_->GetStoragePartition() &&
+        !is_for_guests_only && should_use_spare) {
+      CHECK(spare_render_process_host_->HostHasNotBeenUsed());
+
+      // If the spare process ends up getting killed, the spare manager should
+      // discard the spare RPH, so if one exists, it should always be live here.
+      CHECK(spare_render_process_host_->HasConnection());
+
+      returned_process = spare_render_process_host_;
+      ReleaseSpareRenderProcessHost(spare_render_process_host_);
+    } else if (!RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+      // If the spare shouldn't be kept around, then discard it as soon as we
+      // find that the current spare was mismatched.
       CleanupSpareRenderProcessHost();
-      return nullptr;
+    } else if (g_all_hosts.Get().size() >=
+               RenderProcessHostImpl::GetMaxRendererProcessCount()) {
+      // Drop the spare if we are at a process limit and the spare wasn't taken.
+      // This helps avoid process reuse.
+      CleanupSpareRenderProcessHost();
     }
 
-    CHECK(spare_render_process_host_->HostHasNotBeenUsed());
-    RenderProcessHost* rph = spare_render_process_host_;
-    DropSpareRenderProcessHost(spare_render_process_host_);
-    return rph;
+    return returned_process;
   }
 
-  // Remove |host| as a possible spare renderer. Does not shut it down cleanly;
-  // the assumption is that the host was shutdown somewhere else and has
-  // notifying the SpareRenderProcessHostManager.
-  void DropSpareRenderProcessHost(RenderProcessHost* host) {
-    if (spare_render_process_host_ && spare_render_process_host_ == host) {
-      spare_render_process_host_->RemoveObserver(this);
-      spare_render_process_host_ = nullptr;
-    }
-  }
-
-  // Remove |host| as a possible spare renderer. If |host| is not the spare
-  // renderer, then shut down the spare renderer. The idea is that a navigation
-  // was just made to |host|, and we do not expect another immediate navigation,
-  // so that the spare renderer can be dropped in order to free up resources.
-  void DropSpareOnProcessCreation(RenderProcessHost* new_host) {
-    if (spare_render_process_host_ == new_host) {
-      DropSpareRenderProcessHost(new_host);
+  // Prepares for future requests (with an assumption that a future navigation
+  // might require a new process for |browser_context|).
+  //
+  // Note that depending on the caller PrepareForFutureRequests can be called
+  // after the spare_render_process_host_ has either been 1) matched and taken
+  // or 2) mismatched and ignored or 3) matched and ignored.
+  void PrepareForFutureRequests(BrowserContext* browser_context) {
+    if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+      // Always keep around a spare process for the most recently requested
+      // |browser_context|.
+      WarmupSpareRenderProcessHost(browser_context);
     } else {
+      // Discard the ignored (probably non-matching) spare so as not to waste
+      // resources.
       CleanupSpareRenderProcessHost();
     }
   }
@@ -656,6 +668,16 @@
   }
 
  private:
+  // Release ownership of |host| as a possible spare renderer.  Called when
+  // |host| has either been 1) claimed to be used in a navigation or 2) shutdown
+  // somewhere else.
+  void ReleaseSpareRenderProcessHost(RenderProcessHost* host) {
+    if (spare_render_process_host_ && spare_render_process_host_ == host) {
+      spare_render_process_host_->RemoveObserver(this);
+      spare_render_process_host_ = nullptr;
+    }
+  }
+
   // RenderProcessHostObserver::RenderProcessWillExit is not overriden because:
   // 1. This simplifies reasoning when Cleanup can be called.
   // 2. In practice the spare shouldn't go through graceful shutdown.
@@ -670,7 +692,7 @@
   }
 
   void RenderProcessHostDestroyed(RenderProcessHost* host) override {
-    DropSpareRenderProcessHost(host);
+    ReleaseSpareRenderProcessHost(host);
   }
 
   // This is a bare pointer, because RenderProcessHost manages the lifetime of
@@ -1290,6 +1312,24 @@
 // static
 void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
   g_max_renderer_count_override = count;
+  if (g_all_hosts.Get().size() > count)
+    g_spare_render_process_host_manager.Get().CleanupSpareRenderProcessHost();
+}
+
+// static
+int RenderProcessHost::GetCurrentRenderProcessCountForTesting() {
+  content::RenderProcessHost::iterator it =
+      content::RenderProcessHost::AllHostsIterator();
+  int count = 0;
+  while (!it.IsAtEnd()) {
+    RenderProcessHost* host = it.GetCurrentValue();
+    if (host->HasConnection() &&
+        host != RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()) {
+      count++;
+    }
+    it.Advance();
+  }
+  return count;
 }
 
 // static
@@ -1328,24 +1368,6 @@
 const unsigned int RenderProcessHostImpl::kMaxFrameDepthForPriority =
     std::numeric_limits<unsigned int>::max();
 
-// static
-RenderProcessHost* RenderProcessHostImpl::CreateOrUseSpareRenderProcessHost(
-    BrowserContext* browser_context,
-    SiteInstance* site_instance,
-    bool is_for_guests_only) {
-  RenderProcessHost* render_process_host =
-      g_spare_render_process_host_manager.Get().MaybeTakeSpareRenderProcessHost(
-          browser_context, site_instance, is_for_guests_only);
-
-  if (!render_process_host) {
-    render_process_host = CreateRenderProcessHost(
-        browser_context, nullptr, site_instance, is_for_guests_only);
-  }
-
-  DCHECK(render_process_host);
-  return render_process_host;
-}
-
 RenderProcessHostImpl::RenderProcessHostImpl(
     BrowserContext* browser_context,
     StoragePartitionImpl* storage_partition_impl,
@@ -2429,6 +2451,7 @@
   UpdateProcessPriority();
 }
 
+// static
 void RenderProcessHostImpl::set_render_process_host_factory(
     const RenderProcessHostFactory* rph_factory) {
   g_render_process_host_factory_ = rph_factory;
@@ -2511,8 +2534,10 @@
 }
 
 // static
-void RenderProcessHostImpl::CleanupSpareRenderProcessHost() {
-  g_spare_render_process_host_manager.Get().CleanupSpareRenderProcessHost();
+void RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
+    BrowserContext* browser_context) {
+  g_spare_render_process_host_manager.Get().PrepareForFutureRequests(
+      browser_context);
 }
 
 // static
@@ -2521,6 +2546,22 @@
   return g_spare_render_process_host_manager.Get().spare_render_process_host();
 }
 
+// static
+void RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting() {
+  g_spare_render_process_host_manager.Get().CleanupSpareRenderProcessHost();
+}
+
+// static
+bool RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() {
+  if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
+    return false;
+
+  if (!base::FeatureList::IsEnabled(features::kSpareRendererForSitePerProcess))
+    return false;
+
+  return true;
+}
+
 bool RenderProcessHostImpl::HostHasNotBeenUsed() {
   return IsUnused() && listeners_.IsEmpty() && keep_alive_ref_count_ == 0 &&
          pending_views_ == 0;
@@ -3391,28 +3432,40 @@
   if (!host->InSameStoragePartition(dest_partition))
     return false;
 
+  // Check WebUI bindings and origin locks.
   auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
-  if (policy->HasWebUIBindings(host->GetID()) !=
-      WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
-          browser_context, site_url)) {
-    return false;
-  }
-
-  // Sites requiring dedicated processes can only reuse a compatible process.
+  bool host_has_web_ui_bindings = policy->HasWebUIBindings(host->GetID());
   auto lock_state = policy->CheckOriginLock(host->GetID(), site_url);
-  if (lock_state !=
-      ChildProcessSecurityPolicyImpl::CheckOriginLockResult::NO_LOCK) {
-    // If the process is already dedicated to a site, only allow the destination
-    // URL to reuse this process if the URL has the same site.
-    if (lock_state !=
-        ChildProcessSecurityPolicyImpl::CheckOriginLockResult::HAS_EQUAL_LOCK)
+  if (host->HostHasNotBeenUsed()) {
+    // If the host hasn't been used, it won't have the expected WebUI bindings
+    // or origin locks just *yet* - skip the checks in this case.  One example
+    // where this case can happen is when the spare RenderProcessHost gets used.
+    CHECK(!host_has_web_ui_bindings);
+    CHECK_EQ(CheckOriginLockResult::NO_LOCK, lock_state);
+  } else {
+    // WebUI checks.
+    bool url_requires_web_ui_bindings =
+        WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
+            browser_context, site_url);
+    if (host_has_web_ui_bindings != url_requires_web_ui_bindings)
       return false;
-  } else if (!host->IsUnused() && SiteInstanceImpl::ShouldLockToOrigin(
-                                      browser_context, host, site_url)) {
-    // Otherwise, if this process has been used to host any other content, it
-    // cannot be reused if the destination site indeed requires a dedicated
-    // process and can be locked to just that site.
-    return false;
+
+    // Sites requiring dedicated processes can only reuse a compatible process.
+    switch (lock_state) {
+      case CheckOriginLockResult::HAS_EQUAL_LOCK:
+        break;
+      case CheckOriginLockResult::HAS_WRONG_LOCK:
+        return false;
+      case CheckOriginLockResult::NO_LOCK:
+        if (!host->IsUnused() && SiteInstanceImpl::ShouldLockToOrigin(
+                                     browser_context, host, site_url)) {
+          // If this process has been used to host any other content, it cannot
+          // be reused if the destination site requires a dedicated process and
+          // should use a process locked to just that site.
+          return false;
+        }
+        break;
+    }
   }
 
   return GetContentClient()->browser()->IsSuitableHost(host, site_url);
@@ -3495,7 +3548,7 @@
 }
 
 // static
-RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
+RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost(
     BrowserContext* browser_context,
     const GURL& site_url) {
   // First figure out which existing renderers we can use.
@@ -3507,6 +3560,11 @@
     if (iter.GetCurrentValue()->MayReuseHost() &&
         RenderProcessHostImpl::IsSuitableHost(iter.GetCurrentValue(),
                                               browser_context, site_url)) {
+      // The spare is always considered before process reuse.
+      DCHECK_NE(iter.GetCurrentValue(),
+                g_spare_render_process_host_manager.Get()
+                    .spare_render_process_host());
+
       suitable_renderers.push_back(iter.GetCurrentValue());
     }
     iter.Advance();
@@ -3516,10 +3574,6 @@
   if (!suitable_renderers.empty()) {
     int suitable_count = static_cast<int>(suitable_renderers.size());
     int random_index = base::RandInt(0, suitable_count - 1);
-    // If the process chosen was the spare RenderProcessHost, ensure it won't be
-    // used as a spare in the future, or drop the spare if it wasn't used.
-    g_spare_render_process_host_manager.Get().DropSpareOnProcessCreation(
-        suitable_renderers[random_index]);
     return suitable_renderers[random_index];
   }
 
@@ -3640,6 +3694,16 @@
         browser_context, site_url);
   }
 
+  // See if the spare RenderProcessHost can be used.
+  SpareRenderProcessHostManager& spare_process_manager =
+      g_spare_render_process_host_manager.Get();
+  bool spare_was_taken = false;
+  if (!render_process_host) {
+    render_process_host = spare_process_manager.MaybeTakeSpareRenderProcessHost(
+        browser_context, site_instance, is_for_guests_only);
+    spare_was_taken = (render_process_host != nullptr);
+  }
+
   // If not (or if none found), see if we should reuse an existing process.
   if (!render_process_host &&
       ShouldTryToUseExistingProcessHost(browser_context, site_url)) {
@@ -3663,16 +3727,28 @@
     CHECK(false) << "Unsuitable process reused for site " << site_url;
   }
 
-  // Otherwise, use the spare RenderProcessHost or create a new one.
+  // Otherwise, create a new RenderProcessHost.
   if (!render_process_host) {
     // Pass a null StoragePartition. Tests with TestBrowserContext using a
     // RenderProcessHostFactory may not instantiate a StoragePartition, and
     // creating one here with GetStoragePartition() can run into cross-thread
     // issues as TestBrowserContext initialization is done on the main thread.
-    render_process_host = CreateOrUseSpareRenderProcessHost(
-        browser_context, site_instance, is_for_guests_only);
+    render_process_host = CreateRenderProcessHost(
+        browser_context, nullptr, site_instance, is_for_guests_only);
   }
 
+  // It is important to call PrepareForFutureRequests *after* potentially
+  // creating a process a few statements earlier - doing this avoids violating
+  // the process limit.
+  //
+  // We should not warm-up another spare if the spare was not taken, because in
+  // this case we might have created a new process - we want to avoid spawning
+  // two processes at the same time.  In this case the call to
+  // PrepareForFutureRequests will be postponed until later (e.g. until the
+  // navigation commits or a cross-site redirect happens).
+  if (spare_was_taken)
+    spare_process_manager.PrepareForFutureRequests(browser_context);
+
   if (is_unmatched_service_worker) {
     UnmatchedServiceWorkerProcessTracker::Register(
         browser_context, render_process_host, site_url);
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 977e4750..3a37edd 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "base/containers/flat_set.h"
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
@@ -128,16 +129,7 @@
   // Special depth used when there are no PriorityClients.
   static const unsigned int kMaxFrameDepthForPriority;
 
-  // Use the spare RenderProcessHost if it exists, or create a new one. This
-  // should be the usual way to get a new RenderProcessHost.  Default storage
-  // partition from the browser_context is always used.
-  static RenderProcessHost* CreateOrUseSpareRenderProcessHost(
-      BrowserContext* browser_context,
-      SiteInstance* site_instance,
-      bool is_for_guests_only);
-
-  // Create a new RenderProcessHost. In most cases
-  // CreateOrUseSpareRenderProcessHost, above, should be used instead.
+  // Create a new RenderProcessHost.
   // If |storage_partition_impl| is null, the default partition from the
   // browser_context is used, using |site_instance| (for which a null value is
   // legal). |site_instance| is not used if |storage_partition_impl| is not
@@ -302,10 +294,14 @@
       BrowserContext* browser_context,
       SiteInstanceImpl* site_instance);
 
-  // Cleanup and remove any spare renderer. This should be used when a
-  // navigation has occurred or will be occurring that will not use the spare
-  // renderer and resources should be cleaned up.
-  static void CleanupSpareRenderProcessHost();
+  // Should be called when |browser_context| is used in a navigation.
+  //
+  // The SpareRenderProcessHostManager can decide how to respond (for example,
+  // by shutting down the spare process to conserve resources, or alternatively
+  // by making sure that the spare process belongs to the same BrowserContext as
+  // the most recent navigation).
+  static void NotifySpareManagerAboutRecentlyUsedBrowserContext(
+      BrowserContext* browser_context);
 
   static base::MessageLoop* GetInProcessRendererThreadForTesting();
 
@@ -391,6 +387,13 @@
   // globally-used spare RenderProcessHost at any time.
   static RenderProcessHost* GetSpareRenderProcessHostForTesting();
 
+  // Discards the spare RenderProcessHost.  After this call,
+  // GetSpareRenderProcessHostForTesting will return nullptr.
+  static void DiscardSpareRenderProcessHostForTesting();
+
+  // Returns true if a spare RenderProcessHost should be kept at all times.
+  static bool IsSpareProcessKeptAtAllTimes();
+
   PermissionServiceContext& permission_service_context() {
     return *permission_service_context_;
   }
@@ -534,6 +537,18 @@
       SiteInstanceImpl* site_instance,
       bool is_for_guests_only);
 
+  // Get an existing RenderProcessHost associated with the given browser
+  // context, if possible.  The renderer process is chosen randomly from
+  // suitable renderers that share the same context and type (determined by the
+  // site url).
+  // Returns nullptr if no suitable renderer process is available, in which case
+  // the caller is free to create a new renderer.
+  static RenderProcessHost* GetExistingProcessHost(
+      content::BrowserContext* browser_context,
+      const GURL& site_url);
+  FRIEND_TEST_ALL_PREFIXES(RenderProcessHostUnitTest,
+                           GuestsAreNotSuitableHosts);
+
   // Returns a RenderProcessHost that is rendering |site_url| in one of its
   // frames, or that is expecting a navigation to |site_url|.
   static RenderProcessHost* FindReusableProcessHostForSite(
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc
index 4fce0967..363d4a5d 100644
--- a/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -9,6 +9,8 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/common/frame_messages.h"
 #include "content/common/frame_owner_properties.h"
@@ -42,9 +44,8 @@
       &guest_host, browser_context(), test_url));
   EXPECT_TRUE(RenderProcessHostImpl::IsSuitableHost(
       process(), browser_context(), test_url));
-  EXPECT_EQ(
-      process(),
-      RenderProcessHost::GetExistingProcessHost(browser_context(), test_url));
+  EXPECT_EQ(process(), RenderProcessHostImpl::GetExistingProcessHost(
+                           browser_context(), test_url));
 }
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
@@ -248,6 +249,9 @@
   ContentBrowserClient* regular_client =
       SetBrowserClientForTesting(&modified_client);
 
+  // Discard the spare, so it cannot be considered by the GetProcess call below.
+  RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();
+
   // Now, getting a RenderProcessHost for a navigation to the same site should
   // not reuse the unmatched service worker's process (i.e., |sw_host|), as
   // it's unsuitable.
@@ -883,17 +887,24 @@
 }
 
 class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness {
+ public:
+  SpareRenderProcessHostUnitTest() {}
+
  protected:
   void SetUp() override {
     SetRenderProcessHostFactory(&rph_factory_);
     RenderViewHostImplTestHarness::SetUp();
     SetContents(nullptr);  // Start with no renderers.
+    RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();
     while (!rph_factory_.GetProcesses()->empty()) {
       rph_factory_.Remove(rph_factory_.GetProcesses()->back().get());
     }
   }
 
   MockRenderProcessHostFactory rph_factory_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SpareRenderProcessHostUnitTest);
 };
 
 TEST_F(SpareRenderProcessHostUnitTest, TestRendererTaken) {
@@ -907,21 +918,149 @@
   SetContents(CreateTestWebContents());
   NavigateAndCommit(kUrl1);
   EXPECT_EQ(spare_rph, main_test_rfh()->GetProcess());
-  ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
+
+  EXPECT_NE(spare_rph,
+            RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+    EXPECT_NE(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+    EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
+  } else {
+    EXPECT_EQ(nullptr,
+              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+    EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
+  }
 }
 
 TEST_F(SpareRenderProcessHostUnitTest, TestRendererNotTaken) {
   std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
   RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
   ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
-  RenderProcessHost* spare_rph =
+  RenderProcessHost* old_spare =
       RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
-  EXPECT_EQ(spare_rph, rph_factory_.GetProcesses()->at(0).get());
+  EXPECT_EQ(alternate_context.get(), old_spare->GetBrowserContext());
+  EXPECT_EQ(old_spare, rph_factory_.GetProcesses()->at(0).get());
 
   const GURL kUrl1("http://foo.com");
   SetContents(CreateTestWebContents());
   NavigateAndCommit(kUrl1);
-  EXPECT_NE(spare_rph, main_test_rfh()->GetProcess());
+  EXPECT_NE(old_spare, main_test_rfh()->GetProcess());
+
+  // Pumping the message loop here accounts for the delay between calling
+  // RPH::Cleanup on the spare and the time when the posted delete actually
+  // happens.  Without pumping, the spare would still be present in
+  // rph_factory_.GetProcesses().
+  base::RunLoop().RunUntilIdle();
+
+  RenderProcessHost* new_spare =
+      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  EXPECT_NE(old_spare, new_spare);
+  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
+    EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
+    ASSERT_NE(nullptr, new_spare);
+    EXPECT_EQ(GetBrowserContext(), new_spare->GetBrowserContext());
+  } else {
+    EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
+    EXPECT_EQ(nullptr, new_spare);
+  }
+}
+
+TEST_F(SpareRenderProcessHostUnitTest,
+       SpareShouldNotLaunchInParallelWithOtherProcess) {
+  std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
+  RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
+  ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
+  RenderProcessHost* old_spare =
+      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  EXPECT_EQ(alternate_context.get(), old_spare->GetBrowserContext());
+  EXPECT_EQ(old_spare, rph_factory_.GetProcesses()->at(0).get());
+
+  // When we try to get a process for foo.com, we won't be able to use the spare
+  // (because it is associated with the alternate, mismatched BrowserContext)
+  // and therefore we will have to spawn a new process.  This test verifies that
+  // we don't at the same time try to warm-up a new spare (leading to
+  // unnecessary resource contention when 2 processes try to launch at the same
+  // time).
+  scoped_refptr<SiteInstanceImpl> site_instance =
+      SiteInstanceImpl::CreateForURL(browser_context(), GURL("http://foo.com"));
+  RenderProcessHost* site_instance_process = site_instance->GetProcess();
+  // We need to ensure the MockRenderProcessHost gets destroyed at the end of
+  // the test.
+  std::unique_ptr<MockRenderProcessHost> owned_mock_process(
+      static_cast<MockRenderProcessHost*>(site_instance_process));
+
+  // The SiteInstance shouldn't get the old spare, because of BrowserContext
+  // mismatch.  The SiteInstance will get a new process instead.
+  EXPECT_NE(old_spare, site_instance_process);
+  EXPECT_FALSE(site_instance_process->IsReady());
+
+  // There should be no new spare at this point to avoid launching 2 processes
+  // at the same time.  Note that the spare might still be created later during
+  // a navigation (e.g. after cross-site redirects or when committing).
+  RenderProcessHost* new_spare =
+      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
+  if (new_spare != old_spare)
+    EXPECT_FALSE(new_spare);
+}
+
+// This unit test looks at the simplified equivalent of what
+// CtrlClickShouldEndUpInSameProcessTest.BlankTarget test would have
+// encountered.  The test verifies that the spare RPH is not launched if 1) we
+// need to create another renderer process anyway (e.g. because the spare is
+// missing when MaybeTakeSpareRenderProcessHost is called) and 2) creating the
+// other renderer process will put as at the process limit.  Launching the spare
+// in this scenario would put us over the process limit and is therefore
+// undesirable.
+TEST_F(SpareRenderProcessHostUnitTest, JustBelowProcessLimit) {
+  RenderProcessHostImpl::SetMaxRendererProcessCount(1);
+
+  // No spare or any other renderer process at the start of the test.
+  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  EXPECT_EQ(0U, rph_factory_.GetProcesses()->size());
+
+  // Navigation can't take a spare (none present) and needs to launch a new
+  // renderer process.
+  const GURL kUrl1("http://foo.com");
+  SetContents(CreateTestWebContents());
+  NavigateAndCommit(kUrl1);
+
+  // We should still be below the process limit.
+  EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
+
+  // There should be no spare - having one would put us over the process limit.
+  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+}
+
+// This unit test verifies that a mismatched spare RenderProcessHost is dropped
+// before considering process reuse due to the process limit.
+TEST_F(SpareRenderProcessHostUnitTest, AtProcessLimit) {
+  RenderProcessHostImpl::SetMaxRendererProcessCount(2);
+
+  // Create and navigate the 1st WebContents.
+  const GURL kUrl1("http://foo.com");
+  std::unique_ptr<WebContents> contents1(CreateTestWebContents());
+  static_cast<TestWebContents*>(contents1.get())->NavigateAndCommit(kUrl1);
+  EXPECT_NE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(),
+            contents1->GetMainFrame()->GetProcess());
+
+  // Warm up a mismatched spare.
+  std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
+  RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
+
+  // Create and navigate the 2nd WebContents.
+  const GURL kUrl2("http://bar.com");
+  std::unique_ptr<WebContents> contents2(CreateTestWebContents());
+  static_cast<TestWebContents*>(contents2.get())->NavigateAndCommit(kUrl2);
+  base::RunLoop().RunUntilIdle();
+
+  // Creating a 2nd WebContents shouldn't share a renderer process with the 1st
+  // one - instead the spare should be dropped to stay under the process limit.
+  EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
+  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+  EXPECT_NE(contents1->GetMainFrame()->GetProcess(),
+            contents2->GetMainFrame()->GetProcess());
 }
 
 }  // namespace content
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 32f7849..db919243 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
@@ -1303,9 +1303,15 @@
   target_ancestors.push_back(target->GetFrameSinkId());
   RenderWidgetHostViewBase* cur_view = target;
   while (cur_view->IsRenderWidgetHostViewChildFrame()) {
-    cur_view =
-        static_cast<RenderWidgetHostViewChildFrame*>(cur_view)->GetParentView();
-    DCHECK(cur_view);
+    if (cur_view->IsRenderWidgetHostViewGuest()) {
+      cur_view = static_cast<RenderWidgetHostViewGuest*>(cur_view)
+                     ->GetOwnerRenderWidgetHostView();
+    } else {
+      cur_view = static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
+                     ->GetParentView();
+    }
+    if (!cur_view)
+      return false;
     target_ancestors.push_back(cur_view->GetFrameSinkId());
   }
   DCHECK_EQ(cur_view, root_view);
diff --git a/content/browser/renderer_host/render_widget_host_ns_view_client.h b/content/browser/renderer_host/render_widget_host_ns_view_client.h
index 0a6cd1f..53596eb 100644
--- a/content/browser/renderer_host/render_widget_host_ns_view_client.h
+++ b/content/browser/renderer_host/render_widget_host_ns_view_client.h
@@ -60,6 +60,22 @@
   // Indicate the NSView's NSScreen's properties.
   virtual void OnNSViewDisplayChanged(const display::Display& display) = 0;
 
+  // Indicate the begin and end block of a keyboard event. The beginning of this
+  // block will record the active RenderWidgetHost, and will forward all
+  // remaining keyboard and Ime messages to that RenderWidgetHost.
+  virtual void OnNSViewBeginKeyboardEvent() = 0;
+  virtual void OnNSViewEndKeyboardEvent() = 0;
+
+  // Forward a keyboard event to the RenderWidgetHost that is currently handling
+  // the key-down event.
+  virtual void OnNSViewForwardKeyboardEvent(
+      const NativeWebKeyboardEvent& key_event,
+      const ui::LatencyInfo& latency_info) = 0;
+  virtual void OnNSViewForwardKeyboardEventWithCommands(
+      const NativeWebKeyboardEvent& key_event,
+      const ui::LatencyInfo& latency_info,
+      const std::vector<EditCommand>& commands) = 0;
+
   // Forward events to the renderer or the input router, as appropriate.
   virtual void OnNSViewRouteOrProcessMouseEvent(
       const blink::WebMouseEvent& web_event) = 0;
@@ -79,6 +95,21 @@
   virtual void OnNSViewSmartMagnify(
       const blink::WebGestureEvent& smart_magnify_event) = 0;
 
+  // Forward the corresponding Ime commands to the appropriate RenderWidgetHost.
+  // Appropriate, has two meanings here. If this is during a key-down event,
+  // then the target is the RWH that is handling that key-down event. Otherwise,
+  // it is the result of GetActiveWidget.
+  virtual void OnNSViewImeSetComposition(
+      const base::string16& text,
+      const std::vector<ui::ImeTextSpan>& ime_text_spans,
+      const gfx::Range& replacement_range,
+      int selection_start,
+      int selection_end) = 0;
+  virtual void OnNSViewImeCommitText(const base::string16& text,
+                                     const gfx::Range& replacement_range) = 0;
+  virtual void OnNSViewImeFinishComposingText() = 0;
+  virtual void OnNSViewImeCancelComposition() = 0;
+
   // Request an overlay dictionary be displayed for the text at the specified
   // point.
   virtual void OnNSViewLookUpDictionaryOverlayAtPoint(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 01a48ab..34f52f7 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -912,15 +912,19 @@
 }
 
 void RenderWidgetHostViewAndroid::EvictFrameIfNecessary() {
-  if (!base::FeatureList::IsEnabled(
+  if (!host()->delegate()->IsFullscreenForCurrentTab() ||
+      current_surface_size_ == view_.GetPhysicalBackingSize() ||
+      !base::FeatureList::IsEnabled(
           features::kHideIncorrectlySizedFullscreenFrames)) {
     return;
   }
-  if (host()->delegate()->IsFullscreenForCurrentTab() &&
-      current_surface_size_ != view_.GetPhysicalBackingSize()) {
-    // When we're in a fullscreen and the frame size doesn't match the view
-    // size (e.g. during a fullscreen rotation), we show black instead of the
-    // incorrectly-sized frame.
+  // When we're in a fullscreen and and doing a resize we show black
+  // instead of the incorrectly-sized frame. However when we are just
+  // adjusting the height we keep the frames because it is a less jarring
+  // experience for the user instead frames shown as black.
+  bool is_width_same =
+      current_surface_size_.width() == view_.GetPhysicalBackingSize().width();
+  if (!is_width_same) {
     EvictDelegatedFrame();
     UpdateBackgroundColor(SK_ColorBLACK);
   }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index c09cf642..4813afa 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -381,8 +381,9 @@
 
   cursor_manager_.reset(new CursorManager(this));
 
-  SetOverscrollControllerEnabled(OverscrollConfig::GetMode() !=
-                                 OverscrollConfig::Mode::kDisabled);
+  SetOverscrollControllerEnabled(
+      OverscrollConfig::GetHistoryNavigationMode() !=
+      OverscrollConfig::HistoryNavigationMode::kDisabled);
 
   selection_controller_client_.reset(
       new TouchSelectionControllerClientAura(this));
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index 250af71d..dde32c7d 100644
--- a/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -17,7 +17,6 @@
 #import "content/browser/cocoa/system_hotkey_helper_mac.h"
 #import "content/browser/cocoa/system_hotkey_map.h"
 #include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
 #import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
 #import "content/public/browser/render_widget_host_view_mac_delegate.h"
@@ -526,8 +525,6 @@
   // Don't cancel child popups; the key events are probably what's triggering
   // the popup in the first place.
 
-  RenderWidgetHostImpl* widgetHost = renderWidgetHostView_->host();
-  DCHECK(widgetHost);
 
   NativeWebKeyboardEvent event(theEvent);
   ui::LatencyInfo latency_info;
@@ -538,13 +535,6 @@
 
   latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
 
-  // If there are multiple widgets on the page (such as when there are
-  // out-of-process iframes), pick the one that should process this event.
-  if (widgetHost->delegate())
-    widgetHost = widgetHost->delegate()->GetFocusedRenderWidgetHost(widgetHost);
-  if (!widgetHost)
-    return;
-
   // Do not forward key up events unless preceded by a matching key down,
   // otherwise we might get an event from releasing the return key in the
   // omnibox (https://crbug.com/338736) or from closing another window
@@ -555,6 +545,11 @@
       return;
   }
 
+  // Tell the client that we are beginning a keyboard event. This ensures that
+  // all event and Ime messages target the same RenderWidgetHost throughout this
+  // function call.
+  client_->OnNSViewBeginKeyboardEvent();
+
   ui::TextInputType textInputType = ui::TEXT_INPUT_TYPE_NONE;
   client_->OnNSViewSyncGetTextInputType(&textInputType);
   bool shouldAutohideCursor = textInputType != ui::TEXT_INPUT_TYPE_NONE &&
@@ -563,7 +558,7 @@
 
   // We only handle key down events and just simply forward other events.
   if (eventType != NSKeyDown) {
-    widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
+    client_->OnNSViewForwardKeyboardEvent(event, latency_info);
 
     // Possibly autohide the cursor.
     if (shouldAutohideCursor) {
@@ -571,6 +566,7 @@
       cursorHidden_ = YES;
     }
 
+    client_->OnNSViewEndKeyboardEvent();
     return;
   }
 
@@ -620,7 +616,7 @@
     NativeWebKeyboardEvent fakeEvent = event;
     fakeEvent.windows_key_code = 0xE5;  // VKEY_PROCESSKEY
     fakeEvent.skip_in_browser = true;
-    widgetHost->ForwardKeyboardEventWithLatencyInfo(fakeEvent, latency_info);
+    client_->OnNSViewForwardKeyboardEvent(fakeEvent, latency_info);
     // If this key event was handled by the input method, but
     // -doCommandBySelector: (invoked by the call to -interpretKeyEvents: above)
     // enqueued edit commands, then in order to let webkit handle them
@@ -631,15 +627,13 @@
     if (hasEditCommands_ && !hasMarkedText_)
       delayEventUntilAfterImeCompostion = YES;
   } else {
-    widgetHost->ForwardKeyboardEventWithCommands(event, latency_info,
-                                                 &editCommands_);
+    client_->OnNSViewForwardKeyboardEventWithCommands(event, latency_info,
+                                                      editCommands_);
   }
 
   // Calling ForwardKeyboardEventWithCommands() could have destroyed the
-  // widget. When the widget was destroyed,
-  // |renderWidgetHostView_->host()| will be set to NULL. So we
-  // check it here and return immediately if it's NULL.
-  if (!renderWidgetHostView_->host())
+  // widget.
+  if (clientWasDestroyed_)
     return;
 
   // Then send keypress and/or composition related events.
@@ -656,8 +650,8 @@
   BOOL textInserted = NO;
   if (textToBeInserted_.length() >
       ((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
-    widgetHost->ImeCommitText(textToBeInserted_, std::vector<ui::ImeTextSpan>(),
-                              gfx::Range::InvalidRange(), 0);
+    client_->OnNSViewImeCommitText(textToBeInserted_,
+                                   gfx::Range::InvalidRange());
     textInserted = YES;
   }
 
@@ -668,15 +662,15 @@
     // composition node in WebKit.
     // When marked text is available, |markedTextSelectedRange_| will be the
     // range being selected inside the marked text.
-    widgetHost->ImeSetComposition(markedText_, ime_text_spans_,
-                                  setMarkedTextReplacementRange_,
-                                  markedTextSelectedRange_.location,
-                                  NSMaxRange(markedTextSelectedRange_));
+    client_->OnNSViewImeSetComposition(markedText_, ime_text_spans_,
+                                       setMarkedTextReplacementRange_,
+                                       markedTextSelectedRange_.location,
+                                       NSMaxRange(markedTextSelectedRange_));
   } else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
     if (unmarkTextCalled_) {
-      widgetHost->ImeFinishComposingText(false);
+      client_->OnNSViewImeFinishComposingText();
     } else {
-      widgetHost->ImeCancelComposition();
+      client_->OnNSViewImeCancelComposition();
     }
   }
 
@@ -698,20 +692,17 @@
     fakeEvent.skip_in_browser = true;
     ui::LatencyInfo fake_event_latency_info = latency_info;
     fake_event_latency_info.set_source_event_type(ui::SourceEventType::OTHER);
-    widgetHost->ForwardKeyboardEventWithLatencyInfo(fakeEvent,
-                                                    fake_event_latency_info);
+    client_->OnNSViewForwardKeyboardEvent(fakeEvent, fake_event_latency_info);
     // Not checking |renderWidgetHostView_->host()| here because
     // a key event with |skip_in_browser| == true won't be handled by browser,
     // thus it won't destroy the widget.
 
-    widgetHost->ForwardKeyboardEventWithCommands(event, fake_event_latency_info,
-                                                 &editCommands_);
+    client_->OnNSViewForwardKeyboardEventWithCommands(
+        event, fake_event_latency_info, editCommands_);
 
     // Calling ForwardKeyboardEventWithCommands() could have destroyed the
-    // widget. When the widget was destroyed,
-    // |renderWidgetHostView_->host()| will be set to NULL. So we
-    // check it here and return immediately if it's NULL.
-    if (!renderWidgetHostView_->host())
+    // widget.
+    if (clientWasDestroyed_)
       return;
   }
 
@@ -725,7 +716,7 @@
       event.text[0] = textToBeInserted_[0];
       event.text[1] = 0;
       event.skip_in_browser = true;
-      widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
+      client_->OnNSViewForwardKeyboardEvent(event, latency_info);
     } else if ((!textInserted || delayEventUntilAfterImeCompostion) &&
                event.text[0] != '\0' &&
                ((modifierFlags & kCtrlCmdKeyMask) ||
@@ -735,7 +726,7 @@
       // cases, unless the key event generated any other command.
       event.SetType(blink::WebInputEvent::kChar);
       event.skip_in_browser = true;
-      widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
+      client_->OnNSViewForwardKeyboardEvent(event, latency_info);
     }
   }
 
@@ -744,6 +735,8 @@
     [NSCursor setHiddenUntilMouseMoves:YES];
     cursorHidden_ = YES;
   }
+
+  client_->OnNSViewEndKeyboardEvent();
 }
 
 - (BOOL)suppressNextKeyUpForTesting:(int)keyCode {
@@ -1546,9 +1539,7 @@
   // If we are handling a key down event, then FinishComposingText() will be
   // called in keyEvent: method.
   if (!handlingKeyDown_) {
-    if (renderWidgetHostView_->GetActiveWidget()) {
-      renderWidgetHostView_->GetActiveWidget()->ImeFinishComposingText(false);
-    }
+    client_->OnNSViewImeFinishComposingText();
   } else {
     unmarkTextCalled_ = YES;
   }
@@ -1591,11 +1582,9 @@
   if (handlingKeyDown_) {
     setMarkedTextReplacementRange_ = gfx::Range(replacementRange);
   } else {
-    if (renderWidgetHostView_->GetActiveWidget()) {
-      renderWidgetHostView_->GetActiveWidget()->ImeSetComposition(
-          markedText_, ime_text_spans_, gfx::Range(replacementRange),
-          newSelRange.location, NSMaxRange(newSelRange));
-    }
+    client_->OnNSViewImeSetComposition(
+        markedText_, ime_text_spans_, gfx::Range(replacementRange),
+        newSelRange.location, NSMaxRange(newSelRange));
   }
 }
 
@@ -1647,11 +1636,8 @@
     textToBeInserted_.append(base::SysNSStringToUTF16(im_text));
   } else {
     gfx::Range replacement_range(replacementRange);
-    if (renderWidgetHostView_->GetActiveWidget()) {
-      renderWidgetHostView_->GetActiveWidget()->ImeCommitText(
-          base::SysNSStringToUTF16(im_text), std::vector<ui::ImeTextSpan>(),
-          replacement_range, 0);
-    }
+    client_->OnNSViewImeCommitText(base::SysNSStringToUTF16(im_text),
+                                   replacement_range);
   }
 
   // Inserting text will delete all marked text automatically.
@@ -1753,10 +1739,7 @@
   if (!hasMarkedText_)
     return;
 
-  if (renderWidgetHostView_->GetActiveWidget()) {
-    renderWidgetHostView_->GetActiveWidget()->ImeFinishComposingText(false);
-  }
-
+  client_->OnNSViewImeFinishComposingText();
   [self cancelComposition];
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 7a4e63f..90707a5 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -288,6 +288,15 @@
   void OnNSViewWindowFrameInScreenChanged(
       const gfx::Rect& window_frame_in_screen_dip) override;
   void OnNSViewDisplayChanged(const display::Display& display) override;
+  void OnNSViewBeginKeyboardEvent() override;
+  void OnNSViewEndKeyboardEvent() override;
+  void OnNSViewForwardKeyboardEvent(
+      const NativeWebKeyboardEvent& key_event,
+      const ui::LatencyInfo& latency_info) override;
+  void OnNSViewForwardKeyboardEventWithCommands(
+      const NativeWebKeyboardEvent& key_event,
+      const ui::LatencyInfo& latency_info,
+      const std::vector<EditCommand>& commands) override;
   void OnNSViewRouteOrProcessMouseEvent(
       const blink::WebMouseEvent& web_event) override;
   void OnNSViewRouteOrProcessWheelEvent(
@@ -301,6 +310,16 @@
   void OnNSViewGestureEnd(blink::WebGestureEvent end_event) override;
   void OnNSViewSmartMagnify(
       const blink::WebGestureEvent& smart_magnify_event) override;
+  void OnNSViewImeSetComposition(
+      const base::string16& text,
+      const std::vector<ui::ImeTextSpan>& ime_text_spans,
+      const gfx::Range& replacement_range,
+      int selection_start,
+      int selection_end) override;
+  void OnNSViewImeCommitText(const base::string16& text,
+                             const gfx::Range& replacement_range) override;
+  void OnNSViewImeFinishComposingText() override;
+  void OnNSViewImeCancelComposition() override;
   void OnNSViewLookUpDictionaryOverlayAtPoint(
       const gfx::PointF& root_point) override;
   void OnNSViewLookUpDictionaryOverlayFromRange(
@@ -372,6 +391,19 @@
   // in the destruction path of the WebContentsImpl.
   RenderWidgetHostDelegate* GetFocusedRenderWidgetHostDelegate();
 
+  // Returns the RenderWidgetHostImpl to which Ime messages from the NSView
+  // should be targeted. This exists to preserve historical behavior, and may
+  // not be the desired behavior.
+  // https://crbug.com/831843
+  RenderWidgetHostImpl* GetWidgetForIme();
+
+  // When inside a block of handling a keyboard event, returns the
+  // RenderWidgetHostImpl to which all keyboard and Ime messages from the NSView
+  // should be fowarded. This exists to preserve historical behavior, and may
+  // not be the desired behavior.
+  // https://crbug.com/831843
+  RenderWidgetHostImpl* GetWidgetForKeyboardEvent();
+
  private:
   friend class RenderWidgetHostViewMacTest;
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewMacTest, GetPageTextForSpeech);
@@ -473,6 +505,12 @@
   // Used to track active password input sessions.
   std::unique_ptr<ui::ScopedPasswordInputEnabler> password_input_enabler_;
 
+  // Used to ensure that a consistent RenderWidgetHost is targeted throughout
+  // the duration of a keyboard event.
+  bool in_keyboard_event_ = false;
+  int32_t keyboard_event_widget_process_id_ = 0;
+  int32_t keyboard_event_widget_routing_id_ = 0;
+
   // When a gesture starts, the system does not inform the view of which type
   // of gesture is happening (magnify, rotate, etc), rather, it just informs
   // the view that some as-yet-undefined gesture is starting. Capture the
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 77d296e..5788da5 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -307,6 +307,18 @@
   return host()->delegate();
 }
 
+RenderWidgetHostImpl* RenderWidgetHostViewMac::GetWidgetForKeyboardEvent() {
+  DCHECK(in_keyboard_event_);
+  return RenderWidgetHostImpl::FromID(keyboard_event_widget_process_id_,
+                                      keyboard_event_widget_routing_id_);
+}
+
+RenderWidgetHostImpl* RenderWidgetHostViewMac::GetWidgetForIme() {
+  if (in_keyboard_event_)
+    return GetWidgetForKeyboardEvent();
+  return GetActiveWidget();
+}
+
 void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
   if (!browser_compositor_)
     return;
@@ -1306,6 +1318,44 @@
   UpdateNSViewAndDisplayProperties();
 }
 
+void RenderWidgetHostViewMac::OnNSViewBeginKeyboardEvent() {
+  DCHECK(!in_keyboard_event_);
+  in_keyboard_event_ = true;
+  RenderWidgetHostImpl* widget_host = host();
+  if (widget_host && widget_host->delegate()) {
+    widget_host =
+        widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
+  }
+  if (widget_host) {
+    keyboard_event_widget_process_id_ = widget_host->GetProcess()->GetID();
+    keyboard_event_widget_routing_id_ = widget_host->GetRoutingID();
+  }
+}
+
+void RenderWidgetHostViewMac::OnNSViewEndKeyboardEvent() {
+  in_keyboard_event_ = false;
+  keyboard_event_widget_process_id_ = 0;
+  keyboard_event_widget_routing_id_ = 0;
+}
+
+void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEvent(
+    const NativeWebKeyboardEvent& key_event,
+    const ui::LatencyInfo& latency_info) {
+  if (auto* widget_host = GetWidgetForKeyboardEvent()) {
+    widget_host->ForwardKeyboardEventWithLatencyInfo(key_event, latency_info);
+  }
+}
+
+void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEventWithCommands(
+    const NativeWebKeyboardEvent& key_event,
+    const ui::LatencyInfo& latency_info,
+    const std::vector<EditCommand>& commands) {
+  if (auto* widget_host = GetWidgetForKeyboardEvent()) {
+    widget_host->ForwardKeyboardEventWithCommands(key_event, latency_info,
+                                                  &commands);
+  }
+}
+
 void RenderWidgetHostViewMac::OnNSViewRouteOrProcessMouseEvent(
     const blink::WebMouseEvent& const_web_event) {
   blink::WebMouseEvent web_event = const_web_event;
@@ -1425,6 +1475,39 @@
   host()->ForwardGestureEvent(smart_magnify_event);
 }
 
+void RenderWidgetHostViewMac::OnNSViewImeSetComposition(
+    const base::string16& text,
+    const std::vector<ui::ImeTextSpan>& ime_text_spans,
+    const gfx::Range& replacement_range,
+    int selection_start,
+    int selection_end) {
+  if (auto* widget_host = GetWidgetForIme()) {
+    widget_host->ImeSetComposition(text, ime_text_spans, replacement_range,
+                                   selection_start, selection_end);
+  }
+}
+
+void RenderWidgetHostViewMac::OnNSViewImeCommitText(
+    const base::string16& text,
+    const gfx::Range& replacement_range) {
+  if (auto* widget_host = GetWidgetForIme()) {
+    widget_host->ImeCommitText(text, std::vector<ui::ImeTextSpan>(),
+                               replacement_range, 0);
+  }
+}
+
+void RenderWidgetHostViewMac::OnNSViewImeFinishComposingText() {
+  if (auto* widget_host = GetWidgetForIme()) {
+    widget_host->ImeFinishComposingText(false);
+  }
+}
+
+void RenderWidgetHostViewMac::OnNSViewImeCancelComposition() {
+  if (auto* widget_host = GetWidgetForIme()) {
+    widget_host->ImeCancelComposition();
+  }
+}
+
 void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayFromRange(
     const gfx::Range& range) {
   content::RenderWidgetHostViewBase* focused_view =
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 6e81e9b5..baf6eb5 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -2487,13 +2487,7 @@
 };
 
 static int CountRenderProcessHosts() {
-  int result = 0;
-  for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator());
-       !iter.IsAtEnd();
-       iter.Advance()) {
-    result++;
-  }
-  return result;
+  return RenderProcessHost::GetCurrentRenderProcessCountForTesting();
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
diff --git a/content/browser/service_worker/service_worker_process_manager_unittest.cc b/content/browser/service_worker/service_worker_process_manager_unittest.cc
index 31aa5ce..01390912 100644
--- a/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -35,7 +35,11 @@
       SiteInstance* site_instance) const override {
     processes_.push_back(
         std::make_unique<MockRenderProcessHost>(browser_context));
-    last_site_instance_used_ = site_instance;
+
+    // A spare RenderProcessHost is created with a null SiteInstance.
+    if (site_instance)
+      last_site_instance_used_ = site_instance;
+
     return processes_.back().get();
   }
 
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index 97ed3d30..95595ca 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -625,20 +625,22 @@
   if (AreAllSitesIsolatedForTesting())
     return;
 
-  // On Android by default the number of renderer hosts is unlimited and process
-  // sharing doesn't happen. We set the override so that the test can run
-  // everywhere.
-  RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount);
-
   ChildProcessSecurityPolicyImpl* policy =
       ChildProcessSecurityPolicyImpl::GetInstance();
 
   // Make a bunch of mock renderers so that we hit the limit.
   std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
   std::vector<std::unique_ptr<MockRenderProcessHost>> hosts;
-  for (size_t i = 0; i < kMaxRendererProcessCount; ++i)
+  for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
     hosts.push_back(
         std::make_unique<MockRenderProcessHost>(browser_context.get()));
+    hosts[i]->SetIsUsed();
+  }
+
+  // On Android by default the number of renderer hosts is unlimited and process
+  // sharing doesn't happen. We set the override so that the test can run
+  // everywhere.
+  RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount);
 
   // Create some extension instances and make sure they share a process.
   scoped_refptr<SiteInstanceImpl> extension1_instance(
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 3cc972f6..722dc295 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -1870,8 +1870,16 @@
 // resultant page scale factor is the same for OOPIF and non-OOPIF cases. This
 // also verifies that in response to the scroll command, the root-layer scrolls
 // correctly and the <input> is visible in visual viewport.
+#if defined(OS_ANDROID)
+// crbug.com/793616
+#define MAYBE_ScrollFocusedEditableElementIntoView \
+  DISABLED_ScrollFocusedEditableElementIntoView
+#else
+#define MAYBE_ScrollFocusedEditableElementIntoView \
+  ScrollFocusedEditableElementIntoView
+#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessProgrammaticScrollTest,
-                       ScrollFocusedEditableElementIntoView) {
+                       MAYBE_ScrollFocusedEditableElementIntoView) {
   GURL url_a(embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));
   GURL url_b(embedded_test_server()->GetURL("b.com", kIframeOutOfViewHTML));
 
@@ -11278,4 +11286,66 @@
   EXPECT_EQ(top_origin + "/", main_url.GetOrigin().spec());
 }
 
+// Check that when a postMessage is called on a remote frame, it waits for the
+// current script block to finish executing before forwarding the postMessage,
+// so that if the script causes any other IPCs to be sent in the same event
+// loop iteration, those IPCs are processed, and their side effects are
+// observed by the target frame before it receives the forwarded postMessage.
+// See https://crbug.com/828529.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+                       CrossProcessPostMessageWaitsForCurrentScriptToFinish) {
+  GURL main_url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(b)"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+  EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame());
+
+  // Add an onmessage handler to the subframe to send back a bool of whether
+  // the subframe has focus.
+  EXPECT_TRUE(
+      ExecuteScript(root->child_at(0),
+                    "window.addEventListener('message', function(event) {\n"
+                    "  domAutomationController.send(document.hasFocus());\n"
+                    "});"));
+
+  // Now, send a postMessage from main frame to subframe, and then focus the
+  // subframe in the same script.  postMessage should be scheduled after the
+  // focus() call, so the IPC to focus the subframe should arrive before the
+  // postMessage IPC, and the subframe should already know that it's focused in
+  // the onmessage handler.
+  bool child_has_focus = false;
+  EXPECT_TRUE(ExecuteScriptAndExtractBool(root,
+                                          "frames[0].postMessage('','*');\n"
+                                          "frames[0].focus();\n",
+                                          &child_has_focus));
+  EXPECT_TRUE(child_has_focus);
+}
+
+// Ensure that if a cross-process postMessage is scheduled, and then the target
+// frame is detached before the postMessage is forwarded, the source frame's
+// renderer does not crash.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+                       CrossProcessPostMessageAndDetachTarget) {
+  GURL main_url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(b)"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+  // Send a postMessage to the subframe and then immediately detach the
+  // subframe.
+  EXPECT_TRUE(ExecuteScript(root,
+                            "frames[0].postMessage('','*');\n"
+                            "document.body.removeChild(\n"
+                            "    document.querySelector('iframe'));\n"));
+
+  // Test passes if the main renderer doesn't crash.  Use setTimeout to ensure
+  // this ping is evaluated after the (scheduled) postMessage is processed.
+  bool success;
+  EXPECT_TRUE(ExecuteScriptAndExtractBool(
+      root,
+      "setTimeout(() => { window.domAutomationController.send(true); }, 0)",
+      &success));
+  EXPECT_TRUE(success);
+}
+
 }  // namespace content
diff --git a/content/browser/tracing/memory_instrumentation_browsertest.cc b/content/browser/tracing/memory_instrumentation_browsertest.cc
index fcc0bec..5ebe6aa5 100644
--- a/content/browser/tracing/memory_instrumentation_browsertest.cc
+++ b/content/browser/tracing/memory_instrumentation_browsertest.cc
@@ -6,6 +6,9 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -29,13 +32,18 @@
 };
 
 uint64_t GetPrivateFootprintKb(ProcessType type,
-                               const GlobalMemoryDump& global_dump) {
+                               const GlobalMemoryDump& global_dump,
+                               base::ProcessId pid = base::kNullProcessId) {
   const GlobalMemoryDump::ProcessDump* target_dump = nullptr;
   for (const auto& dump : global_dump.process_dumps()) {
-    if (dump.process_type() == type) {
-      EXPECT_FALSE(target_dump);
-      target_dump = &dump;
-    }
+    if (dump.process_type() != type)
+      continue;
+
+    if (pid != base::kNullProcessId && pid != dump.pid())
+      continue;
+
+    EXPECT_FALSE(target_dump);
+    target_dump = &dump;
   }
   EXPECT_TRUE(target_dump);
   return target_dump->os_dump().private_footprint_kb;
@@ -87,6 +95,9 @@
   EXPECT_EQ(x[0] + x[kAllocSize - 1], 2);
 
   content::WebContents* web_contents = shell()->web_contents();
+  base::ProcessId renderer_pid =
+      base::GetProcId(web_contents->GetMainFrame()->GetProcess()->GetHandle());
+
   // Should allocate at least 4*10^6 / 1024 = 4000kb.
   EXPECT_TRUE(content::ExecuteScript(web_contents,
                                      "var a = Array(1000000).fill(1234);\n"));
@@ -109,9 +120,9 @@
               AllOf(Ge(kAllocSizeKb - 3000), Le(kAllocSizeKb + 3000)));
 
   int64_t before_renderer_kb =
-      GetPrivateFootprintKb(ProcessType::RENDERER, *before_ptr);
+      GetPrivateFootprintKb(ProcessType::RENDERER, *before_ptr, renderer_pid);
   int64_t during_renderer_kb =
-      GetPrivateFootprintKb(ProcessType::RENDERER, *during_ptr);
+      GetPrivateFootprintKb(ProcessType::RENDERER, *during_ptr, renderer_pid);
   EXPECT_GE(during_renderer_kb - before_renderer_kb, 3000);
 }
 
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 0673c307..3aea2d2 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -556,19 +556,20 @@
 
 void WebContentsViewAura::InstallOverscrollControllerDelegate(
     RenderWidgetHostViewAura* view) {
-  const OverscrollConfig::Mode mode = OverscrollConfig::GetMode();
+  const OverscrollConfig::HistoryNavigationMode mode =
+      OverscrollConfig::GetHistoryNavigationMode();
   switch (mode) {
-    case OverscrollConfig::Mode::kDisabled:
+    case OverscrollConfig::HistoryNavigationMode::kDisabled:
       navigation_overlay_.reset();
       break;
-    case OverscrollConfig::Mode::kParallaxUi:
+    case OverscrollConfig::HistoryNavigationMode::kParallaxUi:
       view->overscroll_controller()->set_delegate(this);
       if (!navigation_overlay_ && !is_mus_browser_plugin_guest_) {
         navigation_overlay_.reset(
             new OverscrollNavigationOverlay(web_contents_, window_.get()));
       }
       break;
-    case OverscrollConfig::Mode::kSimpleUi:
+    case OverscrollConfig::HistoryNavigationMode::kSimpleUi:
       navigation_overlay_.reset();
       if (!gesture_nav_simple_)
         gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 86a6574e..35a9c560 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -37,7 +37,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/scoped_overscroll_mode.h"
+#include "content/public/test/scoped_overscroll_modes.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
@@ -613,7 +613,8 @@
 #define MAYBE_OverscrollScreenshot OverscrollScreenshot
 #endif
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
-  ScopedOverscrollMode scoped_mode(OverscrollConfig::Mode::kParallaxUi);
+  ScopedHistoryNavigationMode scoped_mode(
+      OverscrollConfig::HistoryNavigationMode::kParallaxUi);
 
   ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
   WebContentsImpl* web_contents =
@@ -704,7 +705,8 @@
 // RenderViewHost to be swapped out.
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
                        MAYBE_ScreenshotForSwappedOutRenderViews) {
-  ScopedOverscrollMode scoped_mode(OverscrollConfig::Mode::kParallaxUi);
+  ScopedHistoryNavigationMode scoped_mode(
+      OverscrollConfig::HistoryNavigationMode::kParallaxUi);
 
   ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
   // Create a new server with a different site.
@@ -776,7 +778,8 @@
 // Tests that navigations resulting from reloads, history.replaceState,
 // and history.pushState do not capture screenshots.
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) {
-  ScopedOverscrollMode scoped_mode(OverscrollConfig::Mode::kParallaxUi);
+  ScopedHistoryNavigationMode scoped_mode(
+      OverscrollConfig::HistoryNavigationMode::kParallaxUi);
 
   ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
   WebContentsImpl* web_contents =
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc
index 20fcc68..3e8e141 100644
--- a/content/browser/webauth/authenticator_impl.cc
+++ b/content/browser/webauth/authenticator_impl.cc
@@ -29,6 +29,7 @@
 #include "device/fido/authenticator_selection_criteria.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/get_assertion_request_handler.h"
 #include "device/fido/make_credential_request_handler.h"
 #include "device/fido/public_key_credential_descriptor.h"
@@ -36,7 +37,6 @@
 #include "device/fido/u2f_register.h"
 #include "device/fido/u2f_request.h"
 #include "device/fido/u2f_sign.h"
-#include "device/fido/u2f_transport_protocol.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -336,9 +336,9 @@
   DCHECK(render_frame_host_);
   DCHECK(timer_);
 
-  protocols_.insert(device::U2fTransportProtocol::kUsbHumanInterfaceDevice);
+  protocols_.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
   if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
-    protocols_.insert(device::U2fTransportProtocol::kBluetoothLowEnergy);
+    protocols_.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
   }
 }
 
@@ -462,17 +462,17 @@
       !AreOptionsSupportedByU2fAuthenticators(options)) {
     InvokeCallbackAndCleanup(
         std::move(callback),
-        webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+        webauth::mojom::AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+        nullptr);
     return;
   }
 
-  // TODO(crbug.com/819256): Improve messages for "Not Supported" errors.
   if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
       !IsAlgorithmSupportedByU2fAuthenticators(
           options->public_key_parameters)) {
     InvokeCallbackAndCleanup(
         std::move(callback),
-        webauth::mojom::AuthenticatorStatus::NOT_SUPPORTED_ERROR, nullptr);
+        webauth::mojom::AuthenticatorStatus::ALGORITHM_UNSUPPORTED, nullptr);
     return;
   }
 
@@ -580,7 +580,8 @@
           webauth::mojom::UserVerificationRequirement::REQUIRED) {
     InvokeCallbackAndCleanup(
         std::move(callback),
-        webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+        webauth::mojom::AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
+        nullptr);
     return;
   }
 
@@ -601,13 +602,32 @@
     echo_appid_extension_ = true;
   }
 
-  DCHECK(get_assertion_response_callback_.is_null());
-  get_assertion_response_callback_ = std::move(callback);
-
-  // Pass along valid keys from allow_list, if any.
+  // Pass along valid keys from allow_list.
   std::vector<std::vector<uint8_t>> handles =
       FilterCredentialList(std::move(options->allow_credentials));
 
+  // There are two different descriptions of what should happen when
+  // "allowCredentials" is empty.
+  // a) WebAuthN 6.2.3 step 6[1] implies "NotAllowedError".
+  // b) CTAP step 7.2 step 2[2] says the device should error out with
+  // "CTAP2_ERR_OPTION_NOT_SUPPORTED". This also resolves to "NotAllowedError".
+  // The behavior in both cases is consistent with the current implementation.
+  // TODO(crbug.com/831712): When CTAP2 authenticators are supported, this check
+  // should be enforced by handlers in fido/device on a per-device basis.
+
+  // [1] https://w3c.github.io/webauthn/#authenticatorgetassertion
+  // [2]
+  // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html
+  if (handles.empty()) {
+    InvokeCallbackAndCleanup(
+        std::move(callback),
+        webauth::mojom::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, nullptr);
+    return;
+  }
+
+  DCHECK(get_assertion_response_callback_.is_null());
+  get_assertion_response_callback_ = std::move(callback);
+
   timer_->Start(
       FROM_HERE, options->adjusted_timeout,
       base::Bind(&AuthenticatorImpl::OnTimeout, base::Unretained(this)));
@@ -666,7 +686,7 @@
       // |exclude_credentials|.
       InvokeCallbackAndCleanup(
           std::move(make_credential_response_callback_),
-          webauth::mojom::AuthenticatorStatus::INVALID_STATE, nullptr);
+          webauth::mojom::AuthenticatorStatus::CREDENTIAL_EXCLUDED, nullptr);
       return;
     case device::FidoReturnCode::kAuthenticatorResponseInvalid:
       // The response from the authenticator was corrupted.
@@ -759,7 +779,8 @@
       // No authenticators contained the credential.
       InvokeCallbackAndCleanup(
           std::move(get_assertion_response_callback_),
-          webauth::mojom::AuthenticatorStatus::INVALID_STATE, nullptr);
+          webauth::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+          nullptr);
       return;
     case device::FidoReturnCode::kAuthenticatorResponseInvalid:
       // The response from the authenticator was corrupted.
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h
index 66307161..c3f4aac5 100644
--- a/content/browser/webauth/authenticator_impl.h
+++ b/content/browser/webauth/authenticator_impl.h
@@ -19,7 +19,7 @@
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
 #include "url/origin.h"
@@ -133,7 +133,7 @@
 
   RenderFrameHost* render_frame_host_;
   service_manager::Connector* connector_ = nullptr;
-  base::flat_set<device::U2fTransportProtocol> protocols_;
+  base::flat_set<device::FidoTransportProtocol> protocols_;
 
   std::unique_ptr<device::U2fRequest> u2f_request_;
   std::unique_ptr<device::FidoRequestHandlerBase> ctap_request_;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index b10a9b6..c5e56de4 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -383,11 +383,11 @@
     TestMakeCredentialCallback cb;
     authenticator->MakeCredential(std::move(options), cb.callback());
     cb.WaitForCallback();
-    EXPECT_EQ(AuthenticatorStatus::NOT_SUPPORTED_ERROR, cb.status());
+    EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED, cb.status());
   }
 }
 
-// Test that service returns NOT_SUPPORTED_ERROR if no parameters contain
+// Test that service returns ALGORITHM_UNSUPPORTED if no parameters contain
 // a supported algorithm.
 TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
   SimulateNavigation(GURL(kTestOrigin1));
@@ -400,11 +400,11 @@
   TestMakeCredentialCallback cb;
   authenticator->MakeCredential(std::move(options), cb.callback());
   cb.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_SUPPORTED_ERROR, cb.status());
+  EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED, cb.status());
 }
 
-// Test that service returns NOT_ALLOWED_ERROR if user verification is
-// REQUIRED for get().
+// Test that service returns USER_VERIFICATION_UNSUPPORTED if user verification
+// is REQUIRED for get().
 TEST_F(AuthenticatorImplTest, GetAssertionUserVerification) {
   SimulateNavigation(GURL(kTestOrigin1));
   AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -416,11 +416,11 @@
   TestGetAssertionCallback cb;
   authenticator->GetAssertion(std::move(options), cb.callback());
   cb.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+  EXPECT_EQ(AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED, cb.status());
 }
 
-// Test that service returns NOT_ALLOWED_ERROR if user verification is
-// REQUIRED for create().
+// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if user
+// verification is REQUIRED for create().
 TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
   SimulateNavigation(GURL(kTestOrigin1));
   AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -433,11 +433,12 @@
   TestMakeCredentialCallback cb;
   authenticator->MakeCredential(std::move(options), cb.callback());
   cb.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+            cb.status());
 }
 
-// Test that service returns NOT_ALLOWED_ERROR if resident key is
-// requested for create().
+// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if resident key
+// is requested for create().
 TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
   SimulateNavigation(GURL(kTestOrigin1));
   AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -449,11 +450,12 @@
   TestMakeCredentialCallback cb;
   authenticator->MakeCredential(std::move(options), cb.callback());
   cb.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+            cb.status());
 }
 
-// Test that service returns NOT_ALLOWED_ERROR if a platform authenticator is
-// requested for U2F.
+// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if a platform
+// authenticator is requested for U2F.
 TEST_F(AuthenticatorImplTest, MakeCredentialPlatformAuthenticator) {
   SimulateNavigation(GURL(kTestOrigin1));
   AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -466,7 +468,8 @@
   TestMakeCredentialCallback cb;
   authenticator->MakeCredential(std::move(options), cb.callback());
   cb.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+            cb.status());
 }
 
 // Parses its arguments as JSON and expects that all the keys in the first are
@@ -612,7 +615,7 @@
     SCOPED_TRACE(std::string(test_case.origin) + " " +
                  std::string(test_case.claimed_authority));
 
-    EXPECT_EQ(AuthenticatorStatus::INVALID_STATE,
+    EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
               TryAuthenticationWithAppId(test_case.origin,
                                          test_case.claimed_authority));
   }
@@ -702,7 +705,7 @@
     if (should_be_valid) {
       EXPECT_EQ(AuthenticatorStatus::SUCCESS, cb.status());
     } else {
-      EXPECT_EQ(AuthenticatorStatus::INVALID_STATE, cb.status());
+      EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED, cb.status());
     }
   }
 }
@@ -773,6 +776,23 @@
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
 }
 
+TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
+  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+  TestServiceManagerContext service_manager_context;
+
+  SimulateNavigation(GURL(kTestOrigin1));
+  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  PublicKeyCredentialRequestOptionsPtr options =
+      GetTestPublicKeyCredentialRequestOptions();
+  options->allow_credentials.clear();
+
+  TestGetAssertionCallback cb;
+  authenticator->GetAssertion(std::move(options), cb.callback());
+  cb.WaitForCallback();
+
+  EXPECT_EQ(AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, cb.status());
+}
+
 enum class IndividualAttestation {
   REQUESTED,
   NOT_REQUESTED,
diff --git a/content/browser/webauth/authenticator_type_converters.cc b/content/browser/webauth/authenticator_type_converters.cc
index 8a7ffc8..c8d238b9 100644
--- a/content/browser/webauth/authenticator_type_converters.cc
+++ b/content/browser/webauth/authenticator_type_converters.cc
@@ -21,19 +21,19 @@
 using ::webauth::mojom::UserVerificationRequirement;
 
 // static
-::device::U2fTransportProtocol
-TypeConverter<::device::U2fTransportProtocol, AuthenticatorTransport>::Convert(
+::device::FidoTransportProtocol
+TypeConverter<::device::FidoTransportProtocol, AuthenticatorTransport>::Convert(
     const AuthenticatorTransport& input) {
   switch (input) {
     case AuthenticatorTransport::USB:
-      return ::device::U2fTransportProtocol::kUsbHumanInterfaceDevice;
+      return ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
     case AuthenticatorTransport::NFC:
-      return ::device::U2fTransportProtocol::kNearFieldCommunication;
+      return ::device::FidoTransportProtocol::kNearFieldCommunication;
     case AuthenticatorTransport::BLE:
-      return ::device::U2fTransportProtocol::kBluetoothLowEnergy;
+      return ::device::FidoTransportProtocol::kBluetoothLowEnergy;
   }
   NOTREACHED();
-  return ::device::U2fTransportProtocol::kUsbHumanInterfaceDevice;
+  return ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
 }
 
 // static
diff --git a/content/browser/webauth/authenticator_type_converters.h b/content/browser/webauth/authenticator_type_converters.h
index b11c768..0f5c2a1a 100644
--- a/content/browser/webauth/authenticator_type_converters.h
+++ b/content/browser/webauth/authenticator_type_converters.h
@@ -8,11 +8,11 @@
 #include <vector>
 
 #include "device/fido/authenticator_selection_criteria.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/public_key_credential_descriptor.h"
 #include "device/fido/public_key_credential_params.h"
 #include "device/fido/public_key_credential_rp_entity.h"
 #include "device/fido/public_key_credential_user_entity.h"
-#include "device/fido/u2f_transport_protocol.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
 
@@ -22,9 +22,9 @@
 namespace mojo {
 
 template <>
-struct TypeConverter<::device::U2fTransportProtocol,
+struct TypeConverter<::device::FidoTransportProtocol,
                      ::webauth::mojom::AuthenticatorTransport> {
-  static ::device::U2fTransportProtocol Convert(
+  static ::device::FidoTransportProtocol Convert(
       const ::webauth::mojom::AuthenticatorTransport& input);
 };
 
diff --git a/content/browser/webauth/scoped_virtual_authenticator_environment.cc b/content/browser/webauth/scoped_virtual_authenticator_environment.cc
index 2a68e84..630260d0 100644
--- a/content/browser/webauth/scoped_virtual_authenticator_environment.cc
+++ b/content/browser/webauth/scoped_virtual_authenticator_environment.cc
@@ -45,7 +45,7 @@
     webauth::test::mojom::VirtualAuthenticatorOptionsPtr options,
     CreateAuthenticatorCallback callback) {
   auto authenticator = std::make_unique<VirtualAuthenticator>(
-      mojo::ConvertTo<::device::U2fTransportProtocol>(options->transport));
+      mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport));
   auto* authenticator_ptr = authenticator.get();
   authenticators_.emplace(authenticator_ptr->unique_id(),
                           std::move(authenticator));
@@ -98,7 +98,7 @@
 
 std::unique_ptr<::device::FidoDiscovery>
 ScopedVirtualAuthenticatorEnvironment::CreateFidoDiscovery(
-    device::U2fTransportProtocol transport,
+    device::FidoTransportProtocol transport,
     ::service_manager::Connector* connector) {
   auto discovery = std::make_unique<VirtualFidoDiscovery>(this, transport);
   for (auto& authenticator : authenticators_) {
diff --git a/content/browser/webauth/scoped_virtual_authenticator_environment.h b/content/browser/webauth/scoped_virtual_authenticator_environment.h
index ed21de6..142f6f2a 100644
--- a/content/browser/webauth/scoped_virtual_authenticator_environment.h
+++ b/content/browser/webauth/scoped_virtual_authenticator_environment.h
@@ -54,7 +54,7 @@
 
   // ScopedFidoDiscoveryFactory:
   std::unique_ptr<::device::FidoDiscovery> CreateFidoDiscovery(
-      device::U2fTransportProtocol transport,
+      device::FidoTransportProtocol transport,
       ::service_manager::Connector* connector) override;
 
  private:
diff --git a/content/browser/webauth/virtual_authenticator.cc b/content/browser/webauth/virtual_authenticator.cc
index 5729ec7..f830a249 100644
--- a/content/browser/webauth/virtual_authenticator.cc
+++ b/content/browser/webauth/virtual_authenticator.cc
@@ -13,7 +13,7 @@
 namespace content {
 
 VirtualAuthenticator::VirtualAuthenticator(
-    ::device::U2fTransportProtocol transport)
+    ::device::FidoTransportProtocol transport)
     : transport_(transport),
       unique_id_(base::GenerateGUID()),
       state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {}
diff --git a/content/browser/webauth/virtual_authenticator.h b/content/browser/webauth/virtual_authenticator.h
index cd8963c..c0ee5797 100644
--- a/content/browser/webauth/virtual_authenticator.h
+++ b/content/browser/webauth/virtual_authenticator.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/virtual_fido_device.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h"
@@ -26,12 +26,12 @@
 class CONTENT_EXPORT VirtualAuthenticator
     : public webauth::test::mojom::VirtualAuthenticator {
  public:
-  explicit VirtualAuthenticator(::device::U2fTransportProtocol transport);
+  explicit VirtualAuthenticator(::device::FidoTransportProtocol transport);
   ~VirtualAuthenticator() override;
 
   void AddBinding(webauth::test::mojom::VirtualAuthenticatorRequest request);
 
-  ::device::U2fTransportProtocol transport() const { return transport_; }
+  ::device::FidoTransportProtocol transport() const { return transport_; }
   const std::string& unique_id() const { return unique_id_; }
 
   // Constructs a VirtualFidoDevice instance that will perform cryptographic
@@ -55,7 +55,7 @@
   void GetUserPresence(GetUserPresenceCallback callback) override;
 
  private:
-  const ::device::U2fTransportProtocol transport_;
+  const ::device::FidoTransportProtocol transport_;
   const std::string unique_id_;
   scoped_refptr<::device::VirtualFidoDevice::State> state_;
   mojo::BindingSet<webauth::test::mojom::VirtualAuthenticator> binding_set_;
diff --git a/content/browser/webauth/virtual_discovery.cc b/content/browser/webauth/virtual_discovery.cc
index 947e0888..1f37ee8 100644
--- a/content/browser/webauth/virtual_discovery.cc
+++ b/content/browser/webauth/virtual_discovery.cc
@@ -16,7 +16,7 @@
 
 VirtualFidoDiscovery::VirtualFidoDiscovery(
     ScopedVirtualAuthenticatorEnvironment* environment,
-    ::device::U2fTransportProtocol transport)
+    ::device::FidoTransportProtocol transport)
     : FidoDiscovery(transport), environment_(environment) {}
 
 VirtualFidoDiscovery::~VirtualFidoDiscovery() {
diff --git a/content/browser/webauth/virtual_discovery.h b/content/browser/webauth/virtual_discovery.h
index 8fc7eb3b..7c57b04 100644
--- a/content/browser/webauth/virtual_discovery.h
+++ b/content/browser/webauth/virtual_discovery.h
@@ -27,7 +27,7 @@
  public:
   // The |environment| must outlive this instance.
   VirtualFidoDiscovery(ScopedVirtualAuthenticatorEnvironment* environment,
-                       ::device::U2fTransportProtocol transport);
+                       ::device::FidoTransportProtocol transport);
 
   // Notifies the |environment| of this instance being destroyed.
   ~VirtualFidoDiscovery() override;
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index 4aba309..9435db4 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -57,16 +57,33 @@
     AuthenticatorStatus,
     GetAssertionAuthenticatorResponsePtr>;
 
-constexpr char kNotAllowedErrorMessage[] =
-    "NotAllowedError: The operation either timed out or was not allowed. See: "
-    "https://w3c.github.io/webauthn/#sec-assertion-privacy.";
-
 constexpr char kRelyingPartySecurityErrorMessage[] =
     "SecurityError: The relying party ID 'localhost' is not a registrable "
     "domain suffix of, nor equal to 'https://www.example.com";
 
-constexpr char kNotSupportedErrorMessage[] =
-    "NotSupportedError: Parameters for this operation are not supported.";
+constexpr char kAlgorithmUnsupportedErrorMessage[] =
+    "NotSupportedError: None of the algorithms specified in "
+    "`pubKeyCredParams` are compatible with "
+    "CTAP1/U2F authenticators, and CTAP2 "
+    "authenticators are not yet supported.";
+
+constexpr char kAuthenticatorCriteriaErrorMessage[] =
+    "NotSupportedError: The specified `authenticatorSelection` "
+    "criteria cannot be fulfilled by CTAP1/U2F "
+    "authenticators, and CTAP2 authenticators "
+    "are not yet supported.";
+
+constexpr char kUserVerificationErrorMessage[] =
+    "NotSupportedError: The specified `userVerification` "
+    "requirement cannot be fulfilled by "
+    "CTAP1/U2F authenticators, and CTAP2 "
+    "authenticators are not yet supported.";
+
+constexpr char kEmptyAllowCredentialsErrorMessage[] =
+    "NotSupportedError: The `allowCredentials` list cannot be left "
+    "empty for CTAP1/U2F authenticators, and "
+    "support for CTAP2 authenticators is not yet "
+    "implemented.";
 
 // Templates to be used with base::ReplaceStringPlaceholders. Can be
 // modified to include up to 9 replacements. The default values for
@@ -121,11 +138,26 @@
     "  rp: 'example.com',"
     "  timeout: 60000,"
     "  userVerification: '$1',"
-    "  allowCredentials: [{ type: 'public-key',"
-    "     id: new TextEncoder().encode('allowedCredential'),"
-    "     transports: ['usb', 'nfc', 'ble']}] }"
+    "  $2}"
     "}).catch(c => window.domAutomationController.send(c.toString()));";
 
+// Default values for kGetPublicKeyTemplate.
+struct GetParameters {
+  const char* user_verification = kPreferredVerification;
+  const char* allow_credentials =
+      "allowCredentials: [{ type: 'public-key',"
+      "     id: new TextEncoder().encode('allowedCredential'),"
+      "     transports: ['usb', 'nfc', 'ble']}]";
+};
+
+std::string BuildGetCallWithParameters(const GetParameters& parameters) {
+  std::vector<std::string> substititions;
+  substititions.push_back(parameters.user_verification);
+  substititions.push_back(parameters.allow_credentials);
+  return base::ReplaceStringPlaceholders(kGetPublicKeyTemplate, substititions,
+                                         nullptr);
+}
+
 // Helper class that executes the given |closure| the very last moment before
 // the next navigation commits in a given WebContents.
 class ClosureExecutorBeforeNavigationCommit
@@ -408,7 +440,7 @@
   // serviced at all, so the fake request should still be pending on the fake
   // factory.
   auto hid_discovery = ::device::FidoDiscovery::Create(
-      ::device::U2fTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
+      ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
   ASSERT_TRUE(!!hid_discovery);
 
   // The next active document should be able to successfully call
@@ -500,7 +532,7 @@
 };
 
 // Tests that when navigator.credentials.create() is called with user
-// verification required we get a NotAllowedError.
+// verification required we get a NotSupportedError.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
                        CreatePublicKeyCredentialWithUserVerification) {
   CreateParameters parameters;
@@ -509,11 +541,11 @@
   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
-  ASSERT_EQ(kNotAllowedErrorMessage, result);
+  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.create() is called with resident key
-// required, we get a NotAllowedError.
+// required, we get a NotSupportedError.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
                        CreatePublicKeyCredentialWithResidentKeyRequired) {
   CreateParameters parameters;
@@ -523,20 +555,7 @@
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
 
-  ASSERT_EQ(kNotAllowedErrorMessage, result);
-}
-
-// Tests that when navigator.credentials.get() is called with user verification
-// required, we get a NotAllowedError.
-IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
-                       GetPublicKeyCredentialUserVerification) {
-  const std::string kScript = base::ReplaceStringPlaceholders(
-      kGetPublicKeyTemplate, {"required"}, nullptr);
-
-  std::string result;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      shell()->web_contents()->GetMainFrame(), kScript, &result));
-  ASSERT_EQ(kNotAllowedErrorMessage, result);
+  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.create() is called with an invalid
@@ -565,11 +584,11 @@
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
 
-  ASSERT_EQ(kNotSupportedErrorMessage, result);
+  ASSERT_EQ(kAlgorithmUnsupportedErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.create() is called with a
-// platform authenticator requested, we get a NotAllowedError.
+// platform authenticator requested, we get a NotSupportedError.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
                        CreatePublicKeyCredentialPlatformAuthenticator) {
   CreateParameters parameters;
@@ -579,7 +598,33 @@
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
 
-  ASSERT_EQ(kNotAllowedErrorMessage, result);
+  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
+}
+
+// Tests that when navigator.credentials.get() is called with user verification
+// required, we get a NotSupportedError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+                       GetPublicKeyCredentialUserVerification) {
+  GetParameters parameters;
+  parameters.user_verification = "required";
+  std::string result;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+      shell()->web_contents()->GetMainFrame(),
+      BuildGetCallWithParameters(parameters), &result));
+  ASSERT_EQ(kUserVerificationErrorMessage, result);
+}
+
+// Tests that when navigator.credentials.get() is called with an empty
+// allowCredentials list, we get a NotSupportedError.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+                       GetPublicKeyCredentialEmptyAllowCredentialsList) {
+  GetParameters parameters;
+  parameters.allow_credentials = "";
+  std::string result;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+      shell()->web_contents()->GetMainFrame(),
+      BuildGetCallWithParameters(parameters), &result));
+  ASSERT_EQ(kEmptyAllowCredentialsErrorMessage, result);
 }
 
 // WebAuthBrowserBleDisabledTest
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 4f8b465..86b4266 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -399,6 +399,9 @@
   if (base::FeatureList::IsEnabled(features::kKeyboardLockAPI))
     WebRuntimeFeatures::EnableFeatureFromString("KeyboardLock", true);
 
+  if (base::FeatureList::IsEnabled(features::kLazyFrameLoading))
+    WebRuntimeFeatures::EnableLazyFrameLoading(true);
+
   // Enable explicitly enabled features, and then disable explicitly disabled
   // ones.
   for (const std::string& feature :
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index f0990bb..9646d6b 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -352,7 +352,7 @@
     "//content/browser",
   ]
 
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     sources += [ "posix_file_descriptor_info.h" ]
   }
 
diff --git a/content/public/browser/overscroll_configuration.h b/content/public/browser/overscroll_configuration.h
index 2f593f5b..ef246ebf 100644
--- a/content/public/browser/overscroll_configuration.h
+++ b/content/public/browser/overscroll_configuration.h
@@ -12,20 +12,32 @@
 
 class CONTENT_EXPORT OverscrollConfig {
  public:
-  // Determines overscroll history navigation mode according to its
-  // corresponding flag.
-  enum class Mode {
-    // Overscroll history navigation is disabled.
+  // Determines overscroll history navigation mode according to
+  // --overscroll-history-navigation flag.
+  enum class HistoryNavigationMode {
+    // History navigation is disabled.
     kDisabled,
 
-    // Overscroll history navigation is enabled and uses the UI with parallax
-    // effect and screenshots.
+    // History navigation is enabled and uses the UI with parallax effect and
+    // screenshots.
     kParallaxUi,
 
-    // Overscroll history navigation is enabled and uses the simplified UI.
+    // History navigation is enabled and uses the simplified UI.
     kSimpleUi,
   };
 
+  // Determines pull-to-refresh mode according to --pull-to-refresh flag.
+  enum class PullToRefreshMode {
+    // Pull-to-refresh is disabled.
+    kDisabled,
+
+    // Pull-to-refresh is enabled for both touchscreen and touchpad.
+    kEnabled,
+
+    // Pull-to-refresh is enabled only for touchscreen.
+    kEnabledTouchschreen,
+  };
+
   // Specifies an overscroll controller threshold.
   enum class Threshold {
     // Threshold to complete touchpad overscroll, in terms of the percentage of
@@ -43,17 +55,24 @@
     kStartTouchscreen,
   };
 
-  static Mode GetMode();
+  static HistoryNavigationMode GetHistoryNavigationMode();
+  static PullToRefreshMode GetPullToRefreshMode();
 
   static float GetThreshold(Threshold threshold);
 
  private:
-  friend class ScopedOverscrollMode;
+  friend class ScopedHistoryNavigationMode;
+  friend class ScopedPullToRefreshMode;
 
-  // Helper functions used by |ScopedOverscrollMode| to set and reset mode in
+  // Helper functions used by |ScopedHistoryNavigationMode| to set and reset
+  // mode in tests.
+  static void SetHistoryNavigationMode(HistoryNavigationMode mode);
+  static void ResetHistoryNavigationMode();
+
+  // Helper functions used by |ScopedPullToRefreshMode| to set and reset mode in
   // tests.
-  static void SetMode(Mode mode);
-  static void ResetMode();
+  static void SetPullToRefreshMode(PullToRefreshMode mode);
+  static void ResetPullToRefreshMode();
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(OverscrollConfig);
 };
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index 621d24a..30213bb 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -460,9 +460,11 @@
   // The spare RenderProcessHost is meant to be created in a situation where a
   // navigation is imminent and it is unlikely an existing RenderProcessHost
   // will be used, for example in a cross-site navigation when a Service Worker
-  // will need to be started.
-  static void WarmupSpareRenderProcessHost(
-      content::BrowserContext* browser_context);
+  // will need to be started.  Note that if ContentBrowserClient opts into
+  // strict site isolation (via ShouldEnableStrictSiteIsolation), then the
+  // //content layer will maintain a warm spare process host at all times
+  // (without a need for separate calls to WarmupSpareRenderProcessHost).
+  static void WarmupSpareRenderProcessHost(BrowserContext* browser_context);
 
   // Flag to run the renderer in process.  This is primarily
   // for debugging purposes.  When running "in process", the
@@ -501,15 +503,6 @@
   static bool ShouldTryToUseExistingProcessHost(
       content::BrowserContext* browser_context, const GURL& site_url);
 
-  // Get an existing RenderProcessHost associated with the given browser
-  // context, if possible.  The renderer process is chosen randomly from
-  // suitable renderers that share the same context and type (determined by the
-  // site url).
-  // Returns nullptr if no suitable renderer process is available, in which case
-  // the caller is free to create a new renderer.
-  static RenderProcessHost* GetExistingProcessHost(
-      content::BrowserContext* browser_context, const GURL& site_url);
-
   // Overrides the default heuristic for limiting the max renderer process
   // count.  This is useful for unit testing process limit behaviors.  It is
   // also used to allow a command line parameter to configure the max number of
@@ -525,6 +518,9 @@
   using AnalyzeHungRendererFunction = void (*)(const base::Process& renderer);
   static void SetHungRendererAnalysisFunction(
       AnalyzeHungRendererFunction analyze_hung_renderer);
+
+  // Counts current RenderProcessHost(s), ignoring the spare process.
+  static int GetCurrentRenderProcessCountForTesting();
 };
 
 }  // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 5084208..1fb528a 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -155,6 +155,9 @@
 const base::Feature kKeyboardLockAPI{"KeyboardLockAPI",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kLazyFrameLoading{"LazyFrameLoading",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enable lazy initialization of the media controls.
 const base::Feature kLazyInitializeMediaControls{
     "LazyInitializeMediaControls", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -360,6 +363,12 @@
 const base::Feature kSlimmingPaintV175{"SlimmingPaintV175",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Controls whether SpareRenderProcessHostManager tries to always have a warm
+// spare renderer process around for the most recently requested BrowserContext.
+// This feature is only consulted in site-per-process mode.
+const base::Feature kSpareRendererForSitePerProcess{
+    "SpareRendererForSitePerProcess", base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Stop scheduler task queues in background after allowed grace time.
 const base::Feature kStopInBackground {
   "stop-in-background",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 4ab5779..5061a19 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -46,6 +46,7 @@
 CONTENT_EXPORT extern const base::Feature kIsolateOrigins;
 CONTENT_EXPORT extern const char kIsolateOriginsFieldTrialParamName[];
 CONTENT_EXPORT extern const base::Feature kKeyboardLockAPI;
+CONTENT_EXPORT extern const base::Feature kLazyFrameLoading;
 CONTENT_EXPORT extern const base::Feature kLazyInitializeMediaControls;
 CONTENT_EXPORT extern const base::Feature kLazyParseCSS;
 CONTENT_EXPORT extern const base::Feature kLowPriorityIframes;
@@ -88,6 +89,7 @@
 CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
 CONTENT_EXPORT extern const base::Feature kSignInProcessIsolation;
 CONTENT_EXPORT extern const base::Feature kSlimmingPaintV175;
+CONTENT_EXPORT extern const base::Feature kSpareRendererForSitePerProcess;
 CONTENT_EXPORT extern const base::Feature kStopInBackground;
 CONTENT_EXPORT extern const base::Feature kStopLoadingInBackground;
 CONTENT_EXPORT extern const base::Feature kStopNonTimersInBackground;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index e529e9a..97e443b 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -707,7 +707,8 @@
 
 // Enables or disables pull-to-refresh gesture in response to vertical
 // overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Set the value to '0' to disable the feature, set to '1' to enable it for both
+// touchpad and touchscreen, and set to '2' to enable it only for touchscreen.
 // Defaults to disabled.
 const char kPullToRefresh[] = "pull-to-refresh";
 
diff --git a/content/public/common/zygote_features.gni b/content/public/common/zygote_features.gni
index bab19f1..c7580b3 100644
--- a/content/public/common/zygote_features.gni
+++ b/content/public/common/zygote_features.gni
@@ -2,4 +2,4 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-use_zygote_handle = is_posix && !is_android && !is_mac && !is_fuchsia
+use_zygote_handle = is_posix && !is_android && !is_mac
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index dee7068d..a68f00ae 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -147,6 +147,13 @@
       std::string* error_html,
       base::string16* error_description) {}
 
+  // Returns as |error_description| a brief description of the error that
+  // ocurred. The out parameter may be not written to in certain cases (lack of
+  // information on the error code)
+  virtual void GetErrorDescription(const blink::WebURLRequest& failed_request,
+                                   const blink::WebURLError& error,
+                                   base::string16* error_description) {}
+
   // Allows the embedder to control when media resources are loaded. Embedders
   // can run |closure| immediately if they don't wish to defer media resource
   // loading.  If |has_played_media_before| is true, the render frame has
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index fb58f3b..1f538152 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -352,6 +352,16 @@
 
 void MockRenderProcessHost::DisableKeepAliveRefCount() {
   keep_alive_ref_count_ = 0;
+
+  // RenderProcessHost::DisableKeepAliveRefCount() virtual method gets called as
+  // part of BrowserContext::NotifyWillBeDestroyed(...).  Normally
+  // MockRenderProcessHost::DisableKeepAliveRefCount doesn't call Cleanup,
+  // because the MockRenderProcessHost might be owned by a test.  However, when
+  // the MockRenderProcessHost is the spare RenderProcessHost, we know that it
+  // is owned by the SpareRenderProcessHostManager and we need to delete the
+  // spare to avoid reports/DCHECKs about memory leaks.
+  if (this == RenderProcessHostImpl::GetSpareRenderProcessHostForTesting())
+    Cleanup();
 }
 
 bool MockRenderProcessHost::IsKeepAliveRefCountDisabled() {
@@ -503,4 +513,12 @@
   return base::JoinString(result, " ");
 }
 
+ScopedMockRenderProcessHostFactory::ScopedMockRenderProcessHostFactory() {
+  RenderProcessHostImpl::set_render_process_host_factory(this);
+}
+
+ScopedMockRenderProcessHostFactory::~ScopedMockRenderProcessHostFactory() {
+  RenderProcessHostImpl::set_render_process_host_factory(nullptr);
+}
+
 }  // namespace content
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 295c995..45d2377 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -251,6 +251,17 @@
   DISALLOW_COPY_AND_ASSIGN(MockRenderProcessHostFactory);
 };
 
+// Like MockRenderProcessHostFactory, but automatically registers itself as the
+// default factory via RenderProcessHostImpl::set_render_process_host_factory.
+class ScopedMockRenderProcessHostFactory : public MockRenderProcessHostFactory {
+ public:
+  ScopedMockRenderProcessHostFactory();
+  ~ScopedMockRenderProcessHostFactory() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedMockRenderProcessHostFactory);
+};
+
 // Convenient method to retrieve |InputMsg_HandleInputEvent|s from process sink
 // and returns a string of WebInputEvent types. Will append a trailing '*' if
 // other types of messages were found.
diff --git a/content/public/test/scoped_overscroll_mode.cc b/content/public/test/scoped_overscroll_mode.cc
deleted file mode 100644
index 7f5599d..0000000
--- a/content/public/test/scoped_overscroll_mode.cc
+++ /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.
-
-#include "content/public/test/scoped_overscroll_mode.h"
-
-namespace content {
-
-ScopedOverscrollMode::ScopedOverscrollMode(OverscrollConfig::Mode mode) {
-  OverscrollConfig::SetMode(mode);
-}
-
-ScopedOverscrollMode::~ScopedOverscrollMode() {
-  OverscrollConfig::ResetMode();
-}
-
-}  // namespace content
diff --git a/content/public/test/scoped_overscroll_mode.h b/content/public/test/scoped_overscroll_mode.h
deleted file mode 100644
index eafec06..0000000
--- a/content/public/test/scoped_overscroll_mode.h
+++ /dev/null
@@ -1,26 +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 CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODE_H_
-#define CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODE_H_
-
-#include "base/macros.h"
-#include "content/public/browser/overscroll_configuration.h"
-
-namespace content {
-
-// Helper class to set the overscroll configuration mode mode temporarily in
-// tests.
-class ScopedOverscrollMode {
- public:
-  explicit ScopedOverscrollMode(OverscrollConfig::Mode mode);
-  ~ScopedOverscrollMode();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedOverscrollMode);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODE_H_
diff --git a/content/public/test/scoped_overscroll_modes.cc b/content/public/test/scoped_overscroll_modes.cc
new file mode 100644
index 0000000..ae69fe8
--- /dev/null
+++ b/content/public/test/scoped_overscroll_modes.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/test/scoped_overscroll_modes.h"
+
+namespace content {
+
+ScopedHistoryNavigationMode::ScopedHistoryNavigationMode(
+    OverscrollConfig::HistoryNavigationMode mode) {
+  OverscrollConfig::SetHistoryNavigationMode(mode);
+}
+
+ScopedHistoryNavigationMode::~ScopedHistoryNavigationMode() {
+  OverscrollConfig::ResetHistoryNavigationMode();
+}
+
+ScopedPullToRefreshMode::ScopedPullToRefreshMode(
+    OverscrollConfig::PullToRefreshMode mode) {
+  OverscrollConfig::SetPullToRefreshMode(mode);
+}
+
+ScopedPullToRefreshMode::~ScopedPullToRefreshMode() {
+  OverscrollConfig::ResetPullToRefreshMode();
+}
+
+}  // namespace content
diff --git a/content/public/test/scoped_overscroll_modes.h b/content/public/test/scoped_overscroll_modes.h
new file mode 100644
index 0000000..d0e4021
--- /dev/null
+++ b/content/public/test/scoped_overscroll_modes.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODES_H_
+#define CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODES_H_
+
+#include "base/macros.h"
+#include "content/public/browser/overscroll_configuration.h"
+
+namespace content {
+
+// Helper class to set the overscroll history navigation mode temporarily in
+// tests.
+class ScopedHistoryNavigationMode {
+ public:
+  explicit ScopedHistoryNavigationMode(
+      OverscrollConfig::HistoryNavigationMode mode);
+  ~ScopedHistoryNavigationMode();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedHistoryNavigationMode);
+};
+
+// Helper class to set the pull-to-refresh mode temporarily in tests.
+class ScopedPullToRefreshMode {
+ public:
+  explicit ScopedPullToRefreshMode(OverscrollConfig::PullToRefreshMode mode);
+  ~ScopedPullToRefreshMode();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedPullToRefreshMode);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_TEST_SCOPED_OVERSCROLL_MODES_H_
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
index 5b94697..aba19e2 100644
--- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -260,8 +260,6 @@
 
   switch (blink_config.sdp_semantics) {
     case blink::WebRTCSdpSemantics::kDefault:
-      webrtc_config->sdp_semantics = webrtc::SdpSemantics::kDefault;
-      break;
     case blink::WebRTCSdpSemantics::kPlanB:
       webrtc_config->sdp_semantics = webrtc::SdpSemantics::kPlanB;
       break;
@@ -748,12 +746,6 @@
             static_cast<webrtc::KeyExchangeProtocolType>(counter),
             webrtc::kEnumCounterKeyProtocolMax);
         break;
-      case webrtc::kEnumCounterSdpSemanticRequested:
-        UMA_HISTOGRAM_ENUMERATION(
-            "WebRTC.PeerConnection.SdpSemanticRequested",
-            static_cast<webrtc::SdpSemanticRequested>(counter),
-            webrtc::kSdpSemanticRequestMax);
-        break;
       case webrtc::kEnumCounterSdpSemanticNegotiated:
         UMA_HISTOGRAM_ENUMERATION(
             "WebRTC.PeerConnection.SdpSemanticNegotiated",
@@ -930,6 +922,27 @@
   return usage_count;
 }
 
+enum SdpSemanticRequested {
+  kSdpSemanticRequestedDefault,
+  kSdpSemanticRequestedPlanB,
+  kSdpSemanticRequestedUnifiedPlan,
+  kSdpSemanticRequestedMax
+};
+
+SdpSemanticRequested GetSdpSemanticRequested(
+    blink::WebRTCSdpSemantics sdp_semantics) {
+  switch (sdp_semantics) {
+    case blink::WebRTCSdpSemantics::kDefault:
+      return kSdpSemanticRequestedDefault;
+    case blink::WebRTCSdpSemantics::kPlanB:
+      return kSdpSemanticRequestedPlanB;
+    case blink::WebRTCSdpSemantics::kUnifiedPlan:
+      return kSdpSemanticRequestedUnifiedPlan;
+  }
+  NOTREACHED();
+  return kSdpSemanticRequestedDefault;
+}
+
 }  // namespace
 
 // Implementation of LocalRTCStatsRequest.
@@ -1354,6 +1367,12 @@
 
   uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
   native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "WebRTC.PeerConnection.SdpSemanticRequested",
+      GetSdpSemanticRequested(server_configuration.sdp_semantics),
+      kSdpSemanticRequestedMax);
+
   return true;
 }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5717872..fede37b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4540,8 +4540,8 @@
 
   const WebURLRequest& failed_request = document_loader->GetRequest();
   base::string16 error_description;
-  GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, error,
-                                                   nullptr, &error_description);
+  GetContentClient()->renderer()->GetErrorDescription(failed_request, error,
+                                                      &error_description);
   Send(new FrameHostMsg_DidFailLoadWithError(
       routing_id_, failed_request.Url(), error.reason(), error_description));
 }
@@ -7057,8 +7057,8 @@
 
   FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
   params.error_code = error.reason();
-  GetContentClient()->renderer()->PrepareErrorPage(
-      this, request, error, nullptr, &params.error_description);
+  GetContentClient()->renderer()->GetErrorDescription(
+      request, error, &params.error_description);
   params.url = error.url(),
   params.showing_repost_interstitial = show_repost_interstitial;
   Send(new FrameHostMsg_DidFailProvisionalLoadWithError(routing_id_, params));
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index efcc982..1883645 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -109,8 +109,8 @@
     "../public/test/ppapi_test_utils.h",
     "../public/test/render_view_test.cc",
     "../public/test/render_view_test.h",
-    "../public/test/scoped_overscroll_mode.cc",
-    "../public/test/scoped_overscroll_mode.h",
+    "../public/test/scoped_overscroll_modes.cc",
+    "../public/test/scoped_overscroll_modes.h",
     "../public/test/service_worker_test_helpers.cc",
     "../public/test/service_worker_test_helpers.h",
     "../public/test/simple_url_loader_test_helper.cc",
@@ -1772,7 +1772,7 @@
     "//third_party/mesa:osmesa",
   ]
 
-  if (is_posix && !is_fuchsia) {
+  if (is_posix) {
     sources += [ "../browser/posix_file_descriptor_info_impl_unittest.cc" ]
   }
 
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 3df5314..7ae4ce5 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -425,6 +425,12 @@
     self.Fail('deqp/functional/gles3/integerstatequery.html',
         ['passthrough', 'opengl'], bug=602688)
 
+    # These Transform Feedback tests seem flaky on ANGLE/GL.
+    self.Flaky('conformance2/transform_feedback/switching-objects.html',
+        ['passthrough', 'opengl'], bug=696345)
+    self.Flaky('conformance2/transform_feedback/too-small-buffers.html',
+        ['passthrough', 'opengl'], bug=818383)
+
     # Passthrough command decoder / OpenGL / Intel
     self.Fail('conformance2/textures/video/tex-2d-rgb32f-rgb-float.html',
         ['passthrough', 'opengl', 'intel'], bug=602688)
@@ -751,7 +757,7 @@
         'random_separate_triangles.html',
         ['mac', 'amd'], bug=483282)
     self.Fail('conformance2/transform_feedback/too-small-buffers.html',
-        ['mac', 'amd', 'sierra'], bug=818383)
+        ['mac', 'amd', 'sierra', 'no_angle'], bug=818383)
 
     self.Flaky('deqp/functional/gles3/shaderindexing/mat_00.html',
         ['mac', 'amd'], bug=751254)
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
index 74f1331..12447a0d 100644
--- a/content/zygote/zygote_main_linux.cc
+++ b/content/zygote/zygote_main_linux.cc
@@ -23,7 +23,6 @@
 #include "base/compiler_specific.h"
 #include "base/memory/protected_memory.h"
 #include "base/memory/protected_memory_cfi.h"
-#include "base/native_library.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket.h"
 #include "base/rand_util.h"
@@ -31,15 +30,12 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info.h"
 #include "build/build_config.h"
-#include "content/common/font_config_ipc_linux.h"
 #include "content/common/zygote_commands_linux.h"
 #include "content/public/common/common_sandbox_support_linux.h"
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/zygote_fork_delegate_linux.h"
 #include "content/zygote/zygote_linux.h"
-#include "media/media_buildflags.h"
-#include "ppapi/buildflags/buildflags.h"
 #include "sandbox/linux/services/credentials.h"
 #include "sandbox/linux/services/init_process_reaper.h"
 #include "sandbox/linux/services/libc_interceptor.h"
@@ -49,27 +45,7 @@
 #include "services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h"
 #include "services/service_manager/sandbox/linux/sandbox_linux.h"
 #include "services/service_manager/sandbox/sandbox.h"
-#include "third_party/blink/public/platform/web_font_render_style.h"
-#include "third_party/boringssl/src/include/openssl/crypto.h"
-#include "third_party/boringssl/src/include/openssl/rand.h"
 #include "third_party/icu/source/i18n/unicode/timezone.h"
-#include "third_party/skia/include/ports/SkFontConfigInterface.h"
-#include "third_party/skia/include/ports/SkFontMgr.h"
-#include "third_party/skia/include/ports/SkFontMgr_android.h"
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-#include "content/common/pepper_plugin_list.h"
-#include "content/public/common/pepper_plugin_info.h"
-#endif
-
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-#include "content/public/common/cdm_info.h"
-#include "content/public/common/content_client.h"
-#endif
-
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "third_party/webrtc_overrides/init_webrtc.h"  // nogncheck
-#endif
 
 namespace content {
 
@@ -95,44 +71,6 @@
 
 }  // namespace
 
-#if BUILDFLAG(ENABLE_PLUGINS)
-// Loads the (native) libraries but does not initialize them (i.e., does not
-// call PPP_InitializeModule). This is needed by the zygote on Linux to get
-// access to the plugins before entering the sandbox.
-void PreloadPepperPlugins() {
-  std::vector<PepperPluginInfo> plugins;
-  ComputePepperPluginList(&plugins);
-  for (const auto& plugin : plugins) {
-    if (!plugin.is_internal) {
-      base::NativeLibraryLoadError error;
-      base::NativeLibrary library = base::LoadNativeLibrary(plugin.path,
-                                                            &error);
-      VLOG_IF(1, !library) << "Unable to load plugin "
-                           << plugin.path.value() << " "
-                           << error.ToString();
-
-      ignore_result(library);  // Prevent release-mode warning.
-    }
-  }
-}
-#endif
-
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-// Loads registered library CDMs but does not initialize them. This is needed by
-// the zygote on Linux to get access to the CDMs before entering the sandbox.
-void PreloadLibraryCdms() {
-  std::vector<CdmInfo> cdms;
-  GetContentClient()->AddContentDecryptionModules(&cdms, nullptr);
-  for (const auto& cdm : cdms) {
-    base::NativeLibraryLoadError error;
-    base::NativeLibrary library = base::LoadNativeLibrary(cdm.path, &error);
-    VLOG_IF(1, !library) << "Unable to load CDM " << cdm.path.value()
-                         << " (error: " << error.ToString() << ")";
-    ignore_result(library);  // Prevent release-mode warning.
-  }
-}
-#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
 // This function triggers the static and lazy construction of objects that need
 // to be created before imposing the sandbox.
 static void ZygotePreSandboxInit() {
@@ -146,64 +84,6 @@
   // TimeZone::createDefault is called once here, the timezone ID is
   // cached and there's no more need to access the file system.
   std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
-
-#if defined(ARCH_CPU_ARM_FAMILY)
-  // On ARM, BoringSSL requires access to /proc/cpuinfo to determine processor
-  // features. Query this before entering the sandbox.
-  CRYPTO_library_init();
-#endif
-
-  // Pass BoringSSL a copy of the /dev/urandom file descriptor so RAND_bytes
-  // will work inside the sandbox.
-  RAND_set_urandom_fd(base::GetUrandomFD());
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-  // Ensure access to the Pepper plugins before the sandbox is turned on.
-  PreloadPepperPlugins();
-#endif
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-  // Ensure access to the library CDMs before the sandbox is turned on.
-  PreloadLibraryCdms();
-#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-  InitializeWebRtcModule();
-#endif
-
-  SkFontConfigInterface::SetGlobal(new FontConfigIPC(GetSandboxFD()))->unref();
-
-  // Set the android SkFontMgr for blink. We need to ensure this is done
-  // before the sandbox is initialized to allow the font manager to access
-  // font configuration files on disk.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAndroidFontsPath)) {
-    std::string android_fonts_dir =
-        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-            switches::kAndroidFontsPath);
-
-    if (android_fonts_dir.size() > 0 && android_fonts_dir.back() != '/')
-      android_fonts_dir += '/';
-
-    SkFontMgr_Android_CustomFonts custom;
-    custom.fSystemFontUse =
-        SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
-    custom.fBasePath = android_fonts_dir.c_str();
-
-    std::string font_config;
-    std::string fallback_font_config;
-    if (android_fonts_dir.find("kitkat") != std::string::npos) {
-      font_config = android_fonts_dir + "system_fonts.xml";
-      fallback_font_config = android_fonts_dir + "fallback_fonts.xml";
-      custom.fFallbackFontsXml = fallback_font_config.c_str();
-    } else {
-      font_config = android_fonts_dir + "fonts.xml";
-      custom.fFallbackFontsXml = nullptr;
-    }
-    custom.fFontsXml = font_config.c_str();
-    custom.fIsolated = true;
-
-    blink::WebFontRenderStyle::SetSkiaFontManager(
-        SkFontMgr_New_Android(&custom));
-  }
 }
 
 static bool CreateInitProcessReaper(
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index a3602f47..ea09dff 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -64,6 +64,7 @@
     "fido_request_handler_base.h",
     "fido_task.cc",
     "fido_task.h",
+    "fido_transport_protocol.h",
     "get_assertion_request_handler.cc",
     "get_assertion_request_handler.h",
     "get_assertion_task.cc",
@@ -96,7 +97,6 @@
     "u2f_request.h",
     "u2f_sign.cc",
     "u2f_sign.h",
-    "u2f_transport_protocol.h",
     "virtual_fido_device.cc",
     "virtual_fido_device.h",
   ]
diff --git a/device/fido/fake_fido_discovery.cc b/device/fido/fake_fido_discovery.cc
index 78cf132..e7e5335 100644
--- a/device/fido/fake_fido_discovery.cc
+++ b/device/fido/fake_fido_discovery.cc
@@ -18,7 +18,7 @@
 
 // FakeFidoDiscovery ----------------------------------------------------------
 
-FakeFidoDiscovery::FakeFidoDiscovery(U2fTransportProtocol transport,
+FakeFidoDiscovery::FakeFidoDiscovery(FidoTransportProtocol transport,
                                      StartMode mode)
     : FidoDiscovery(transport), mode_(mode) {}
 FakeFidoDiscovery::~FakeFidoDiscovery() = default;
@@ -55,34 +55,34 @@
 FakeFidoDiscovery* ScopedFakeFidoDiscoveryFactory::ForgeNextHidDiscovery(
     FakeFidoDiscovery::StartMode mode) {
   next_hid_discovery_ = std::make_unique<FakeFidoDiscovery>(
-      U2fTransportProtocol::kUsbHumanInterfaceDevice, mode);
+      FidoTransportProtocol::kUsbHumanInterfaceDevice, mode);
   return next_hid_discovery_.get();
 }
 
 FakeFidoDiscovery* ScopedFakeFidoDiscoveryFactory::ForgeNextNfcDiscovery(
     FakeFidoDiscovery::StartMode mode) {
   next_nfc_discovery_ = std::make_unique<FakeFidoDiscovery>(
-      U2fTransportProtocol::kNearFieldCommunication, mode);
+      FidoTransportProtocol::kNearFieldCommunication, mode);
   return next_nfc_discovery_.get();
 }
 
 FakeFidoDiscovery* ScopedFakeFidoDiscoveryFactory::ForgeNextBleDiscovery(
     FakeFidoDiscovery::StartMode mode) {
   next_ble_discovery_ = std::make_unique<FakeFidoDiscovery>(
-      U2fTransportProtocol::kBluetoothLowEnergy, mode);
+      FidoTransportProtocol::kBluetoothLowEnergy, mode);
   return next_ble_discovery_.get();
 }
 
 std::unique_ptr<FidoDiscovery>
 ScopedFakeFidoDiscoveryFactory::CreateFidoDiscovery(
-    U2fTransportProtocol transport,
+    FidoTransportProtocol transport,
     ::service_manager::Connector* connector) {
   switch (transport) {
-    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
+    case FidoTransportProtocol::kUsbHumanInterfaceDevice:
       return std::move(next_hid_discovery_);
-    case U2fTransportProtocol::kNearFieldCommunication:
+    case FidoTransportProtocol::kNearFieldCommunication:
       return std::move(next_nfc_discovery_);
-    case U2fTransportProtocol::kBluetoothLowEnergy:
+    case FidoTransportProtocol::kBluetoothLowEnergy:
       return std::move(next_ble_discovery_);
   }
   NOTREACHED();
diff --git a/device/fido/fake_fido_discovery.h b/device/fido/fake_fido_discovery.h
index e04b309b..de4428e 100644
--- a/device/fido/fake_fido_discovery.h
+++ b/device/fido/fake_fido_discovery.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "device/fido/fido_discovery.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -32,9 +32,9 @@
 //   auto* fake_ble_discovery = factory.ForgeNextBleDiscovery();
 //
 //   // Run the production code that will eventually call:
-//   //// FidoDiscovery::Create(U2fTransportProtocol::kUsbHumanInterfaceDevice)
+//   //// FidoDiscovery::Create(FidoTransportProtocol::kUsbHumanInterfaceDevice)
 //   //// hid_instance->Start();
-//   //// FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy)
+//   //// FidoDiscovery::Create(FidoTransportProtocol::kBluetoothLowEnergy)
 //   //// ble_instance->Start();
 //
 //   // Wait, i.e. spin the message loop until the fake discoveries are started.
@@ -65,7 +65,7 @@
     kAutomatic
   };
 
-  explicit FakeFidoDiscovery(U2fTransportProtocol transport,
+  explicit FakeFidoDiscovery(FidoTransportProtocol transport,
                              StartMode mode = StartMode::kManual);
   ~FakeFidoDiscovery() override;
 
@@ -115,7 +115,7 @@
 
  protected:
   std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
-      U2fTransportProtocol transport,
+      FidoTransportProtocol transport,
       ::service_manager::Connector* connector) override;
 
  private:
diff --git a/device/fido/fake_fido_discovery_unittest.cc b/device/fido/fake_fido_discovery_unittest.cc
index 063bfd4..9858dcb 100644
--- a/device/fido/fake_fido_discovery_unittest.cc
+++ b/device/fido/fake_fido_discovery_unittest.cc
@@ -34,25 +34,25 @@
 using ScopedFakeFidoDiscoveryFactoryTest = FakeFidoDiscoveryTest;
 
 TEST_F(FakeFidoDiscoveryTest, Transport) {
-  FakeFidoDiscovery discovery_ble(U2fTransportProtocol::kBluetoothLowEnergy);
-  EXPECT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
+  FakeFidoDiscovery discovery_ble(FidoTransportProtocol::kBluetoothLowEnergy);
+  EXPECT_EQ(FidoTransportProtocol::kBluetoothLowEnergy,
             discovery_ble.transport());
 
   FakeFidoDiscovery discovery_hid(
-      U2fTransportProtocol::kUsbHumanInterfaceDevice);
-  EXPECT_EQ(U2fTransportProtocol::kUsbHumanInterfaceDevice,
+      FidoTransportProtocol::kUsbHumanInterfaceDevice);
+  EXPECT_EQ(FidoTransportProtocol::kUsbHumanInterfaceDevice,
             discovery_hid.transport());
 }
 
 TEST_F(FakeFidoDiscoveryTest, InitialState) {
-  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  FakeFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
 
   ASSERT_FALSE(discovery.is_running());
   ASSERT_FALSE(discovery.is_start_requested());
 }
 
 TEST_F(FakeFidoDiscoveryTest, StartDiscovery) {
-  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  FakeFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
 
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
@@ -69,7 +69,7 @@
 }
 
 TEST_F(FakeFidoDiscoveryTest, WaitThenStartStopDiscovery) {
-  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  FakeFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
 
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
@@ -90,7 +90,7 @@
 
 // Starting discovery and failing: instance stays in "not running" state
 TEST_F(FakeFidoDiscoveryTest, StartFail) {
-  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  FakeFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
 
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
@@ -108,7 +108,7 @@
 
 // Adding device is possible both before and after discovery actually starts.
 TEST_F(FakeFidoDiscoveryTest, AddDevice) {
-  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  FakeFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
 
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
@@ -137,10 +137,10 @@
        OverridesUsbFactoryFunctionWhileInScope) {
   ScopedFakeFidoDiscoveryFactory factory;
   auto* injected_fake_discovery = factory.ForgeNextHidDiscovery();
-  ASSERT_EQ(U2fTransportProtocol::kUsbHumanInterfaceDevice,
+  ASSERT_EQ(FidoTransportProtocol::kUsbHumanInterfaceDevice,
             injected_fake_discovery->transport());
   auto produced_discovery = FidoDiscovery::Create(
-      U2fTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
+      FidoTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
   EXPECT_TRUE(produced_discovery);
   EXPECT_EQ(injected_fake_discovery, produced_discovery.get());
 }
@@ -151,17 +151,17 @@
   ScopedFakeFidoDiscoveryFactory factory;
 
   auto* injected_fake_discovery_1 = factory.ForgeNextBleDiscovery();
-  ASSERT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
+  ASSERT_EQ(FidoTransportProtocol::kBluetoothLowEnergy,
             injected_fake_discovery_1->transport());
-  auto produced_discovery_1 =
-      FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
+  auto produced_discovery_1 = FidoDiscovery::Create(
+      FidoTransportProtocol::kBluetoothLowEnergy, nullptr);
   EXPECT_EQ(injected_fake_discovery_1, produced_discovery_1.get());
 
   auto* injected_fake_discovery_2 = factory.ForgeNextBleDiscovery();
-  ASSERT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
+  ASSERT_EQ(FidoTransportProtocol::kBluetoothLowEnergy,
             injected_fake_discovery_2->transport());
-  auto produced_discovery_2 =
-      FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
+  auto produced_discovery_2 = FidoDiscovery::Create(
+      FidoTransportProtocol::kBluetoothLowEnergy, nullptr);
   EXPECT_EQ(injected_fake_discovery_2, produced_discovery_2.get());
 }
 
diff --git a/device/fido/fido_ble_discovery.cc b/device/fido/fido_ble_discovery.cc
index b1ec9e76..ef8b2c5 100644
--- a/device/fido/fido_ble_discovery.cc
+++ b/device/fido/fido_ble_discovery.cc
@@ -24,7 +24,7 @@
 namespace device {
 
 FidoBleDiscovery::FidoBleDiscovery()
-    : FidoDiscovery(U2fTransportProtocol::kBluetoothLowEnergy),
+    : FidoDiscovery(FidoTransportProtocol::kBluetoothLowEnergy),
       weak_factory_(this) {}
 FidoBleDiscovery::~FidoBleDiscovery() {
   if (adapter_)
diff --git a/device/fido/fido_discovery.cc b/device/fido/fido_discovery.cc
index 48bcad0f..8e941b65 100644
--- a/device/fido/fido_discovery.cc
+++ b/device/fido/fido_discovery.cc
@@ -20,10 +20,10 @@
 namespace {
 
 std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl(
-    U2fTransportProtocol transport,
+    FidoTransportProtocol transport,
     service_manager::Connector* connector) {
   switch (transport) {
-    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
+    case FidoTransportProtocol::kUsbHumanInterfaceDevice:
 #if !defined(OS_ANDROID)
       DCHECK(connector);
       return std::make_unique<FidoHidDiscovery>(connector);
@@ -31,9 +31,9 @@
       NOTREACHED() << "USB HID not supported on Android.";
       return nullptr;
 #endif  // !defined(OS_ANDROID)
-    case U2fTransportProtocol::kBluetoothLowEnergy:
+    case FidoTransportProtocol::kBluetoothLowEnergy:
       return std::make_unique<FidoBleDiscovery>();
-    case U2fTransportProtocol::kNearFieldCommunication:
+    case FidoTransportProtocol::kNearFieldCommunication:
       // TODO(https://crbug.com/825949): Add NFC support.
       return nullptr;
   }
@@ -51,12 +51,12 @@
 
 // static
 std::unique_ptr<FidoDiscovery> FidoDiscovery::Create(
-    U2fTransportProtocol transport,
+    FidoTransportProtocol transport,
     service_manager::Connector* connector) {
   return (*g_factory_func_)(transport, connector);
 }
 
-FidoDiscovery::FidoDiscovery(U2fTransportProtocol transport)
+FidoDiscovery::FidoDiscovery(FidoTransportProtocol transport)
     : transport_(transport) {}
 
 FidoDiscovery::~FidoDiscovery() = default;
@@ -157,7 +157,7 @@
 // static
 std::unique_ptr<FidoDiscovery>
 ScopedFidoDiscoveryFactory::ForwardCreateFidoDiscoveryToCurrentFactory(
-    U2fTransportProtocol transport,
+    FidoTransportProtocol transport,
     ::service_manager::Connector* connector) {
   DCHECK(g_current_factory);
   return g_current_factory->CreateFidoDiscovery(transport, connector);
diff --git a/device/fido/fido_discovery.h b/device/fido/fido_discovery.h
index 90d94b4d..a3c31b5 100644
--- a/device/fido/fido_discovery.h
+++ b/device/fido/fido_discovery.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -57,10 +57,10 @@
   // Factory function to construct an instance that discovers authenticators on
   // the given |transport| protocol.
   //
-  // U2fTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid
+  // FidoTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid
   // |connector| on Desktop, and is not valid on Android.
   static std::unique_ptr<FidoDiscovery> Create(
-      U2fTransportProtocol transport,
+      FidoTransportProtocol transport,
       ::service_manager::Connector* connector);
 
   virtual ~FidoDiscovery();
@@ -71,7 +71,7 @@
     observer_ = observer;
   }
 
-  U2fTransportProtocol transport() const { return transport_; }
+  FidoTransportProtocol transport() const { return transport_; }
   bool is_start_requested() const { return state_ != State::kIdle; }
   bool is_running() const { return state_ == State::kRunning; }
 
@@ -84,7 +84,7 @@
   const FidoDevice* GetDevice(base::StringPiece device_id) const;
 
  protected:
-  FidoDiscovery(U2fTransportProtocol transport);
+  FidoDiscovery(FidoTransportProtocol transport);
 
   void NotifyDiscoveryStarted(bool success);
   void NotifyDeviceAdded(FidoDevice* device);
@@ -110,7 +110,7 @@
   using FactoryFuncPtr = decltype(&Create);
   static FactoryFuncPtr g_factory_func_;
 
-  const U2fTransportProtocol transport_;
+  const FidoTransportProtocol transport_;
   State state_ = State::kIdle;
 
   DISALLOW_COPY_AND_ASSIGN(FidoDiscovery);
@@ -132,13 +132,13 @@
 
  protected:
   virtual std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
-      U2fTransportProtocol transport,
+      FidoTransportProtocol transport,
       ::service_manager::Connector* connector) = 0;
 
  private:
   static std::unique_ptr<FidoDiscovery>
   ForwardCreateFidoDiscoveryToCurrentFactory(
-      U2fTransportProtocol transport,
+      FidoTransportProtocol transport,
       ::service_manager::Connector* connector);
 
   static ScopedFidoDiscoveryFactory* g_current_factory;
diff --git a/device/fido/fido_discovery_unittest.cc b/device/fido/fido_discovery_unittest.cc
index d438853..51b873e 100644
--- a/device/fido/fido_discovery_unittest.cc
+++ b/device/fido/fido_discovery_unittest.cc
@@ -23,7 +23,7 @@
 // A minimal implementation of FidoDiscovery that is no longer abstract.
 class ConcreteFidoDiscovery : public FidoDiscovery {
  public:
-  explicit ConcreteFidoDiscovery(U2fTransportProtocol transport)
+  explicit ConcreteFidoDiscovery(FidoTransportProtocol transport)
       : FidoDiscovery(transport) {}
   ~ConcreteFidoDiscovery() override = default;
 
@@ -43,7 +43,7 @@
 }  // namespace
 
 TEST(FidoDiscoveryTest, TestAddAndRemoveObserver) {
-  ConcreteFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
   MockFidoDiscoveryObserver observer;
   EXPECT_EQ(nullptr, discovery.observer());
 
@@ -55,7 +55,7 @@
 }
 
 TEST(FidoDiscoveryTest, TestNotificationsOnSuccessfulStart) {
-  ConcreteFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
 
@@ -76,7 +76,7 @@
 }
 
 TEST(FidoDiscoveryTest, TestNotificationsOnFailedStart) {
-  ConcreteFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
 
@@ -90,7 +90,7 @@
 }
 
 TEST(FidoDiscoveryTest, TestAddRemoveDevices) {
-  ConcreteFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+  ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
   MockFidoDiscoveryObserver observer;
   discovery.set_observer(&observer);
   discovery.Start();
diff --git a/device/fido/fido_hid_discovery.cc b/device/fido/fido_hid_discovery.cc
index dd80d7e..483b4b35 100644
--- a/device/fido/fido_hid_discovery.cc
+++ b/device/fido/fido_hid_discovery.cc
@@ -14,7 +14,7 @@
 namespace device {
 
 FidoHidDiscovery::FidoHidDiscovery(::service_manager::Connector* connector)
-    : FidoDiscovery(U2fTransportProtocol::kUsbHumanInterfaceDevice),
+    : FidoDiscovery(FidoTransportProtocol::kUsbHumanInterfaceDevice),
       connector_(connector),
       binding_(this),
       weak_factory_(this) {
diff --git a/device/fido/fido_request_handler.h b/device/fido/fido_request_handler.h
index 14848d1..3b46f90 100644
--- a/device/fido/fido_request_handler.h
+++ b/device/fido/fido_request_handler.h
@@ -15,7 +15,7 @@
 #include "base/optional.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_device.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace device {
 
@@ -29,7 +29,7 @@
                               base::Optional<Response> response_data)>;
 
   FidoRequestHandler(service_manager::Connector* connector,
-                     const base::flat_set<U2fTransportProtocol>& transports,
+                     const base::flat_set<FidoTransportProtocol>& transports,
                      CompletionCallback completion_callback)
       : FidoRequestHandlerBase(connector, transports),
         completion_callback_(std::move(completion_callback)) {}
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc
index 3bc4418c..156f61c 100644
--- a/device/fido/fido_request_handler_base.cc
+++ b/device/fido/fido_request_handler_base.cc
@@ -15,7 +15,7 @@
 
 FidoRequestHandlerBase::FidoRequestHandlerBase(
     service_manager::Connector* connector,
-    const base::flat_set<U2fTransportProtocol>& transports) {
+    const base::flat_set<FidoTransportProtocol>& transports) {
   for (const auto transport : transports) {
     auto discovery = FidoDiscovery::Create(transport, connector);
     if (discovery == nullptr) {
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h
index b0014d38d..8c010f01 100644
--- a/device/fido/fido_request_handler_base.h
+++ b/device/fido/fido_request_handler_base.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/strings/string_piece_forward.h"
 #include "device/fido/fido_discovery.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -39,7 +39,7 @@
 
   FidoRequestHandlerBase(
       service_manager::Connector* connector,
-      const base::flat_set<U2fTransportProtocol>& transports);
+      const base::flat_set<FidoTransportProtocol>& transports);
   ~FidoRequestHandlerBase() override;
 
   // Triggers cancellation of all per-device FidoTasks, except for the device
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc
index df2be6e..f96a7bf 100644
--- a/device/fido/fido_request_handler_unittest.cc
+++ b/device/fido/fido_request_handler_unittest.cc
@@ -14,9 +14,9 @@
 #include "device/fido/fido_request_handler.h"
 #include "device/fido/fido_task.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
-#include "device/fido/u2f_transport_protocol.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -85,7 +85,7 @@
 
 class FakeFidoRequestHandler : public FidoRequestHandler<std::vector<uint8_t>> {
  public:
-  FakeFidoRequestHandler(const base::flat_set<U2fTransportProtocol>& protocols,
+  FakeFidoRequestHandler(const base::flat_set<FidoTransportProtocol>& protocols,
                          FakeHandlerCallback callback)
       : FidoRequestHandler(nullptr /* connector */,
                            protocols,
@@ -129,8 +129,8 @@
   std::unique_ptr<FakeFidoRequestHandler> CreateFakeHandler() {
     ForgeNextHidDiscovery();
     return std::make_unique<FakeFidoRequestHandler>(
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
         cb_.callback());
   }
 
diff --git a/device/fido/fido_transport_protocol.h b/device/fido/fido_transport_protocol.h
new file mode 100644
index 0000000..87bae57
--- /dev/null
+++ b/device/fido/fido_transport_protocol.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_FIDO_FIDO_TRANSPORT_PROTOCOL_H_
+#define DEVICE_FIDO_FIDO_TRANSPORT_PROTOCOL_H_
+
+namespace device {
+
+// This enum represents the transport protocols over which Fido WebAuthN API is
+// currently supported.
+enum class FidoTransportProtocol {
+  kUsbHumanInterfaceDevice,
+  kNearFieldCommunication,
+  kBluetoothLowEnergy,
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_FIDO_TRANSPORT_PROTOCOL_H_
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index 6487c8c..5cb7882 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -11,6 +11,7 @@
 #include "device/fido/fake_fido_discovery.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/get_assertion_request_handler.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
@@ -49,8 +50,8 @@
 
     return std::make_unique<GetAssertionRequestHandler>(
         nullptr /* connector */,
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
         std::move(request_param), get_assertion_cb_.callback());
   }
 
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index 5ff70cf2..119a417b 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -15,7 +15,7 @@
 
 GetAssertionRequestHandler::GetAssertionRequestHandler(
     service_manager::Connector* connector,
-    const base::flat_set<U2fTransportProtocol>& protocols,
+    const base::flat_set<FidoTransportProtocol>& protocols,
     CtapGetAssertionRequest request,
     SignResponseCallback completion_callback)
     : FidoRequestHandler(connector, protocols, std::move(completion_callback)),
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h
index 5a541fa..191a6ad 100644
--- a/device/fido/get_assertion_request_handler.h
+++ b/device/fido/get_assertion_request_handler.h
@@ -14,6 +14,7 @@
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_request_handler.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -34,7 +35,7 @@
  public:
   GetAssertionRequestHandler(
       service_manager::Connector* connector,
-      const base::flat_set<U2fTransportProtocol>& protocols,
+      const base::flat_set<FidoTransportProtocol>& protocols,
       CtapGetAssertionRequest request_parameter,
       SignResponseCallback completion_callback);
   ~GetAssertionRequestHandler() override;
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc
index 1105442..c94061f 100644
--- a/device/fido/make_credential_handler_unittest.cc
+++ b/device/fido/make_credential_handler_unittest.cc
@@ -13,11 +13,11 @@
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_device.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/make_credential_request_handler.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
-#include "device/fido/u2f_transport_protocol.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -56,8 +56,8 @@
 
     return std::make_unique<MakeCredentialRequestHandler>(
         nullptr,
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
         std::move(request_parameter), AuthenticatorSelectionCriteria(),
         cb_.callback());
   }
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc
index 125e6f9..fe72f26a 100644
--- a/device/fido/make_credential_request_handler.cc
+++ b/device/fido/make_credential_request_handler.cc
@@ -16,7 +16,7 @@
 
 MakeCredentialRequestHandler::MakeCredentialRequestHandler(
     service_manager::Connector* connector,
-    const base::flat_set<U2fTransportProtocol>& protocols,
+    const base::flat_set<FidoTransportProtocol>& protocols,
     CtapMakeCredentialRequest request_parameter,
     AuthenticatorSelectionCriteria authenticator_selection_criteria,
     RegisterResponseCallback completion_callback)
diff --git a/device/fido/make_credential_request_handler.h b/device/fido/make_credential_request_handler.h
index 71f361d4..f0ac0d6e 100644
--- a/device/fido/make_credential_request_handler.h
+++ b/device/fido/make_credential_request_handler.h
@@ -16,6 +16,7 @@
 #include "device/fido/ctap_make_credential_request.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_request_handler.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -36,7 +37,7 @@
  public:
   MakeCredentialRequestHandler(
       service_manager::Connector* connector,
-      const base::flat_set<U2fTransportProtocol>& protocols,
+      const base::flat_set<FidoTransportProtocol>& protocols,
       CtapMakeCredentialRequest request_parameter,
       AuthenticatorSelectionCriteria authenticator_criteria,
       RegisterResponseCallback completion_callback);
diff --git a/device/fido/scoped_virtual_fido_device.cc b/device/fido/scoped_virtual_fido_device.cc
index da7cc033..db7fc51 100644
--- a/device/fido/scoped_virtual_fido_device.cc
+++ b/device/fido/scoped_virtual_fido_device.cc
@@ -20,7 +20,7 @@
  public:
   explicit VirtualFidoDeviceDiscovery(
       scoped_refptr<VirtualFidoDevice::State> state)
-      : FidoDiscovery(U2fTransportProtocol::kUsbHumanInterfaceDevice),
+      : FidoDiscovery(FidoTransportProtocol::kUsbHumanInterfaceDevice),
         state_(std::move(state)) {}
   ~VirtualFidoDeviceDiscovery() override = default;
 
@@ -48,9 +48,9 @@
 }
 
 std::unique_ptr<FidoDiscovery> ScopedVirtualFidoDevice::CreateFidoDiscovery(
-    U2fTransportProtocol transport,
+    FidoTransportProtocol transport,
     ::service_manager::Connector* connector) {
-  if (transport != U2fTransportProtocol::kUsbHumanInterfaceDevice) {
+  if (transport != FidoTransportProtocol::kUsbHumanInterfaceDevice) {
     return nullptr;
   }
   return std::make_unique<VirtualFidoDeviceDiscovery>(state_);
diff --git a/device/fido/scoped_virtual_fido_device.h b/device/fido/scoped_virtual_fido_device.h
index 92fe760..a9c8d8583 100644
--- a/device/fido/scoped_virtual_fido_device.h
+++ b/device/fido/scoped_virtual_fido_device.h
@@ -27,7 +27,7 @@
 
  protected:
   std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
-      U2fTransportProtocol transport,
+      FidoTransportProtocol transport,
       ::service_manager::Connector* connector) override;
 
  private:
diff --git a/device/fido/u2f_register.cc b/device/fido/u2f_register.cc
index 4ee6851..4f6557c 100644
--- a/device/fido/u2f_register.cc
+++ b/device/fido/u2f_register.cc
@@ -17,7 +17,7 @@
 // static
 std::unique_ptr<U2fRequest> U2fRegister::TryRegistration(
     service_manager::Connector* connector,
-    const base::flat_set<U2fTransportProtocol>& transports,
+    const base::flat_set<FidoTransportProtocol>& transports,
     std::vector<std::vector<uint8_t>> registered_keys,
     std::vector<uint8_t> challenge_digest,
     std::vector<uint8_t> application_parameter,
@@ -31,13 +31,14 @@
   return request;
 }
 
-U2fRegister::U2fRegister(service_manager::Connector* connector,
-                         const base::flat_set<U2fTransportProtocol>& transports,
-                         std::vector<std::vector<uint8_t>> registered_keys,
-                         std::vector<uint8_t> challenge_digest,
-                         std::vector<uint8_t> application_parameter,
-                         bool individual_attestation_ok,
-                         RegisterResponseCallback completion_callback)
+U2fRegister::U2fRegister(
+    service_manager::Connector* connector,
+    const base::flat_set<FidoTransportProtocol>& transports,
+    std::vector<std::vector<uint8_t>> registered_keys,
+    std::vector<uint8_t> challenge_digest,
+    std::vector<uint8_t> application_parameter,
+    bool individual_attestation_ok,
+    RegisterResponseCallback completion_callback)
     : U2fRequest(connector,
                  transports,
                  std::move(application_parameter),
diff --git a/device/fido/u2f_register.h b/device/fido/u2f_register.h
index 0b26efe..139d806 100644
--- a/device/fido/u2f_register.h
+++ b/device/fido/u2f_register.h
@@ -16,8 +16,8 @@
 #include "base/optional.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/u2f_request.h"
-#include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -33,7 +33,7 @@
 
   static std::unique_ptr<U2fRequest> TryRegistration(
       service_manager::Connector* connector,
-      const base::flat_set<U2fTransportProtocol>& transports,
+      const base::flat_set<FidoTransportProtocol>& transports,
       std::vector<std::vector<uint8_t>> registered_keys,
       std::vector<uint8_t> challenge_digest,
       std::vector<uint8_t> application_parameter,
@@ -41,7 +41,7 @@
       RegisterResponseCallback completion_callback);
 
   U2fRegister(service_manager::Connector* connector,
-              const base::flat_set<U2fTransportProtocol>& transports,
+              const base::flat_set<FidoTransportProtocol>& transports,
               std::vector<std::vector<uint8_t>> registered_keys,
               std::vector<uint8_t> challenge_digest,
               std::vector<uint8_t> application_parameter,
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
index 0cbb33b..af6edca 100644
--- a/device/fido/u2f_register_unittest.cc
+++ b/device/fido/u2f_register_unittest.cc
@@ -19,6 +19,7 @@
 #include "device/fido/fido_attestation_statement.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
@@ -181,8 +182,8 @@
     ForgeNextHidDiscovery();
     return std::make_unique<U2fRegister>(
         nullptr /* connector */,
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
         registered_keys,
         u2f_parsing_utils::Materialize(test_data::kChallengeParameter),
         u2f_parsing_utils::Materialize(test_data::kApplicationParameter),
@@ -201,7 +202,7 @@
   std::vector<uint8_t> challenge_parameter_ =
       u2f_parsing_utils::Materialize(test_data::kChallengeParameter);
   std::vector<std::vector<uint8_t>> key_handles_;
-  base::flat_set<U2fTransportProtocol> protocols_;
+  base::flat_set<FidoTransportProtocol> protocols_;
   test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
   test::FakeFidoDiscovery* discovery_;
   TestRegisterCallback register_callback_receiver_;
@@ -761,8 +762,8 @@
     TestRegisterCallback cb;
     auto request = std::make_unique<U2fRegister>(
         nullptr /* connector */,
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}) /* transports */,
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}) /* transports */,
         key_handles_, challenge_parameter_, application_parameter_,
         individual_attestation, cb.callback());
     request->Start();
diff --git a/device/fido/u2f_request.cc b/device/fido/u2f_request.cc
index a5a789e..f5fb0f2 100644
--- a/device/fido/u2f_request.cc
+++ b/device/fido/u2f_request.cc
@@ -19,7 +19,7 @@
 namespace device {
 
 U2fRequest::U2fRequest(service_manager::Connector* connector,
-                       const base::flat_set<U2fTransportProtocol>& transports,
+                       const base::flat_set<FidoTransportProtocol>& transports,
                        std::vector<uint8_t> application_parameter,
                        std::vector<uint8_t> challenge_digest,
                        std::vector<std::vector<uint8_t>> registered_keys)
diff --git a/device/fido/u2f_request.h b/device/fido/u2f_request.h
index fb78303..2ed0157 100644
--- a/device/fido/u2f_request.h
+++ b/device/fido/u2f_request.h
@@ -21,7 +21,7 @@
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_device.h"
 #include "device/fido/fido_discovery.h"
-#include "device/fido/u2f_transport_protocol.h"
+#include "device/fido/fido_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -39,7 +39,7 @@
   // TODO(https://crbug.com/769631): Remove the dependency on Connector once U2F
   // is servicified.
   U2fRequest(service_manager::Connector* connector,
-             const base::flat_set<U2fTransportProtocol>& transports,
+             const base::flat_set<FidoTransportProtocol>& transports,
              std::vector<uint8_t> application_parameter,
              std::vector<uint8_t> challenge_digest,
              std::vector<std::vector<uint8_t>> registered_keys);
diff --git a/device/fido/u2f_request_unittest.cc b/device/fido/u2f_request_unittest.cc
index 1ed38c8..b4b9d930 100644
--- a/device/fido/u2f_request_unittest.cc
+++ b/device/fido/u2f_request_unittest.cc
@@ -9,9 +9,9 @@
 
 #include "base/test/scoped_task_environment.h"
 #include "device/fido/fake_fido_discovery.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
-#include "device/fido/u2f_transport_protocol.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::_;
@@ -23,7 +23,7 @@
 class FakeU2fRequest : public U2fRequest {
  public:
   explicit FakeU2fRequest(
-      const base::flat_set<U2fTransportProtocol>& transports)
+      const base::flat_set<FidoTransportProtocol>& transports)
       : U2fRequest(nullptr /* connector */,
                    transports,
                    std::vector<uint8_t>(),
@@ -65,7 +65,7 @@
 TEST_F(U2fRequestTest, TestIterateDevice) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
 
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   auto device0 = std::make_unique<MockFidoDevice>();
@@ -109,7 +109,7 @@
 TEST_F(U2fRequestTest, TestAbandonCurrentDeviceAndTransition) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
 
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   auto device = std::make_unique<MockFidoDevice>();
@@ -138,7 +138,7 @@
 
 TEST_F(U2fRequestTest, TestBasicMachine) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   ASSERT_NO_FATAL_FAILURE(discovery->WaitForCallToStartAndSimulateSuccess());
@@ -156,7 +156,7 @@
 TEST_F(U2fRequestTest, TestAlreadyPresentDevice) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
 
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   auto device = std::make_unique<MockFidoDevice>();
@@ -173,8 +173,8 @@
 
   // Create a fake request with two different discoveries that both start up
   // successfully.
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice,
-                          U2fTransportProtocol::kBluetoothLowEnergy});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
+                          FidoTransportProtocol::kBluetoothLowEnergy});
   request.Start();
 
   ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStartAndSimulateSuccess());
@@ -226,8 +226,8 @@
 
   // Create a fake request with two different discoveries that start at
   // different times.
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice,
-                          U2fTransportProtocol::kBluetoothLowEnergy});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
+                          FidoTransportProtocol::kBluetoothLowEnergy});
 
   auto fast_device = std::make_unique<MockFidoDevice>();
   auto slow_device = std::make_unique<MockFidoDevice>();
@@ -307,8 +307,8 @@
     auto* discovery_1 = discovery_factory().ForgeNextHidDiscovery();
     auto* discovery_2 = discovery_factory().ForgeNextBleDiscovery();
 
-    FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice,
-                            U2fTransportProtocol::kBluetoothLowEnergy});
+    FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
+                            FidoTransportProtocol::kBluetoothLowEnergy});
     request.Start();
 
     ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStart());
@@ -325,8 +325,8 @@
     auto* discovery_1 = discovery_factory().ForgeNextHidDiscovery();
     auto* discovery_2 = discovery_factory().ForgeNextBleDiscovery();
 
-    FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice,
-                            U2fTransportProtocol::kBluetoothLowEnergy});
+    FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
+                            FidoTransportProtocol::kBluetoothLowEnergy});
     request.Start();
 
     ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStart());
@@ -380,7 +380,7 @@
 // sent to device as a retry.
 TEST_F(U2fRequestTest, TestLegacyVersionRequest) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-  FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
+  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   auto device0 = std::make_unique<MockFidoDevice>();
diff --git a/device/fido/u2f_sign.cc b/device/fido/u2f_sign.cc
index 97e0abb98..e0d6187 100644
--- a/device/fido/u2f_sign.cc
+++ b/device/fido/u2f_sign.cc
@@ -15,7 +15,7 @@
 // static
 std::unique_ptr<U2fRequest> U2fSign::TrySign(
     service_manager::Connector* connector,
-    const base::flat_set<U2fTransportProtocol>& transports,
+    const base::flat_set<FidoTransportProtocol>& transports,
     std::vector<std::vector<uint8_t>> registered_keys,
     std::vector<uint8_t> challenge_digest,
     std::vector<uint8_t> application_parameter,
@@ -31,7 +31,7 @@
 }
 
 U2fSign::U2fSign(service_manager::Connector* connector,
-                 const base::flat_set<U2fTransportProtocol>& transports,
+                 const base::flat_set<FidoTransportProtocol>& transports,
                  std::vector<std::vector<uint8_t>> registered_keys,
                  std::vector<uint8_t> challenge_digest,
                  std::vector<uint8_t> application_parameter,
@@ -44,36 +44,18 @@
                  std::move(registered_keys)),
       alt_application_parameter_(std::move(alt_application_parameter)),
       completion_callback_(std::move(completion_callback)),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  // U2F devices require at least one key handle.
+  // TODO(crbug.com/831712): When CTAP2 authenticators are supported, this check
+  // should be enforced by handlers in fido/device on a per-device basis.
+  DCHECK(registered_keys_.size() > 0);
+}
 
 U2fSign::~U2fSign() = default;
 
 void U2fSign::TryDevice() {
   DCHECK(current_device_);
 
-  // There are two different descriptions of what should happen when
-  // "allowCredentials" is empty.
-  // a) WebAuthN 6.2.3 step 6[1] implies "NotAllowedError". The current
-  // implementation returns this in response to receiving
-  // CONDITIONS_NOT_SATISFIED from TrySign.
-  // b) CTAP step 7.2 step 2[2] says the device should error out with
-  // "CTAP2_ERR_OPTION_NOT_SUPPORTED". This also resolves to "NotAllowedError".
-  // The behavior in both cases is consistent with the current implementation.
-  // When CTAP2 authenticators are supported, this check should be enforced by
-  // handlers in fido/device on a per-device basis.
-
-  // [1] https://w3c.github.io/webauthn/#authenticatorgetassertion
-  // [2]
-  // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html
-  if (registered_keys_.size() == 0) {
-    // Send registration (Fake enroll) if no keys were provided.
-    InitiateDeviceTransaction(
-        U2fRequest::GetBogusRegisterCommand(),
-        base::BindOnce(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(),
-                       registered_keys_.cend(),
-                       ApplicationParameterType::kPrimary));
-    return;
-  }
   // Try signing current device with the first registered key.
   auto it = registered_keys_.cbegin();
   InitiateDeviceTransaction(
@@ -150,6 +132,10 @@
       } else {
         // No provided key was accepted by this device. Send registration
         // (Fake enroll) request to device.
+        // We do this to prevent user confusion. Otherwise, if the device
+        // doesn't blink, the user might think it's broken rather than that
+        // it's not registered. Once the user consents to use the device,
+        // the relying party can inform them that it hasn't been registered.
         InitiateDeviceTransaction(
             U2fRequest::GetBogusRegisterCommand(),
             base::BindOnce(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(),
diff --git a/device/fido/u2f_sign.h b/device/fido/u2f_sign.h
index 5e76a3a..6dccad0 100644
--- a/device/fido/u2f_sign.h
+++ b/device/fido/u2f_sign.h
@@ -15,8 +15,8 @@
 #include "base/optional.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/u2f_request.h"
-#include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
 class Connector;
@@ -32,7 +32,7 @@
 
   static std::unique_ptr<U2fRequest> TrySign(
       service_manager::Connector* connector,
-      const base::flat_set<U2fTransportProtocol>& transports,
+      const base::flat_set<FidoTransportProtocol>& transports,
       std::vector<std::vector<uint8_t>> registered_keys,
       std::vector<uint8_t> challenge_digest,
       std::vector<uint8_t> application_parameter,
@@ -40,7 +40,7 @@
       SignResponseCallback completion_callback);
 
   U2fSign(service_manager::Connector* connector,
-          const base::flat_set<U2fTransportProtocol>& transports,
+          const base::flat_set<FidoTransportProtocol>& transports,
           std::vector<std::vector<uint8_t>> registered_keys,
           std::vector<uint8_t> challenge_digest,
           std::vector<uint8_t> application_parameter,
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
index 3299e9c..f4d3c13 100644
--- a/device/fido/u2f_sign_unittest.cc
+++ b/device/fido/u2f_sign_unittest.cc
@@ -15,6 +15,7 @@
 #include "device/fido/fake_fido_discovery.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/fido_transport_protocol.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
@@ -84,8 +85,8 @@
     ForgeNextHidDiscovery();
     return std::make_unique<U2fSign>(
         nullptr /* connector */,
-        base::flat_set<U2fTransportProtocol>(
-            {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+        base::flat_set<FidoTransportProtocol>(
+            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
         std::move(registered_keys), challenge_parameter_,
         application_parameter_, base::nullopt,
         sign_callback_receiver_.callback());
@@ -103,7 +104,7 @@
   test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
   test::FakeFidoDiscovery* discovery_;
   TestSignCallback sign_callback_receiver_;
-  base::flat_set<U2fTransportProtocol> protocols_;
+  base::flat_set<FidoTransportProtocol> protocols_;
 };
 
 TEST_F(U2fSignTest, TestCreateSignApduCommand) {
@@ -507,8 +508,8 @@
   ForgeNextHidDiscovery();
   auto request = std::make_unique<U2fSign>(
       nullptr /* connector */,
-      base::flat_set<U2fTransportProtocol>(
-          {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
+      base::flat_set<FidoTransportProtocol>(
+          {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
       std::vector<std::vector<uint8_t>>({signing_key_handle}),
       std::vector<uint8_t>(32), primary_app_param, alt_app_param,
       sign_callback_receiver_.callback());
diff --git a/device/fido/u2f_transport_protocol.h b/device/fido/u2f_transport_protocol.h
deleted file mode 100644
index ae419269..0000000
--- a/device/fido/u2f_transport_protocol.h
+++ /dev/null
@@ -1,20 +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 DEVICE_U2F_U2F_TRANSPORT_PROTOCOL_H_
-#define DEVICE_U2F_U2F_TRANSPORT_PROTOCOL_H_
-
-namespace device {
-
-// This enum represents the transport protocols over which U2F is currently
-// supported.
-enum class U2fTransportProtocol {
-  kUsbHumanInterfaceDevice,
-  kNearFieldCommunication,
-  kBluetoothLowEnergy,
-};
-
-}  // namespace device
-
-#endif  // DEVICE_U2F_U2F_TRANSPORT_PROTOCOL_H_
diff --git a/extensions/browser/updater/update_service.cc b/extensions/browser/updater/update_service.cc
index 56e06ce..fd513ac 100644
--- a/extensions/browser/updater/update_service.cc
+++ b/extensions/browser/updater/update_service.cc
@@ -71,6 +71,13 @@
 bool UpdateService::CanUpdate(const std::string& extension_id) const {
   if (!base::FeatureList::IsEnabled(features::kNewExtensionUpdaterService))
     return false;
+  // It's possible to change Webstore update URL from command line (through
+  // apps-gallery-update-url command line switch). When Webstore update URL is
+  // different the default Webstore update URL, we won't support updating
+  // extensions through UpdateService.
+  if (extension_urls::GetDefaultWebstoreUpdateUrl() !=
+      extension_urls::GetWebstoreUpdateUrl())
+    return false;
   // We can only update extensions that have been installed on the system.
   // Furthermore, we can only update extensions that were installed from the
   // webstore.
diff --git a/extensions/browser/updater/update_service_unittest.cc b/extensions/browser/updater/update_service_unittest.cc
index ddb1e03..ad80d16 100644
--- a/extensions/browser/updater/update_service_unittest.cc
+++ b/extensions/browser/updater/update_service_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/crx_file/id_util.h"
@@ -29,6 +30,9 @@
 #include "extensions/browser/updater/extension_update_data.h"
 #include "extensions/browser/updater/update_service.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_features.h"
+#include "extensions/common/extension_urls.h"
+#include "extensions/common/extensions_client.h"
 #include "extensions/common/manifest_url_handlers.h"
 #include "extensions/common/value_builder.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -726,6 +730,95 @@
   ASSERT_TRUE(executed4);
 }
 
+class UpdateServiceCanUpdateTest : public UpdateServiceTest,
+                                   public ::testing::WithParamInterface<bool> {
+ public:
+  UpdateServiceCanUpdateTest() {}
+  ~UpdateServiceCanUpdateTest() override {}
+
+  void SetUp() override {
+    UpdateServiceTest::SetUp();
+
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kNewExtensionUpdaterService);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          features::kNewExtensionUpdaterService);
+    }
+
+    store_extension_ =
+        ExtensionBuilder("store_extension")
+            .MergeManifest(
+                DictionaryBuilder()
+                    .Set("update_url",
+                         extension_urls::GetDefaultWebstoreUpdateUrl().spec())
+                    .Build())
+            .Build();
+    offstore_extension_ =
+        ExtensionBuilder("offstore_extension")
+            .MergeManifest(
+                DictionaryBuilder()
+                    .Set("update_url", "http://localhost/test/updates.xml")
+                    .Build())
+            .Build();
+
+    ASSERT_TRUE(store_extension_.get());
+    ASSERT_TRUE(ExtensionRegistry::Get(browser_context())
+                    ->AddEnabled(store_extension_));
+    ASSERT_TRUE(offstore_extension_.get());
+    ASSERT_TRUE(ExtensionRegistry::Get(browser_context())
+                    ->AddEnabled(offstore_extension_));
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_refptr<Extension> store_extension_;
+  scoped_refptr<Extension> offstore_extension_;
+};
+
+class UpdateServiceCanUpdateFeatureEnabledNonDefaultUpdateUrl
+    : public UpdateServiceCanUpdateTest {
+ public:
+  void SetUp() override {
+    UpdateServiceCanUpdateTest::SetUp();
+
+    // Change the webstore update url.
+    auto* command_line = base::CommandLine::ForCurrentProcess();
+    // Note: |offstore_extension_|'s update url is the same.
+    command_line->AppendSwitchASCII("apps-gallery-update-url",
+                                    "http://localhost/test/updates.xml");
+    ExtensionsClient::Get()->InitializeWebStoreUrls(
+        base::CommandLine::ForCurrentProcess());
+  }
+};
+
+TEST_P(UpdateServiceCanUpdateTest, UpdateService_CanUpdate) {
+  // Update service can only update webstore extensions when enabled.
+  EXPECT_EQ(GetParam(), update_service()->CanUpdate(store_extension_->id()));
+  // It can't update off-store extrensions.
+  EXPECT_FALSE(update_service()->CanUpdate(offstore_extension_->id()));
+  // ... or extensions that don't exist.
+  EXPECT_FALSE(update_service()->CanUpdate(std::string(32, 'a')));
+}
+
+TEST_P(UpdateServiceCanUpdateFeatureEnabledNonDefaultUpdateUrl,
+       UpdateService_CanUpdate) {
+  // Update service cannot update extensions when the default webstore update
+  // url is changed.
+  EXPECT_FALSE(update_service()->CanUpdate(store_extension_->id()));
+  EXPECT_FALSE(update_service()->CanUpdate(offstore_extension_->id()));
+  EXPECT_FALSE(update_service()->CanUpdate(std::string(32, 'a')));
+}
+
+INSTANTIATE_TEST_CASE_P(CanUpdateTest,
+                        UpdateServiceCanUpdateTest,
+                        ::testing::Bool());
+
+INSTANTIATE_TEST_CASE_P(CanUpdateTest,
+                        UpdateServiceCanUpdateFeatureEnabledNonDefaultUpdateUrl,
+                        ::testing::Bool());
+
 }  // namespace
 
 }  // namespace extensions
diff --git a/extensions/common/common_manifest_handlers.cc b/extensions/common/common_manifest_handlers.cc
index 8c662fc..2ea7e956 100644
--- a/extensions/common/common_manifest_handlers.cc
+++ b/extensions/common/common_manifest_handlers.cc
@@ -29,6 +29,7 @@
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
 #include "extensions/common/manifest_handlers/webview_info.h"
+#include "extensions/common/manifest_url_handlers.h"
 
 #if defined(OS_CHROMEOS)
 #include "extensions/common/manifest_handlers/action_handlers_handler.h"
@@ -64,6 +65,7 @@
   (new SandboxedPageHandler)->Register();
   (new SharedModuleHandler)->Register();
   (new SocketsManifestHandler)->Register();
+  (new UpdateURLHandler)->Register();
   (new UsbPrinterManifestHandler)->Register();
   (new WebAccessibleResourcesHandler)->Register();
   (new WebviewHandler)->Register();
diff --git a/extensions/test/test_extensions_client.cc b/extensions/test/test_extensions_client.cc
index ea03f843..8f2986b5 100644
--- a/extensions/test/test_extensions_client.cc
+++ b/extensions/test/test_extensions_client.cc
@@ -8,6 +8,7 @@
 #include <set>
 #include <string>
 
+#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/stl_util.h"
 #include "extensions/common/api/generated_schemas.h"
@@ -61,7 +62,14 @@
 }
 
 void TestExtensionsClient::InitializeWebStoreUrls(
-    base::CommandLine* command_line) {}
+    base::CommandLine* command_line) {
+  // TODO (mxnguyen): Move |kAppsGalleryUpdateURL| constant from chrome/... to
+  // extensions/... to avoid referring to the constant value directly.
+  if (command_line->HasSwitch("apps-gallery-update-url")) {
+    webstore_update_url_ =
+        GURL(command_line->GetSwitchValueASCII("apps-gallery-update-url"));
+  }
+}
 
 const PermissionMessageProvider&
 TestExtensionsClient::GetPermissionMessageProvider() const {
diff --git a/extensions/test/test_extensions_client.h b/extensions/test/test_extensions_client.h
index dfbca7b..972bc226 100644
--- a/extensions/test/test_extensions_client.h
+++ b/extensions/test/test_extensions_client.h
@@ -65,7 +65,7 @@
   std::set<BrowserImagePathsFilter*> browser_image_filters_;
 
   const GURL webstore_base_url_;
-  const GURL webstore_update_url_;
+  GURL webstore_update_url_;
 
   DISALLOW_COPY_AND_ASSIGN(TestExtensionsClient);
 };
diff --git a/gpu/command_buffer/client/client_discardable_manager.cc b/gpu/command_buffer/client/client_discardable_manager.cc
index ed56dfb4..61794ed 100644
--- a/gpu/command_buffer/client/client_discardable_manager.cc
+++ b/gpu/command_buffer/client/client_discardable_manager.cc
@@ -5,7 +5,6 @@
 #include "gpu/command_buffer/client/client_discardable_manager.h"
 
 #include "base/containers/flat_set.h"
-#include "base/memory/ptr_util.h"
 #include "base/sys_info.h"
 
 namespace gpu {
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
index 7613d8a..3a76b38 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc
index 4bdcb9e..4dc7898 100644
--- a/gpu/command_buffer/client/fenced_allocator_test.cc
+++ b/gpu/command_buffer/client/fenced_allocator_test.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/aligned_memory.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc
index 72c00db..ca7f5b8 100644
--- a/gpu/command_buffer/client/mapped_memory_unittest.cc
+++ b/gpu/command_buffer/client/mapped_memory_unittest.cc
@@ -11,7 +11,6 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
diff --git a/gpu/command_buffer/client/query_tracker.cc b/gpu/command_buffer/client/query_tracker.cc
index 5a6c8e5..c5994f6 100644
--- a/gpu/command_buffer/client/query_tracker.cc
+++ b/gpu/command_buffer/client/query_tracker.cc
@@ -14,7 +14,6 @@
 
 #include "base/atomicops.h"
 #include "base/containers/circular_deque.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc
index 7c5d209..5640705 100644
--- a/gpu/command_buffer/client/ring_buffer_test.cc
+++ b/gpu/command_buffer/client/ring_buffer_test.cc
@@ -12,7 +12,6 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 3d989386..1f48ae78 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -11,7 +11,6 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/cmd_buffer_common.h"
 #include "gpu/command_buffer/common/command_buffer_shared.h"
diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc
index 9e53de5..52c9e7d 100644
--- a/gpu/command_buffer/service/command_buffer_service_unittest.cc
+++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc
@@ -9,7 +9,6 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/client/client_test_helper.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
 #include "gpu/command_buffer/service/mocks.h"
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 3def1f31..278e934 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -11,7 +11,6 @@
 #include <string>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/service/buffer_manager.h"
 #include "gpu/command_buffer/service/decoder_context.h"
 #include "gpu/command_buffer/service/framebuffer_manager.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index e66e141..b2029e29 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -20,7 +20,6 @@
 #include "base/containers/queue.h"
 #include "base/containers/span.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index 1367c1e..1e6f3d44 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -11,7 +11,6 @@
 #include <memory>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "gpu/command_buffer/common/gles2_cmd_format.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 2fe1ca8..ae8b149 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -5,7 +5,6 @@
 #include <stdint.h>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/client/client_test_helper.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
diff --git a/gpu/command_buffer/service/mailbox_manager_factory.cc b/gpu/command_buffer/service/mailbox_manager_factory.cc
index 395bd209..b810d7cf 100644
--- a/gpu/command_buffer/service/mailbox_manager_factory.cc
+++ b/gpu/command_buffer/service/mailbox_manager_factory.cc
@@ -5,7 +5,6 @@
 #include "gpu/command_buffer/service/mailbox_manager_factory.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/mailbox_manager_sync.h"
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc
index cb38432..1ffcdca 100644
--- a/gpu/command_buffer/service/mailbox_manager_sync.cc
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 
 #include "base/containers/queue.h"
-#include "base/memory/ptr_util.h"
 #include "base/synchronization/lock.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/texture_manager.h"
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 6600d0f6..1f1f201 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
diff --git a/gpu/command_buffer/service/scheduler.cc b/gpu/command_buffer/service/scheduler.cc
index b269bce..74f9319 100644
--- a/gpu/command_buffer/service/scheduler.cc
+++ b/gpu/command_buffer/service/scheduler.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/callback.h"
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
diff --git a/gpu/command_buffer/service/scheduler_unittest.cc b/gpu/command_buffer/service/scheduler_unittest.cc
index f77d657..96d34b6 100644
--- a/gpu/command_buffer/service/scheduler_unittest.cc
+++ b/gpu/command_buffer/service/scheduler_unittest.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/gpu/command_buffer/service/sync_point_manager.cc b/gpu/command_buffer/service/sync_point_manager.cc
index 08b5bc2..92c4c88 100644
--- a/gpu/command_buffer/service/sync_point_manager.cc
+++ b/gpu/command_buffer/service/sync_point_manager.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 
diff --git a/gpu/command_buffer/service/sync_point_manager_unittest.cc b/gpu/command_buffer/service/sync_point_manager_unittest.cc
index f926a74..5ed87c7 100644
--- a/gpu/command_buffer/service/sync_point_manager_unittest.cc
+++ b/gpu/command_buffer/service/sync_point_manager_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/containers/queue.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
index 0ee9483..9bdeed8 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
@@ -8,7 +8,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index b240c2d..95a1bf2e 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
diff --git a/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc
index d3855df..a2510a9 100644
--- a/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc
@@ -13,7 +13,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/tests/gl_manager.h"
 #include "gpu/command_buffer/tests/gl_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc
index f93c1d2..a34cc7fc 100644
--- a/gpu/config/gpu_control_list.cc
+++ b/gpu/config/gpu_control_list.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index c46dd32d..2c3c0ac 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -479,8 +479,8 @@
     },
     {
       "id": 68,
-      "description": "VMware has corrupt rendering on Windows",
-      "cr_bugs": [169470, 754435],
+      "description": "VMware Fusion 4 has corrupt rendering with Win Vista+",
+      "cr_bugs": [169470],
       "os": {
         "type": "win",
         "version": {
@@ -489,6 +489,10 @@
         }
       },
       "vendor_id": "0x15ad",
+      "driver_version": {
+        "op": "<=",
+        "value": "7.14.1.1134"
+      },
       "features": [
         "all"
       ]
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
index cdd99a0..4e7fb82 100644
--- a/gpu/gles2_conform_support/egl/context.cc
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
diff --git a/gpu/ipc/host/shader_disk_cache.cc b/gpu/ipc/host/shader_disk_cache.cc
index 7504616..8f76ba80 100644
--- a/gpu/ipc/host/shader_disk_cache.cc
+++ b/gpu/ipc/host/shader_disk_cache.cc
@@ -5,7 +5,6 @@
 #include "gpu/ipc/host/shader_disk_cache.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/sys_info.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
diff --git a/gpu/ipc/host/shader_disk_cache_unittest.cc b/gpu/ipc/host/shader_disk_cache_unittest.cc
index 1e429ee1..c69fafe9 100644
--- a/gpu/ipc/host/shader_disk_cache_unittest.cc
+++ b/gpu/ipc/host/shader_disk_cache_unittest.cc
@@ -5,7 +5,6 @@
 #include "gpu/ipc/host/shader_disk_cache.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "net/base/test_completion_callback.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 90ab63b..6710e27 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -19,7 +19,6 @@
 #include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/sequence_checker.h"
diff --git a/gpu/ipc/service/child_window_win.cc b/gpu/ipc/service/child_window_win.cc
index c3fe0e4..785731d3 100644
--- a/gpu/ipc/service/child_window_win.cc
+++ b/gpu/ipc/service/child_window_win.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/compiler_specific.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "base/win/scoped_hdc.h"
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc
index 8584202..58ef9f80 100644
--- a/gpu/ipc/service/direct_composition_child_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_child_surface_win.cc
@@ -9,7 +9,6 @@
 
 #include "base/debug/alias.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/trace_event/trace_event.h"
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index 71ec9c2..00c81c5 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -11,7 +11,6 @@
 #include "base/containers/circular_deque.h"
 #include "base/debug/alias.h"
 #include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index ce0b5e5..4cb8021 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -12,7 +12,6 @@
 #include "base/json/json_writer.h"
 #include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index e91f73a..d055d94 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc
index 6dce9c29..f3ae1e7 100644
--- a/gpu/ipc/service/gpu_channel_test_common.cc
+++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -4,7 +4,6 @@
 
 #include "gpu/ipc/service/gpu_channel_test_common.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/gpu/ipc/service/raster_command_buffer_stub.cc b/gpu/ipc/service/raster_command_buffer_stub.cc
index 49a08a3b..4c2290b 100644
--- a/gpu/ipc/service/raster_command_buffer_stub.cc
+++ b/gpu/ipc/service/raster_command_buffer_stub.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
diff --git a/gpu/tools/compositor_model_bench/render_models.cc b/gpu/tools/compositor_model_bench/render_models.cc
index 68970ead..aee89cda6 100644
--- a/gpu/tools/compositor_model_bench/render_models.cc
+++ b/gpu/tools/compositor_model_bench/render_models.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "gpu/tools/compositor_model_bench/forward_render_model.h"
 
 const char* ModelToString(RenderModel m) {
diff --git a/gpu/vulkan/vulkan_descriptor_pool.cc b/gpu/vulkan/vulkan_descriptor_pool.cc
index 99fd107c..e747545 100644
--- a/gpu/vulkan/vulkan_descriptor_pool.cc
+++ b/gpu/vulkan/vulkan_descriptor_pool.cc
@@ -5,7 +5,6 @@
 #include "gpu/vulkan/vulkan_descriptor_pool.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/vulkan/vulkan_descriptor_set.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
 
diff --git a/gpu/vulkan/vulkan_shader_module.cc b/gpu/vulkan/vulkan_shader_module.cc
index fde7ac1f..2f3b5b9 100644
--- a/gpu/vulkan/vulkan_shader_module.cc
+++ b/gpu/vulkan/vulkan_shader_module.cc
@@ -9,7 +9,6 @@
 #include <sstream>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
 
 namespace {
diff --git a/infra/config/global/luci-milo-dev.cfg b/infra/config/global/luci-milo-dev.cfg
index 708ba19e..505fce88 100644
--- a/infra/config/global/luci-milo-dev.cfg
+++ b/infra/config/global/luci-milo-dev.cfg
@@ -3012,14 +3012,6 @@
     category: "android"
   }
   builders: {
-    name: "buildbot/chromium.perf.fyi/Battor Agent Mac"
-    category: "battor"
-  }
-  builders: {
-    name: "buildbot/chromium.perf.fyi/Battor Agent Win"
-    category: "battor"
-  }
-  builders: {
     name: "buildbot/chromium.perf.fyi/Mojo Linux Perf"
     category: "linux"
   }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 706ab23..3db9553 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -1867,6 +1867,16 @@
     category: "chromium.android|debug"
     short_name: "ci"
   }
+  builders: {
+    name: "buildbot/chromium.mac/ios-simulator"
+    category: "chromium.mac|ios-simulator"
+    short_name: "bb"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/ios-simulator"
+    category: "chromium.mac|ios-simulator"
+    short_name: "ci"
+  }
 }
 
 # Everything below was generated from buildermap.json.
@@ -3476,14 +3486,6 @@
     category: "android"
   }
   builders: {
-    name: "buildbot/chromium.perf.fyi/Battor Agent Mac"
-    category: "battor"
-  }
-  builders: {
-    name: "buildbot/chromium.perf.fyi/Battor Agent Win"
-    category: "battor"
-  }
-  builders: {
     name: "buildbot/chromium.perf.fyi/Mojo Linux Perf"
     category: "linux"
   }
diff --git a/ios/chrome/browser/sync/ios_user_event_service_factory.cc b/ios/chrome/browser/sync/ios_user_event_service_factory.cc
index 85fbc90..05230b9 100644
--- a/ios/chrome/browser/sync/ios_user_event_service_factory.cc
+++ b/ios/chrome/browser/sync/ios_user_event_service_factory.cc
@@ -60,7 +60,7 @@
       std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
           syncer::USER_EVENTS, /*dump_stack=*/base::BindRepeating(
               &syncer::ReportUnrecoverableError, ::GetChannel())),
-      sync_service->GetGlobalIdMapper());
+      sync_service->GetGlobalIdMapper(), sync_service);
   return std::make_unique<syncer::UserEventServiceImpl>(sync_service,
                                                         std::move(bridge));
 }
diff --git a/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm b/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm
index 06815f0e..bdcc1f09 100644
--- a/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm
+++ b/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm
@@ -10,8 +10,8 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/metrics/user_metrics.h"
 #include "components/infobars/core/infobar_manager.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/infobars/infobar.h"
@@ -77,8 +77,8 @@
     authService->SetPromptForSignIn(false);
     return nullptr;
   }
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Impression_FromReSigninInfobar"));
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+      signin_metrics::AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR);
   // User needs to be reminded to sign in again. Creates a new infobar delegate
   // and returns it.
   return std::make_unique<ReSignInInfoBarDelegate>(browser_state, presenter);
@@ -120,8 +120,8 @@
 }
 
 bool ReSignInInfoBarDelegate::Accept() {
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Signin_FromReSigninInfobar"));
+  signin_metrics::RecordSigninUserActionForAccessPoint(
+      signin_metrics::AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR);
   UIView* infobarView = static_cast<InfoBarIOS*>(infobar())->view();
   DCHECK(infobarView);
   ShowSigninCommand* command = [[ShowSigninCommand alloc]
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
index 1a66806..5ea9c283 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
@@ -49,84 +49,6 @@
   }
 }
 
-void RecordSigninImpressionUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point) {
-  switch (access_point) {
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_Impression_FromBookmarkManager"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_Impression_FromRecentTabs"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_Impression_FromSettings"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_Impression_FromTabSwitcher"));
-      break;
-    default:
-      NOTREACHED() << "Unexpected value for access point "
-                   << static_cast<int>(access_point);
-      break;
-  }
-}
-
-void RecordSigninImpressionWithAccountUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point) {
-  switch (access_point) {
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithAccount_FromBookmarkManager"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithAccount_FromRecentTabs"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_ImpressionWithAccount_FromSettings"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithAccount_FromTabSwitcher"));
-      break;
-    default:
-      NOTREACHED() << "Unexpected value for access point "
-                   << static_cast<int>(access_point);
-      break;
-  }
-}
-
-void RecordSigninImpressionWithNoAccountUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point) {
-  switch (access_point) {
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithNoAccount_FromBookmarkManager"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithNoAccount_FromRecentTabs"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithNoAccount_FromSettings"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_ImpressionWithNoAccount_FromTabSwitcher"));
-      break;
-    default:
-      NOTREACHED() << "Unexpected value for access point "
-                   << static_cast<int>(access_point);
-      break;
-  }
-}
-
 void RecordSigninDefaultUserActionForAccessPoint(
     signin_metrics::AccessPoint access_point) {
   switch (access_point) {
@@ -450,12 +372,9 @@
   if (_signinPromoViewState == ios::SigninPromoViewState::NeverVisible)
     _signinPromoViewState = ios::SigninPromoViewState::Unused;
   _isSigninPromoViewVisible = YES;
-  RecordSigninImpressionUserActionForAccessPoint(_accessPoint);
-  if (_defaultIdentity) {
-    RecordSigninImpressionWithAccountUserActionForAccessPoint(_accessPoint);
-  } else {
-    RecordSigninImpressionWithNoAccountUserActionForAccessPoint(_accessPoint);
-  }
+  signin_metrics::RecordSigninImpressionUserActionForAccessPoint(_accessPoint);
+  signin_metrics::RecordSigninImpressionWithAccountUserActionForAccessPoint(
+      _accessPoint, !!_defaultIdentity);
   const char* displayedCountPreferenceKey =
       DisplayedCountPreferenceKey(_accessPoint);
   if (!displayedCountPreferenceKey)
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index ffca2bd..9d3da6d 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -102,6 +102,7 @@
     "history_table_updater_delegate.h",
     "history_table_view_controller.h",
     "history_table_view_controller.mm",
+    "history_table_view_controller_delegate.h",
     "history_util.h",
     "history_util.mm",
   ]
@@ -115,8 +116,11 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/sync",
+    "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/collection_view/cells",
+    "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:styler",
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm
index 2ffb493..a93265e5 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.mm
+++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -60,6 +60,7 @@
   self.historyContainerViewController =
       [[HistoryTableContainerViewController alloc]
           initWithTable:historyTableViewController];
+  self.historyContainerViewController.dispatcher = self.dispatcher;
   self.historyContainerViewController.title =
       l10n_util::GetNSString(IDS_HISTORY_TITLE);
   // TODO(crbug.com/805192): Move this configuration code to
@@ -68,6 +69,7 @@
   [self.historyContainerViewController.dismissButton setAction:@selector(stop)];
   self.historyContainerViewController.navigationItem.rightBarButtonItem =
       self.historyContainerViewController.dismissButton;
+  historyTableViewController.delegate = self.historyContainerViewController;
 
   // Present HistoryContainerViewController.
   FormSheetNavigationController* navController =
diff --git a/ios/chrome/browser/ui/history/history_table_container_view_controller.h b/ios/chrome/browser/ui/history/history_table_container_view_controller.h
index 813982af..a5f40f15 100644
--- a/ios/chrome/browser/ui/history/history_table_container_view_controller.h
+++ b/ios/chrome/browser/ui/history/history_table_container_view_controller.h
@@ -5,15 +5,22 @@
 #ifndef IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_CONTAINER_VIEW_CONTROLLER_H_
 #define IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_CONTAINER_VIEW_CONTROLLER_H_
 
+#import "ios/chrome/browser/ui/history/history_table_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/table_view/table_container_view_controller.h"
 
+@protocol ApplicationCommands;
 @protocol HistoryTableUpdaterDelegate;
 
 // Container for handling the interaction between its TableViewController, the
 // container BottomToolbar and the SearchController.
-@interface HistoryTableContainerViewController : TableContainerViewController
+@interface HistoryTableContainerViewController
+    : TableContainerViewController<HistoryTableViewControllerDelegate>
+
 - (instancetype)initWithTable:
     (ChromeTableViewController<HistoryTableUpdaterDelegate>*)table;
+// The dispatcher used by this ViewController.
+@property(nonatomic, weak) id<ApplicationCommands> dispatcher;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/history/history_table_container_view_controller.mm b/ios/chrome/browser/ui/history/history_table_container_view_controller.mm
index 5e746bbb..cc40eec3 100644
--- a/ios/chrome/browser/ui/history/history_table_container_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_container_view_controller.mm
@@ -5,7 +5,10 @@
 #import "ios/chrome/browser/ui/history/history_table_container_view_controller.h"
 
 #include "base/mac/foundation_util.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
 #include "ios/chrome/browser/ui/history/history_table_view_controller.h"
 #import "ios/chrome/browser/ui/table_view/table_container_bottom_toolbar.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -20,12 +23,14 @@
 @end
 
 @implementation HistoryTableContainerViewController
+@synthesize dispatcher = _dispatcher;
 @synthesize searchController = _searchController;
 
 - (instancetype)initWithTable:
     (ChromeTableViewController<HistoryTableUpdaterDelegate>*)table {
   self = [super initWithTable:table];
   if (self) {
+    // Setup the bottom toolbar.
     NSString* leadingButtonString = l10n_util::GetNSStringWithFixup(
         IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG);
     NSString* trailingButtonString =
@@ -36,6 +41,11 @@
     [toolbar.leadingButton setTitleColor:[UIColor redColor]
                                 forState:UIControlStateNormal];
     self.bottomToolbar = toolbar;
+
+    // Setup toolbar buttons.
+    [self.bottomToolbar.leadingButton addTarget:self
+                                         action:@selector(openPrivacySettings)
+                               forControlEvents:UIControlEventTouchUpInside];
   }
   return self;
 }
@@ -64,4 +74,35 @@
   }
 }
 
+#pragma mark - Private Methods
+
+- (void)openPrivacySettings {
+  // Ignore the button tap if |self| is presenting another ViewController.
+  // TODO(crbug.com/831865): Find a way to disable the button when a VC is
+  // presented.
+  if ([self presentedViewController]) {
+    return;
+  }
+  base::RecordAction(
+      base::UserMetricsAction("HistoryPage_InitClearBrowsingData"));
+  [self.dispatcher showClearBrowsingDataSettingsFromViewController:
+                       self.navigationController];
+}
+
+#pragma mark - HistoryTableViewControllerDelegate
+
+- (void)dismissHistoryWithCompletion:(ProceduralBlock)completionHandler {
+  [self.presentingViewController
+      dismissViewControllerAnimated:YES
+                         completion:completionHandler];
+}
+
+- (void)historyTableViewControllerDidChangeEntries {
+  // TODO(crbug.com/805190): Migrate.
+}
+
+- (void)historyTableViewControllerDidChangeEntrySelection {
+  // TODO(crbug.com/805190): Migrate.
+}
+
 @end
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.h b/ios/chrome/browser/ui/history/history_table_view_controller.h
index 54d0e191..3f2c34c1 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.h
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.h
@@ -7,7 +7,6 @@
 
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
 
-#include "base/ios/block_types.h"
 #include "ios/chrome/browser/ui/history/history_consumer.h"
 #include "ios/chrome/browser/ui/history/history_table_updater_delegate.h"
 
@@ -15,25 +14,9 @@
 class ChromeBrowserState;
 }
 
-@class HistoryTableViewController;
+@protocol HistoryTableViewControllerDelegate;
 @protocol UrlLoader;
 
-// Delegate for HistoryTableViewController.
-@protocol HistoryTableViewControllerDelegate<NSObject>
-// Notifies the delegate that history should be dismissed.
-- (void)historyTableViewController:(HistoryTableViewController*)controller
-         shouldCloseWithCompletion:(ProceduralBlock)completionHandler;
-// Notifies the delegate that the tableView has scrolled to |offset|.
-- (void)historyTableViewController:(HistoryTableViewController*)controller
-                 didScrollToOffset:(CGPoint)offset;
-// Notifies the delegate that history entries have been loaded or changed.
-- (void)historyTableViewControllerDidChangeEntries:
-    (HistoryTableViewController*)controller;
-// Notifies the delegate that history entries have been selected or deselected.
-- (void)historyTableViewControllerDidChangeEntrySelection:
-    (HistoryTableViewController*)controller;
-@end
-
 // ChromeTableViewController for displaying history items.
 @interface HistoryTableViewController
     : ChromeTableViewController<HistoryConsumer, HistoryTableUpdaterDelegate>
@@ -45,8 +28,7 @@
 // The UrlLoader used by this ViewController.
 @property(nonatomic, weak) id<UrlLoader> loader;
 // Delegate for this HistoryTableView.
-@property(nonatomic, weak, readonly) id<HistoryTableViewControllerDelegate>
-    delegate;
+@property(nonatomic, weak) id<HistoryTableViewControllerDelegate> delegate;
 
 @end
 
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm
index 3528c121..628fa77 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -6,18 +6,24 @@
 
 #include "base/i18n/time_formatting.h"
 #include "base/mac/foundation_util.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/metrics/new_tab_page_uma.h"
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #include "ios/chrome/browser/ui/history/history_entries_status_item.h"
 #import "ios/chrome/browser/ui/history/history_entries_status_item_delegate.h"
 #include "ios/chrome/browser/ui/history/history_entry_inserter.h"
 #import "ios/chrome/browser/ui/history/history_entry_item.h"
+#import "ios/chrome/browser/ui/history/history_table_view_controller_delegate.h"
 #include "ios/chrome/browser/ui/history/history_util.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h"
+#import "ios/chrome/browser/ui/url_loader.h"
 #include "ios/chrome/grit/ios_strings.h"
+#import "ios/web/public/referrer.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -126,40 +132,9 @@
   [self showHistoryMatchingQuery:nil];
 }
 
-#pragma mark - Protocols.
+#pragma mark - Protocols
 
-#pragma mark HistoryEntriesStatusItemDelegate
-
-- (void)historyEntriesStatusItem:(HistoryEntriesStatusItem*)item
-               didRequestOpenURL:(const GURL&)URL {
-  // TODO(crbug.com/805190): Migrate.
-}
-
-#pragma mark HistoryEntryInserterDelegate
-
-- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
-    didInsertItemAtIndexPath:(NSIndexPath*)indexPath {
-  [self.tableView insertRowsAtIndexPaths:@[ indexPath ]
-                        withRowAnimation:UITableViewRowAnimationNone];
-}
-
-- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
-     didInsertSectionAtIndex:(NSInteger)sectionIndex {
-  [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
-                withRowAnimation:UITableViewRowAnimationNone];
-}
-
-- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
-     didRemoveSectionAtIndex:(NSInteger)sectionIndex {
-  [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
-                withRowAnimation:UITableViewRowAnimationNone];
-}
-
-#pragma mark HistoryEntryItemDelegate
-// TODO(crbug.com/805190): Migrate once we decide how to handle favicons and the
-// a11y callback on HistoryEntryItem.
-
-#pragma mark - HistoryConsumer
+#pragma mark HistoryConsumer
 
 - (void)historyQueryWasCompletedWithResults:
             (const std::vector<BrowsingHistoryService::HistoryEntry>&)results
@@ -186,7 +161,7 @@
   // history entries were found.
   if (results.empty() && self.empty) {
     [self updateEntriesStatusMessage];
-    [self.delegate historyTableViewControllerDidChangeEntries:self];
+    [self.delegate historyTableViewControllerDidChangeEntries];
     return;
   }
 
@@ -216,7 +191,7 @@
       item.timestamp = entry.time;
       [resultsItems addObject:item];
     }
-    [self.delegate historyTableViewControllerDidChangeEntries:self];
+    [self.delegate historyTableViewControllerDidChangeEntries];
     if (([self isSearching] && [searchQuery length] > 0 &&
          [self.currentQuery isEqualToString:searchQuery]) ||
         self.filterQueryResult) {
@@ -265,6 +240,48 @@
   [self showHistoryMatchingQuery:nil];
 }
 
+#pragma mark HistoryEntriesStatusItemDelegate
+
+- (void)historyEntriesStatusItem:(HistoryEntriesStatusItem*)item
+               didRequestOpenURL:(const GURL&)URL {
+  // TODO(crbug.com/805190): Migrate.
+}
+
+#pragma mark HistoryEntryInserterDelegate
+
+- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
+    didInsertItemAtIndexPath:(NSIndexPath*)indexPath {
+  [self.tableView insertRowsAtIndexPaths:@[ indexPath ]
+                        withRowAnimation:UITableViewRowAnimationNone];
+}
+
+- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
+     didInsertSectionAtIndex:(NSInteger)sectionIndex {
+  [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
+                withRowAnimation:UITableViewRowAnimationNone];
+}
+
+- (void)historyEntryInserter:(HistoryEntryInserter*)inserter
+     didRemoveSectionAtIndex:(NSInteger)sectionIndex {
+  [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
+                withRowAnimation:UITableViewRowAnimationNone];
+}
+
+#pragma mark HistoryEntryItemDelegate
+// TODO(crbug.com/805190): Migrate once we decide how to handle favicons and the
+// a11y callback on HistoryEntryItem.
+
+#pragma mark HistoryTableUpdaterDelegate
+
+- (void)showHistoryMatchingQuery:(NSString*)query {
+  self.finishedLoading = NO;
+  self.currentQuery = query;
+  [self fetchHistoryForQuery:query continuation:false];
+}
+- (void)deleteSelectedItems {
+  // TODO(crbug.com/805190): Migrate.
+}
+
 #pragma mark - UITableViewDelegate
 
 - (CGFloat)tableView:(UITableView*)tableView
@@ -276,6 +293,24 @@
   return UITableViewAutomaticDimension;
 }
 
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  DCHECK_EQ(tableView, self.tableView);
+  if (self.isEditing) {
+    [self.delegate historyTableViewControllerDidChangeEntrySelection];
+  } else {
+    HistoryEntryItem* item = base::mac::ObjCCastStrict<HistoryEntryItem>(
+        [self.tableViewModel itemAtIndexPath:indexPath]);
+    [self openURL:item.URL];
+    if (self.isSearching) {
+      base::RecordAction(
+          base::UserMetricsAction("HistoryPage_SearchResultClick"));
+    } else {
+      base::RecordAction(base::UserMetricsAction("HistoryPage_EntryLinkClick"));
+    }
+  }
+}
+
 #pragma mark - UIScrollViewDelegate
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
@@ -374,32 +409,38 @@
 }
 
 #pragma mark Context Menu
+
+// Displays context menu on cell pressed with gestureRecognizer.
 - (void)displayContextMenuInvokedByGestureRecognizer:
     (UILongPressGestureRecognizer*)gestureRecognizer {
   // TODO(crbug.com/805190): Migrate.
 }
 
-- (void)openURL:(const GURL&)URL {
-  // TODO(crbug.com/805190): Migrate.
-}
-
+// Opens URL in a new non-incognito tab and dismisses the history view.
 - (void)openURLInNewTab:(const GURL&)URL {
   // TODO(crbug.com/805190): Migrate.
 }
 
+// Opens URL in a new incognito tab and dismisses the history view.
 - (void)openURLInNewIncognitoTab:(const GURL&)URL {
   // TODO(crbug.com/805190): Migrate.
 }
 
-#pragma mark - HistoryTableUpdaterDelegate
+#pragma mark Helper Methods
 
-- (void)showHistoryMatchingQuery:(NSString*)query {
-  self.finishedLoading = NO;
-  self.currentQuery = query;
-  [self fetchHistoryForQuery:query continuation:false];
-}
-- (void)deleteSelectedItems {
-  // TODO(crbug.com/805190): Migrate.
+// Opens URL in the current tab and dismisses the history view.
+- (void)openURL:(const GURL&)URL {
+  // Make a copy to make sure the referenced URL doesn't change while we're
+  // opening it.
+  GURL copiedURL(URL);
+  new_tab_page_uma::RecordAction(_browserState,
+                                 new_tab_page_uma::ACTION_OPENED_HISTORY_ENTRY);
+  [self.delegate dismissHistoryWithCompletion:^{
+    [self.loader loadURL:copiedURL
+                 referrer:web::Referrer()
+               transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK
+        rendererInitiated:NO];
+  }];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller_delegate.h b/ios/chrome/browser/ui/history/history_table_view_controller_delegate.h
new file mode 100644
index 0000000..bbdb54ad
--- /dev/null
+++ b/ios/chrome/browser/ui/history/history_table_view_controller_delegate.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_VIEW_CONTROLLER_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_VIEW_CONTROLLER_DELEGATE_H_
+
+#include "base/ios/block_types.h"
+
+// Delegate for handling HistoryTableViewController actions.
+@protocol HistoryTableViewControllerDelegate
+// Notifies the delegate that history should be dismissed.
+- (void)dismissHistoryWithCompletion:(ProceduralBlock)completionHandler;
+// Notifies the delegate that history entries have been loaded or changed.
+- (void)historyTableViewControllerDidChangeEntries;
+// Notifies the delegate that history entries have been selected or deselected.
+- (void)historyTableViewControllerDidChangeEntrySelection;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_TABLE_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
index fc1c93b..0499a19d 100644
--- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -7,7 +7,6 @@
 #include <memory>
 
 #import "base/mac/foundation_util.h"
-#include "base/metrics/user_metrics.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/browser_sync/profile_sync_service.h"
@@ -17,6 +16,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/util.h"
 #include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -447,8 +447,8 @@
   if (!_hasRecordedSigninImpression) {
     // Once the Settings are open, this button impression will at most be
     // recorded once until they are closed.
-    base::RecordAction(
-        base::UserMetricsAction("Signin_Impression_FromSettings"));
+    signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
+        signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS);
     _hasRecordedSigninImpression = YES;
   }
   AccountSignInItem* signInTextItem =
@@ -750,7 +750,8 @@
 
   switch (itemType) {
     case ItemTypeSignInButton:
-      base::RecordAction(base::UserMetricsAction("Signin_Signin_FromSettings"));
+      signin_metrics::RecordSigninUserActionForAccessPoint(
+          signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS);
       [self showSignInWithIdentity:nil
                        promoAction:signin_metrics::PromoAction::
                                        PROMO_ACTION_NO_SIGNIN_PROMO
diff --git a/ios/chrome/browser/ui/table_view/table_container_view_controller.h b/ios/chrome/browser/ui/table_view/table_container_view_controller.h
index 0ee60e8d..8ae1649 100644
--- a/ios/chrome/browser/ui/table_view/table_container_view_controller.h
+++ b/ios/chrome/browser/ui/table_view/table_container_view_controller.h
@@ -8,6 +8,7 @@
 #import <UIKit/UIKit.h>
 
 @class ChromeTableViewController;
+@class TableContainerBottomToolbar;
 
 // TableContainerViewController contains a ChromeTableViewController and a
 // Bottom Toolbar that interacts with the ChromeTableViewController.
@@ -21,7 +22,7 @@
 - (instancetype)init NS_UNAVAILABLE;
 
 // The bottom toolbar owned by this ViewController.
-@property(nonatomic, strong) UIView* bottomToolbar;
+@property(nonatomic, strong) TableContainerBottomToolbar* bottomToolbar;
 
 // UIBarButtonItem to be used on a Navigation Controller to dismiss this
 // ViewController.
diff --git a/ios/chrome/browser/ui/table_view/table_container_view_controller.mm b/ios/chrome/browser/ui/table_view/table_container_view_controller.mm
index a03d909..a6187d6 100644
--- a/ios/chrome/browser/ui/table_view/table_container_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/table_container_view_controller.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/table_view/table_container_view_controller.h"
 
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
+#import "ios/chrome/browser/ui/table_view/table_container_bottom_toolbar.h"
 #import "ios/chrome/browser/ui/table_view/table_container_constants.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -42,7 +43,7 @@
 #pragma mark Setters and Getters
 
 // TODO(crbug.com/805178): Temporary Toolbar code for prototyping purposes.
-- (void)setBottomToolbar:(UIView*)bottomToolbar {
+- (void)setBottomToolbar:(TableContainerBottomToolbar*)bottomToolbar {
   _bottomToolbar = bottomToolbar;
   _bottomToolbar.backgroundColor = [UIColor lightGrayColor];
   _bottomToolbar.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/ui/user_feedback_features.cc b/ios/chrome/browser/ui/user_feedback_features.cc
index f8244c1e..d2fefd9 100644
--- a/ios/chrome/browser/ui/user_feedback_features.cc
+++ b/ios/chrome/browser/ui/user_feedback_features.cc
@@ -8,4 +8,4 @@
                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kFeedbackKitV2WithSSOService{
-    "FeedbackKitV2WithSSOService", base::FEATURE_DISABLED_BY_DEFAULT};
+    "FeedbackKitV2WithSSOService", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 4987757..7f0849a8a 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -352,7 +352,7 @@
   if (is_chromecast) {
     sources += [ "demuxer_memory_limit_low.cc" ]
   } else if (is_android) {
-    sources += [ "demuxer_memory_limit_select.cc" ]
+    sources += [ "demuxer_memory_limit_android.cc" ]
   } else {
     sources += [ "demuxer_memory_limit_default.cc" ]
   }
diff --git a/media/base/demuxer_memory_limit.h b/media/base/demuxer_memory_limit.h
index 610018b..6fac9409 100644
--- a/media/base/demuxer_memory_limit.h
+++ b/media/base/demuxer_memory_limit.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include "build/build_config.h"
 #include "media/base/media_export.h"
 
 namespace media {
@@ -34,6 +35,14 @@
 constexpr size_t kDemuxerStreamVideoMemoryLimitDefault = 150 * 1024 * 1024;
 constexpr size_t kDemuxerStreamVideoMemoryLimitLow = 30 * 1024 * 1024;
 
+#if defined(OS_ANDROID)
+// Special "very low" settings for 512MiB Android Go devices:
+// * audio memory limit: 1MB (30 seconds of 256Kbps content).
+// * video memory limit: 15MB (30 seconds of 4Mbps content).
+constexpr size_t kDemuxerStreamAudioMemoryLimitVeryLow = 1 * 1024 * 1024;
+constexpr size_t kDemuxerStreamVideoMemoryLimitVeryLow = 15 * 1024 * 1024;
+#endif
+
 }  // namespace internal
 
 }  // namespace media
diff --git a/media/base/demuxer_memory_limit_android.cc b/media/base/demuxer_memory_limit_android.cc
new file mode 100644
index 0000000..799e1b7
--- /dev/null
+++ b/media/base/demuxer_memory_limit_android.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 "media/base/demuxer_memory_limit.h"
+
+#include "base/android/build_info.h"
+#include "base/sys_info.h"
+
+namespace media {
+
+namespace {
+
+size_t SelectLimit(size_t default_limit,
+                   size_t low_limit,
+                   size_t very_low_limit) {
+  if (!base::SysInfo::IsLowEndDevice()) {
+    return default_limit;
+  }
+  // Use very low limit on 512MiB Android Go devices only.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+          base::android::SDK_VERSION_OREO &&
+      base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) {
+    return very_low_limit;
+  }
+  return low_limit;
+}
+
+}  // namespace
+
+size_t GetDemuxerStreamAudioMemoryLimit() {
+  static const size_t limit =
+      SelectLimit(internal::kDemuxerStreamAudioMemoryLimitDefault,
+                  internal::kDemuxerStreamAudioMemoryLimitLow,
+                  internal::kDemuxerStreamAudioMemoryLimitVeryLow);
+  return limit;
+}
+
+size_t GetDemuxerStreamVideoMemoryLimit() {
+  static const size_t limit =
+      SelectLimit(internal::kDemuxerStreamVideoMemoryLimitDefault,
+                  internal::kDemuxerStreamVideoMemoryLimitLow,
+                  internal::kDemuxerStreamVideoMemoryLimitVeryLow);
+  return limit;
+}
+
+size_t GetDemuxerMemoryLimit() {
+  return GetDemuxerStreamAudioMemoryLimit() +
+         GetDemuxerStreamVideoMemoryLimit();
+}
+
+}  // namespace media
diff --git a/media/base/demuxer_memory_limit_select.cc b/media/base/demuxer_memory_limit_select.cc
deleted file mode 100644
index e4aa107..0000000
--- a/media/base/demuxer_memory_limit_select.cc
+++ /dev/null
@@ -1,30 +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 "media/base/demuxer_memory_limit.h"
-
-#include "base/sys_info.h"
-
-namespace media {
-
-size_t GetDemuxerStreamAudioMemoryLimit() {
-  static size_t limit = base::SysInfo::IsLowEndDevice()
-                            ? internal::kDemuxerStreamAudioMemoryLimitLow
-                            : internal::kDemuxerStreamAudioMemoryLimitDefault;
-  return limit;
-}
-
-size_t GetDemuxerStreamVideoMemoryLimit() {
-  static size_t limit = base::SysInfo::IsLowEndDevice()
-                            ? internal::kDemuxerStreamVideoMemoryLimitLow
-                            : internal::kDemuxerStreamVideoMemoryLimitDefault;
-  return limit;
-}
-
-size_t GetDemuxerMemoryLimit() {
-  return GetDemuxerStreamAudioMemoryLimit() +
-         GetDemuxerStreamVideoMemoryLimit();
-}
-
-}  // namespace media
diff --git a/media/blink/video_decode_stats_reporter.cc b/media/blink/video_decode_stats_reporter.cc
index e760d47c..8f2a195 100644
--- a/media/blink/video_decode_stats_reporter.cc
+++ b/media/blink/video_decode_stats_reporter.cc
@@ -190,8 +190,9 @@
   frames_dropped_offset_ = frames_dropped_offset;
   frames_decoded_power_efficient_offset_ =
       frames_decoded_power_efficient_offset;
-  recorder_ptr_->StartNewRecord(video_config_.profile(), natural_size_,
-                                last_observed_fps_);
+  mojom::PredictionFeaturesPtr features = mojom::PredictionFeatures::New(
+      video_config_.profile(), natural_size_, last_observed_fps_);
+  recorder_ptr_->StartNewRecord(std::move(features));
 }
 
 void VideoDecodeStatsReporter::ResetFrameRateState() {
@@ -343,18 +344,17 @@
   if (stats.video_frames_decoded == frames_decoded_offset_)
     return;
 
-  uint32_t frames_decoded = stats.video_frames_decoded - frames_decoded_offset_;
-  uint32_t frames_dropped = stats.video_frames_dropped - frames_dropped_offset_;
-  uint32_t frames_decoded_power_efficient =
+  mojom::PredictionTargetsPtr targets = mojom::PredictionTargets::New(
+      stats.video_frames_decoded - frames_decoded_offset_,
+      stats.video_frames_dropped - frames_dropped_offset_,
       stats.video_frames_decoded_power_efficient -
-      frames_decoded_power_efficient_offset_;
+          frames_decoded_power_efficient_offset_);
 
-  DVLOG(2) << __func__ << " Recording -- dropped:" << frames_dropped << "/"
-           << frames_decoded
-           << " power efficient:" << frames_decoded_power_efficient << "/"
-           << frames_decoded;
-  recorder_ptr_->UpdateRecord(frames_decoded, frames_dropped,
-                              frames_decoded_power_efficient);
+  DVLOG(2) << __func__ << " Recording -- dropped:" << targets->frames_dropped
+           << "/" << targets->frames_decoded
+           << " power efficient:" << targets->frames_decoded_power_efficient
+           << "/" << targets->frames_decoded;
+  recorder_ptr_->UpdateRecord(std::move(targets));
 }
 
 }  // namespace media
diff --git a/media/blink/video_decode_stats_reporter_unittest.cc b/media/blink/video_decode_stats_reporter_unittest.cc
index d6055732..313e0eb 100644
--- a/media/blink/video_decode_stats_reporter_unittest.cc
+++ b/media/blink/video_decode_stats_reporter_unittest.cc
@@ -70,15 +70,27 @@
   RecordInterceptor() = default;
   ~RecordInterceptor() override = default;
 
-  MOCK_METHOD3(StartNewRecord,
+  // Until move-only types work.
+  void StartNewRecord(mojom::PredictionFeaturesPtr features) {
+    MockStartNewRecord(features->profile, features->video_size,
+                       features->frames_per_sec);
+  }
+
+  MOCK_METHOD3(MockStartNewRecord,
                void(VideoCodecProfile profile,
                     const gfx::Size& natural_size,
                     int frames_per_sec));
 
-  MOCK_METHOD3(UpdateRecord,
+  void UpdateRecord(mojom::PredictionTargetsPtr targets) {
+    MockUpdateRecord(targets->frames_decoded, targets->frames_dropped,
+                     targets->frames_decoded_power_efficient);
+  }
+
+  MOCK_METHOD3(MockUpdateRecord,
                void(uint32_t frames_decoded,
                     uint32_t frames_dropped,
                     uint32_t frames_decoded_power_efficient));
+
   MOCK_METHOD0(FinalizeRecord, void());
 };
 
@@ -256,7 +268,7 @@
       // The final iteration stabilizes framerate and starts a new record.
       if (CurrentStableFpsSamples() == kRequiredStableFpsSamples - 1) {
         EXPECT_CALL(*interceptor_,
-                    StartNewRecord(profile, natural_size, frames_per_sec));
+                    MockStartNewRecord(profile, natural_size, frames_per_sec));
       }
 
       if (fps_timer_speed == FAST_STABILIZE_FPS) {
@@ -309,12 +321,12 @@
     // Verify that UpdateRecord calls come at the recording interval with
     // correct values.
     EXPECT_CALL(*this, GetPipelineStatsCB());
-    EXPECT_CALL(
-        *interceptor_,
-        UpdateRecord(next_stats.video_frames_decoded - decoded_frames_offset,
-                     next_stats.video_frames_dropped - dropped_frames_offset,
-                     next_stats.video_frames_decoded_power_efficient -
-                         decoded_power_efficient_offset));
+    EXPECT_CALL(*interceptor_,
+                MockUpdateRecord(
+                    next_stats.video_frames_decoded - decoded_frames_offset,
+                    next_stats.video_frames_dropped - dropped_frames_offset,
+                    next_stats.video_frames_decoded_power_efficient -
+                        decoded_power_efficient_offset));
     FastForward(kRecordingInterval);
   }
 
@@ -404,7 +416,7 @@
   reporter_->OnPaused();
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   // Advance a few recording intervals just to be sure.
   FastForward(kRecordingInterval * 3);
 
@@ -433,7 +445,7 @@
   reporter_->OnHidden();
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   // Advance a few recording intervals just to be sure.
   FastForward(kRecordingInterval * 3);
 
@@ -442,7 +454,7 @@
   // called to update offsets to ignore stats while hidden.
   EXPECT_CALL(*this, GetPipelineStatsCB());
   EXPECT_CALL(*interceptor_,
-              StartNewRecord(kDefaultProfile, kDefaultSize_, kDefaultFps));
+              MockStartNewRecord(kDefaultProfile, kDefaultSize_, kDefaultFps));
   reporter_->OnShown();
 
   // Update offsets for new record and verify updates resume as time advances.
@@ -475,7 +487,7 @@
   // Verify record updates stop while decode is not progressing. Fast forward
   // through several recording intervals to be sure we never call UpdateRecord.
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(3);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Resume progressing decode!
@@ -508,7 +520,7 @@
   // Next stats update will not cause a record update. We must first check
   // to see if the framerate changes and start a new record.
   EXPECT_CALL(*this, GetPipelineStatsCB());
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval);
 
   // A new record is started with the latest natural size as soon as the
@@ -547,7 +559,7 @@
   // Next stats update will not cause a record update. We must first check
   // to see if the framerate changes and start a new record.
   EXPECT_CALL(*this, GetPipelineStatsCB());
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval);
 
   // A new record is started with the latest configuration as soon as the
@@ -586,7 +598,7 @@
   // Next stats update will not cause a record update. It will instead begin
   // detection of the new framerate.
   EXPECT_CALL(*this, GetPipelineStatsCB());
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval);
 
   // A new record is started with the latest frames per second as soon as the
@@ -621,8 +633,8 @@
   EXPECT_CALL(*this, GetPipelineStatsCB());
 
   // We should not start nor update a record while failing to detect fps.
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
-  EXPECT_CALL(*interceptor_, StartNewRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval);
   int num_fps_samples = 1;
 
@@ -719,7 +731,7 @@
   // Verify no further stats updates are made because we've hit the maximum
   // number of tiny framerate windows.
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval);
 
   // Pausing then playing does not kickstart reporting. We assume framerate is
@@ -802,7 +814,7 @@
   // calls to UpdateRecord because decode progress is still frozen. Fast forward
   // through several recording intervals to be sure nothing changes.
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(3);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Un-freeze decode stats!
@@ -847,7 +859,7 @@
   reporter_->OnHidden();
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Config changes may still arrive when hidden and should not be dropped.
@@ -897,7 +909,7 @@
   reporter_->OnPaused();
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Config changes are still possible when paused (e.g. user seeks to a new
@@ -910,7 +922,7 @@
   // Playback is still paused, so reporting should be stopped.
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Upon playing, expect the new config to re-trigger framerate detection and
@@ -948,13 +960,13 @@
 
   // Small changes to framerate should not trigger a new record.
   pipeline_framerate_ = kDefaultFps + .5;
-  EXPECT_CALL(*interceptor_, StartNewRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _)).Times(0);
   AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
                                    decoded_power_efficient_offset);
 
   // Small changes in the other direction should also not trigger a new record.
   pipeline_framerate_ = kDefaultFps - .5;
-  EXPECT_CALL(*interceptor_, StartNewRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _)).Times(0);
   AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
                                    decoded_power_efficient_offset);
 
@@ -1022,7 +1034,7 @@
   // Using the same bucket means we expect it continues to use the same record.
   // Verify recording progresses as if size were unchanged.
   reporter_->OnNaturalSizeChanged(slightly_smaller_size);
-  EXPECT_CALL(*interceptor_, StartNewRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _)).Times(0);
   AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
                                    decoded_power_efficient_offset);
 
@@ -1057,7 +1069,7 @@
                                    slightly_larger_size.height() + 1);
   EXPECT_EQ(larger_size_bucket, GetSizeBucket(slightly_larger_size));
   reporter_->OnNaturalSizeChanged(slightly_larger_size);
-  EXPECT_CALL(*interceptor_, StartNewRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockStartNewRecord(_, _, _)).Times(0);
   AdvanceTimeAndVerifyRecordUpdate(decoded_offset, dropped_offset,
                                    decoded_power_efficient_offset);
 
@@ -1106,7 +1118,7 @@
   // tiny size is in effect.
   EXPECT_FALSE(ShouldBeReporting());
   EXPECT_CALL(*this, GetPipelineStatsCB()).Times(0);
-  EXPECT_CALL(*interceptor_, UpdateRecord(_, _, _)).Times(0);
+  EXPECT_CALL(*interceptor_, MockUpdateRecord(_, _, _)).Times(0);
   FastForward(kRecordingInterval * 3);
 
   // Change the size to something small, but reasonable.
diff --git a/media/blink/webmediacapabilitiesclient_impl.cc b/media/blink/webmediacapabilitiesclient_impl.cc
index e756c07..3a71b878 100644
--- a/media/blink/webmediacapabilitiesclient_impl.cc
+++ b/media/blink/webmediacapabilitiesclient_impl.cc
@@ -14,6 +14,7 @@
 #include "media/base/video_codecs.h"
 #include "media/base/video_color_space.h"
 #include "media/filters/stream_parser_factory.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h"
@@ -202,9 +203,12 @@
     BindToHistoryService(&decode_history_ptr_);
   DCHECK(decode_history_ptr_.is_bound());
 
-  decode_history_ptr_->GetPerfInfo(
+  mojom::PredictionFeaturesPtr features = mojom::PredictionFeatures::New(
       video_profile, gfx::Size(video_config.width, video_config.height),
-      video_config.framerate,
+      video_config.framerate);
+
+  decode_history_ptr_->GetPerfInfo(
+      std::move(features),
       base::BindOnce(&VideoPerfInfoCallback, std::move(callbacks),
                      std::move(info)));
 }
diff --git a/media/media_options.gni b/media/media_options.gni
index abe51f9..3ea9aa20 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -97,7 +97,7 @@
 
   # Alsa should be used on non-Android, non-Mac POSIX systems.
   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
-  if (is_posix && !is_android && !is_mac && !is_fuchsia &&
+  if (is_posix && !is_android && !is_mac &&
       (!is_chromecast || is_cast_desktop_build || is_cast_audio_only)) {
     use_alsa = true
 
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom
index f7ea910..4231856 100644
--- a/media/mojo/interfaces/media_types.mojom
+++ b/media/mojo/interfaces/media_types.mojom
@@ -282,3 +282,22 @@
   int64 audio_memory_usage;
   int64 video_memory_usage;
 };
+
+// Set of features for MediaCapabilities prediction.
+// TODO(liberato): consider generalizing this.
+struct PredictionFeatures {
+    // It would be nice to initialize this to VIDEO_CODEC_PROFILE_UNKNOWN (-1),
+    // but we can't do that with native enums.
+    VideoCodecProfile profile;
+    gfx.mojom.Size video_size;
+    int32 frames_per_sec = 0;
+};
+
+// Target values for MediaCapabilities predictions.
+// TODO(liberato): consider generalizing this.
+struct PredictionTargets {
+  uint32 frames_decoded = 0;
+  uint32 frames_dropped = 0;
+  uint32 frames_decoded_power_efficient = 0;
+};
+
diff --git a/media/mojo/interfaces/video_decode_perf_history.mojom b/media/mojo/interfaces/video_decode_perf_history.mojom
index 9ee5747..7dffaaf4 100644
--- a/media/mojo/interfaces/video_decode_perf_history.mojom
+++ b/media/mojo/interfaces/video_decode_perf_history.mojom
@@ -12,6 +12,7 @@
 interface VideoDecodePerfHistory {
   // Parameters describe the stream characteristics for which we will return
   // performance info.
-  GetPerfInfo(VideoCodecProfile profile, gfx.mojom.Size video_size,
-              int32 frames_per_sec) => (bool is_smooth, bool is_power_efficient);
-};
\ No newline at end of file
+  // TODO(liberato): Consider making this return PredictionTargets, and move the
+  // conversion to bool higher in the stack.
+  GetPerfInfo(PredictionFeatures features) => (bool is_smooth, bool is_power_efficient);
+};
diff --git a/media/mojo/interfaces/video_decode_stats_recorder.mojom b/media/mojo/interfaces/video_decode_stats_recorder.mojom
index bbb61c0f..cfdb876 100644
--- a/media/mojo/interfaces/video_decode_stats_recorder.mojom
+++ b/media/mojo/interfaces/video_decode_stats_recorder.mojom
@@ -13,13 +13,10 @@
 interface VideoDecodeStatsRecorder {
   // Will finalize any ongoing record and begin a new record with the given
   // properties.
-  StartNewRecord(VideoCodecProfile profile, gfx.mojom.Size video_size,
-                 int32 frames_per_sec);
+  StartNewRecord(PredictionFeatures features);
 
   // Update stats values for the current record. Each update overrides the
   // previous values. Values should only be considered final when a new
   // record is started or upon IPC disconnect.
-  UpdateRecord(uint32 frames_decoded,
-               uint32 frames_dropped,
-               uint32 frames_decoded_power_efficient);
+  UpdateRecord(PredictionTargets targets);
 };
diff --git a/media/mojo/services/video_decode_perf_history.cc b/media/mojo/services/video_decode_perf_history.cc
index 390b572..f074b4e 100644
--- a/media/mojo/services/video_decode_perf_history.cc
+++ b/media/mojo/services/video_decode_perf_history.cc
@@ -66,16 +66,14 @@
   init_deferred_api_calls_.clear();
 }
 
-void VideoDecodePerfHistory::GetPerfInfo(VideoCodecProfile profile,
-                                         const gfx::Size& natural_size,
-                                         int frame_rate,
+void VideoDecodePerfHistory::GetPerfInfo(mojom::PredictionFeaturesPtr features,
                                          GetPerfInfoCallback got_info_cb) {
   DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  DCHECK_NE(profile, VIDEO_CODEC_PROFILE_UNKNOWN);
-  DCHECK_GT(frame_rate, 0);
-  DCHECK(natural_size.width() > 0 && natural_size.height() > 0);
+  DCHECK_NE(features->profile, VIDEO_CODEC_PROFILE_UNKNOWN);
+  DCHECK_GT(features->frames_per_sec, 0);
+  DCHECK(features->video_size.width() > 0 && features->video_size.height() > 0);
 
   if (db_init_status_ == FAILED) {
     // Optimistically claim perf is both smooth and power efficient.
@@ -87,14 +85,14 @@
   if (db_init_status_ != COMPLETE) {
     init_deferred_api_calls_.push_back(base::BindOnce(
         &VideoDecodePerfHistory::GetPerfInfo, weak_ptr_factory_.GetWeakPtr(),
-        profile, natural_size, frame_rate, std::move(got_info_cb)));
+        std::move(features), std::move(got_info_cb)));
     InitDatabase();
     return;
   }
 
   VideoDecodeStatsDB::VideoDescKey video_key =
-      VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(profile, natural_size,
-                                                        frame_rate);
+      VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(
+          features->profile, features->video_size, features->frames_per_sec);
 
   db_->GetDecodeStats(
       video_key, base::BindOnce(&VideoDecodePerfHistory::OnGotStatsForRequest,
@@ -174,21 +172,18 @@
 void VideoDecodePerfHistory::SavePerfRecord(
     const url::Origin& untrusted_top_frame_origin,
     bool is_top_frame,
-    VideoCodecProfile profile,
-    const gfx::Size& natural_size,
-    int frame_rate,
-    uint32_t frames_decoded,
-    uint32_t frames_dropped,
-    uint32_t frames_decoded_power_efficient,
+    mojom::PredictionFeatures features,
+    mojom::PredictionTargets targets,
     uint64_t player_id,
     base::OnceClosure save_done_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(3) << __func__
            << base::StringPrintf(
                   " profile:%s size:%s fps:%d decoded:%d dropped:%d",
-                  GetProfileName(profile).c_str(),
-                  natural_size.ToString().c_str(), frame_rate, frames_decoded,
-                  frames_dropped);
+                  GetProfileName(features.profile).c_str(),
+                  features.video_size.ToString().c_str(),
+                  features.frames_per_sec, targets.frames_decoded,
+                  targets.frames_dropped);
 
   if (db_init_status_ == FAILED) {
     DVLOG(3) << __func__ << " Can't save stats. No DB!";
@@ -199,18 +194,18 @@
   if (db_init_status_ != COMPLETE) {
     init_deferred_api_calls_.push_back(base::BindOnce(
         &VideoDecodePerfHistory::SavePerfRecord, weak_ptr_factory_.GetWeakPtr(),
-        untrusted_top_frame_origin, is_top_frame, profile, natural_size,
-        frame_rate, frames_decoded, frames_dropped,
-        frames_decoded_power_efficient, player_id, std::move(save_done_cb)));
+        untrusted_top_frame_origin, is_top_frame, std::move(features),
+        std::move(targets), player_id, std::move(save_done_cb)));
     InitDatabase();
     return;
   }
 
   VideoDecodeStatsDB::VideoDescKey video_key =
-      VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(profile, natural_size,
-                                                        frame_rate);
+      VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(
+          features.profile, features.video_size, features.frames_per_sec);
   VideoDecodeStatsDB::DecodeStatsEntry new_stats(
-      frames_decoded, frames_dropped, frames_decoded_power_efficient);
+      targets.frames_decoded, targets.frames_dropped,
+      targets.frames_decoded_power_efficient);
 
   // Get past perf info and report UKM metrics before saving this record.
   db_->GetDecodeStats(
diff --git a/media/mojo/services/video_decode_perf_history.h b/media/mojo/services/video_decode_perf_history.h
index f9ec32df..8fe4f9e 100644
--- a/media/mojo/services/video_decode_perf_history.h
+++ b/media/mojo/services/video_decode_perf_history.h
@@ -56,9 +56,7 @@
   void BindRequest(mojom::VideoDecodePerfHistoryRequest request);
 
   // mojom::VideoDecodePerfHistory implementation:
-  void GetPerfInfo(VideoCodecProfile profile,
-                   const gfx::Size& natural_size,
-                   int frame_rate,
+  void GetPerfInfo(mojom::PredictionFeaturesPtr features,
                    GetPerfInfoCallback got_info_cb) override;
 
   // Save a record of the given performance stats for the described stream.
@@ -66,12 +64,8 @@
   // for tests to know the save is complete.
   void SavePerfRecord(const url::Origin& untrusted_top_frame_origin,
                       bool is_top_frame,
-                      VideoCodecProfile profile,
-                      const gfx::Size& natural_size,
-                      int frame_rate,
-                      uint32_t frames_decoded,
-                      uint32_t frames_dropped,
-                      uint32_t frames_decoded_power_efficient,
+                      mojom::PredictionFeatures features,
+                      mojom::PredictionTargets targets,
                       uint64_t player_id,
                       base::OnceClosure save_done_cb = base::OnceClosure());
 
diff --git a/media/mojo/services/video_decode_perf_history_unittest.cc b/media/mojo/services/video_decode_perf_history_unittest.cc
index ffa6eb0e..fa36b55 100644
--- a/media/mojo/services/video_decode_perf_history_unittest.cc
+++ b/media/mojo/services/video_decode_perf_history_unittest.cc
@@ -158,6 +158,35 @@
   // the operation has completed. See CompleteDBInitOnClearedHistory().
   MOCK_METHOD0(MockOnClearedHistory, void());
 
+  mojom::PredictionFeatures MakeFeatures(VideoCodecProfile profile,
+                                         gfx::Size video_size,
+                                         int frames_per_sec) {
+    mojom::PredictionFeatures features;
+    features.profile = profile;
+    features.video_size = video_size;
+    features.frames_per_sec = frames_per_sec;
+    return features;
+  }
+
+  mojom::PredictionFeaturesPtr MakeFeaturesPtr(VideoCodecProfile profile,
+                                               gfx::Size video_size,
+                                               int frames_per_sec) {
+    mojom::PredictionFeaturesPtr features = mojom::PredictionFeatures::New();
+    *features = MakeFeatures(profile, video_size, frames_per_sec);
+    return features;
+  }
+
+  mojom::PredictionTargets MakeTargets(
+      uint32_t frames_decoded,
+      uint32_t frames_dropped,
+      uint32_t frames_decoded_power_efficient) {
+    mojom::PredictionTargets targets;
+    targets.frames_decoded = frames_decoded;
+    targets.frames_dropped = frames_dropped;
+    targets.frames_decoded_power_efficient = frames_decoded_power_efficient;
+    return targets;
+  }
+
  protected:
   using VideoDescKey = VideoDecodeStatsDB::VideoDescKey;
   using DecodeStatsEntry = VideoDecodeStatsDB::DecodeStatsEntry;
@@ -209,26 +238,30 @@
       kFramesDecoded * kMaxSmoothDroppedFramesPercent + 1;
 
   // Add the entries.
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kKnownProfile, kKownSize,
-                                kSmoothFrameRate, kFramesDecoded,
-                                kSmoothFramesDropped,
-                                kNotPowerEfficientFramesDecoded, kPlayerId);
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kKnownProfile, kKownSize,
-                                kNotSmoothFrameRate, kFramesDecoded,
-                                kNotSmoothFramesDropped,
-                                kNotPowerEfficientFramesDecoded, kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame,
+      MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRate),
+      MakeTargets(kFramesDecoded, kSmoothFramesDropped,
+                  kNotPowerEfficientFramesDecoded),
+      kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame,
+      MakeFeatures(kKnownProfile, kKownSize, kNotSmoothFrameRate),
+      MakeTargets(kFramesDecoded, kNotSmoothFramesDropped,
+                  kNotPowerEfficientFramesDecoded),
+      kPlayerId);
 
   // Verify perf history returns is_smooth = true for the smooth entry.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
   perf_history_->GetPerfInfo(
-      kKnownProfile, kKownSize, kSmoothFrameRate,
+      MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
   // Verify perf history returns is_smooth = false for the NOT smooth entry.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient));
   perf_history_->GetPerfInfo(
-      kKnownProfile, kKownSize, kNotSmoothFrameRate,
+      MakeFeaturesPtr(kKnownProfile, kKownSize, kNotSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -237,7 +270,7 @@
   const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kUnknownProfile, kKownSize, kNotSmoothFrameRate,
+      MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -285,37 +318,43 @@
       kFramesDecoded * kMaxSmoothDroppedFramesPercent + 1;
 
   // Add the entries.
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kPowerEfficientProfile,
-                                kKownSize, kSmoothFrameRate, kFramesDecoded,
-                                kSmoothFramesDropped,
-                                kPowerEfficientFramesDecoded, kPlayerId);
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kNotPowerEfficientProfile,
-                                kKownSize, kSmoothFrameRate, kFramesDecoded,
-                                kSmoothFramesDropped,
-                                kNotPowerEfficientFramesDecoded, kPlayerId);
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kPowerEfficientProfile,
-                                kKownSize, kNotSmoothFrameRate, kFramesDecoded,
-                                kNotSmoothFramesDropped,
-                                kPowerEfficientFramesDecoded, kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame,
+      MakeFeatures(kPowerEfficientProfile, kKownSize, kSmoothFrameRate),
+      MakeTargets(kFramesDecoded, kSmoothFramesDropped,
+                  kPowerEfficientFramesDecoded),
+      kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame,
+      MakeFeatures(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate),
+      MakeTargets(kFramesDecoded, kSmoothFramesDropped,
+                  kNotPowerEfficientFramesDecoded),
+      kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame,
+      MakeFeatures(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate),
+      MakeTargets(kFramesDecoded, kNotSmoothFramesDropped,
+                  kPowerEfficientFramesDecoded),
+      kPlayerId);
 
   // Verify perf history returns is_smooth = true, is_power_efficient = true.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kPowerEfficientProfile, kKownSize, kSmoothFrameRate,
+      MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
   // Verify perf history returns is_smooth = true, is_power_efficient = false.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
   perf_history_->GetPerfInfo(
-      kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate,
+      MakeFeaturesPtr(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
   // Verify perf history returns is_smooth = false, is_power_efficient = true.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate,
+      MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -325,7 +364,7 @@
   const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kUnknownProfile, kKownSize, kNotSmoothFrameRate,
+      MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -354,7 +393,7 @@
   // and power efficient performance.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kProfile, kSize, kFrameRate,
+      MakeFeaturesPtr(kProfile, kSize, kFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -387,14 +426,15 @@
   const int kFramesDecoded = 1000;
   const int kManyFramesDropped = kFramesDecoded / 2;
   const int kFramesPowerEfficient = kFramesDecoded;
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kProfile, kSize,
-                                kFrameRate, kFramesDecoded, kManyFramesDropped,
-                                kFramesPowerEfficient, kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame, MakeFeatures(kProfile, kSize, kFrameRate),
+      MakeTargets(kFramesDecoded, kManyFramesDropped, kFramesPowerEfficient),
+      kPlayerId);
 
   // Verify its there before we ClearHistory(). Note that perf is NOT smooth.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kProfile, kSize, kFrameRate,
+      MakeFeaturesPtr(kProfile, kSize, kFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -410,7 +450,7 @@
   // "smooth" when it claimed NOT smooth just moments before.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kProfile, kSize, kFrameRate,
+      MakeFeaturesPtr(kProfile, kSize, kFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
@@ -469,15 +509,16 @@
 
   // With DB reinitialization still pending, save a record that indicates
   // NOT smooth performance.
-  perf_history_->SavePerfRecord(kOrigin, kIsTopFrame, kProfile, kSize,
-                                kFrameRate, kFramesDecoded, kManyFramesDropped,
-                                kFramesPowerEfficient, kPlayerId);
+  perf_history_->SavePerfRecord(
+      kOrigin, kIsTopFrame, MakeFeatures(kProfile, kSize, kFrameRate),
+      MakeTargets(kFramesDecoded, kManyFramesDropped, kFramesPowerEfficient),
+      kPlayerId);
 
   // Expect that NOT smooth is eventually reported (after DB reinitialization
   // completes) when we query this stream description.
   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
-      kProfile, kSize, kFrameRate,
+      MakeFeaturesPtr(kProfile, kSize, kFrameRate),
       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
diff --git a/media/mojo/services/video_decode_stats_recorder.cc b/media/mojo/services/video_decode_stats_recorder.cc
index a62b990..f6866c0a 100644
--- a/media/mojo/services/video_decode_stats_recorder.cc
+++ b/media/mojo/services/video_decode_stats_recorder.cc
@@ -31,62 +31,57 @@
   FinalizeRecord();
 }
 
-void VideoDecodeStatsRecorder::StartNewRecord(VideoCodecProfile profile,
-                                              const gfx::Size& natural_size,
-                                              int frames_per_sec) {
-  DCHECK_NE(profile, VIDEO_CODEC_PROFILE_UNKNOWN);
-  DCHECK_GT(frames_per_sec, 0);
-  DCHECK(natural_size.width() > 0 && natural_size.height() > 0);
+void VideoDecodeStatsRecorder::StartNewRecord(
+    mojom::PredictionFeaturesPtr features) {
+  DCHECK_NE(features->profile, VIDEO_CODEC_PROFILE_UNKNOWN);
+  DCHECK_GT(features->frames_per_sec, 0);
+  DCHECK(features->video_size.width() > 0 && features->video_size.height() > 0);
 
+  features_ = *features;
   FinalizeRecord();
 
-  DVLOG(2) << __func__ << "profile: " << profile
-           << " sz:" << natural_size.ToString() << " fps:" << frames_per_sec;
+  DVLOG(2) << __func__ << "profile: " << features_.profile
+           << " sz:" << features_.video_size.ToString()
+           << " fps:" << features_.frames_per_sec;
 
-  profile_ = profile;
-  natural_size_ = natural_size;
-  frames_per_sec_ = frames_per_sec;
-  frames_decoded_ = 0;
-  frames_dropped_ = 0;
-  frames_decoded_power_efficient_ = 0;
+  // Reinitialize to defaults.
+  targets_ = mojom::PredictionTargets();
 }
 
 void VideoDecodeStatsRecorder::UpdateRecord(
-    uint32_t frames_decoded,
-    uint32_t frames_dropped,
-    uint32_t frames_decoded_power_efficient) {
-  DVLOG(3) << __func__ << " decoded:" << frames_decoded
-           << " dropped:" << frames_dropped;
+    mojom::PredictionTargetsPtr targets) {
+  DVLOG(3) << __func__ << " decoded:" << targets->frames_decoded
+           << " dropped:" << targets->frames_dropped;
 
   // Dropped can never exceed decoded.
-  DCHECK_LE(frames_dropped, frames_decoded);
+  DCHECK_LE(targets->frames_dropped, targets->frames_decoded);
   // Power efficient frames can never exceed decoded frames.
-  DCHECK_LE(frames_decoded_power_efficient, frames_decoded);
+  DCHECK_LE(targets->frames_decoded_power_efficient, targets->frames_decoded);
   // Should never go backwards.
-  DCHECK_GE(frames_decoded, frames_decoded_);
-  DCHECK_GE(frames_dropped, frames_dropped_);
-  DCHECK_GE(frames_decoded_power_efficient, frames_decoded_power_efficient_);
+  DCHECK_GE(targets->frames_decoded, targets_.frames_decoded);
+  DCHECK_GE(targets->frames_dropped, targets_.frames_dropped);
+  DCHECK_GE(targets->frames_decoded_power_efficient,
+            targets_.frames_decoded_power_efficient);
 
-  frames_decoded_ = frames_decoded;
-  frames_dropped_ = frames_dropped;
-  frames_decoded_power_efficient_ = frames_decoded_power_efficient;
+  targets_ = *targets;
 }
 
 void VideoDecodeStatsRecorder::FinalizeRecord() {
-  if (profile_ == VIDEO_CODEC_PROFILE_UNKNOWN || frames_decoded_ == 0 ||
-      !perf_history_) {
+  if (features_.profile == VIDEO_CODEC_PROFILE_UNKNOWN ||
+      targets_.frames_decoded == 0 || !perf_history_) {
     return;
   }
 
-  DVLOG(2) << __func__ << " profile: " << profile_
-           << " size:" << natural_size_.ToString() << " fps:" << frames_per_sec_
-           << " decoded:" << frames_decoded_ << " dropped:" << frames_dropped_
-           << " power efficient decoded:" << frames_decoded_power_efficient_;
+  DVLOG(2) << __func__ << " profile: " << features_.profile
+           << " size:" << features_.video_size.ToString()
+           << " fps:" << features_.frames_per_sec
+           << " decoded:" << targets_.frames_decoded
+           << " dropped:" << targets_.frames_dropped
+           << " power efficient decoded:"
+           << targets_.frames_decoded_power_efficient;
 
   perf_history_->SavePerfRecord(untrusted_top_frame_origin_, is_top_frame_,
-                                profile_, natural_size_, frames_per_sec_,
-                                frames_decoded_, frames_dropped_,
-                                frames_decoded_power_efficient_, player_id_);
+                                features_, targets_, player_id_);
 }
 
 }  // namespace media
diff --git a/media/mojo/services/video_decode_stats_recorder.h b/media/mojo/services/video_decode_stats_recorder.h
index bb45c00..8445aed 100644
--- a/media/mojo/services/video_decode_stats_recorder.h
+++ b/media/mojo/services/video_decode_stats_recorder.h
@@ -33,12 +33,8 @@
   ~VideoDecodeStatsRecorder() override;
 
   // mojom::VideoDecodeStatsRecorder implementation:
-  void StartNewRecord(VideoCodecProfile profile,
-                      const gfx::Size& natural_size,
-                      int frames_per_sec) override;
-  void UpdateRecord(uint32_t frames_decoded,
-                    uint32_t frames_dropped,
-                    uint32_t frames_decoded_power_efficient) override;
+  void StartNewRecord(mojom::PredictionFeaturesPtr features) override;
+  void UpdateRecord(mojom::PredictionTargetsPtr targets) override;
 
  private:
   // Save most recent stats values to disk. Called during destruction and upon
@@ -50,12 +46,8 @@
   VideoDecodePerfHistory* const perf_history_;
   const uint64_t player_id_;
 
-  VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
-  gfx::Size natural_size_;
-  int frames_per_sec_ = 0;
-  uint32_t frames_decoded_ = 0;
-  uint32_t frames_dropped_ = 0;
-  uint32_t frames_decoded_power_efficient_ = 0;
+  mojom::PredictionFeatures features_;
+  mojom::PredictionTargets targets_;
 
   DISALLOW_COPY_AND_ASSIGN(VideoDecodeStatsRecorder);
 };
diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn
index 3528cb32..7cf4f13a 100644
--- a/mojo/edk/embedder/BUILD.gn
+++ b/mojo/edk/embedder/BUILD.gn
@@ -13,7 +13,7 @@
     "platform_shared_buffer_unittest.cc",
   ]
 
-  if (is_posix && !is_fuchsia) {
+  if (is_posix) {
     sources += [ "platform_channel_pair_posix_unittest.cc" ]
   }
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 1707fb53..7521d6b 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -37,8 +37,8 @@
 use_v8_in_net = !is_ios && !is_proto_quic
 enable_built_in_dns = !is_ios && !is_proto_quic
 
-# Unix sockets are not supported on iOS, Fuchsia or NaCl.
-enable_unix_sockets = is_posix && !is_ios && !is_fuchsia && !is_nacl
+# Unix sockets are not supported on iOS or NaCl.
+enable_unix_sockets = is_posix && !is_ios && !is_nacl
 
 # Android and Fuchsia can't run testserver.py directly, so they use remote
 # test server.
@@ -471,8 +471,6 @@
       "base/network_delegate.h",
       "base/network_delegate_impl.cc",
       "base/network_delegate_impl.h",
-      "base/network_interfaces_getifaddrs.cc",
-      "base/network_interfaces_getifaddrs.h",
       "base/network_interfaces_linux.cc",
       "base/network_interfaces_linux.h",
       "base/network_interfaces_nacl.cc",
@@ -1860,7 +1858,7 @@
       ]
     }
 
-    if (is_posix) {
+    if (is_posix || is_fuchsia) {
       if (posix_avoid_mmap) {
         sources -= [ "disk_cache/blockfile/mapped_file_posix.cc" ]
       } else {
@@ -1905,8 +1903,8 @@
     }
 
     # Use getifaddrs() on POSIX platforms, except Linux and Android.
-    if (!is_posix || is_linux || is_android || is_fuchsia) {
-      sources -= [
+    if (is_posix && !is_linux && !is_android) {
+      sources += [
         "base/network_interfaces_getifaddrs.cc",
         "base/network_interfaces_getifaddrs.h",
       ]
@@ -4722,7 +4720,6 @@
     "base/network_activity_monitor_unittest.cc",
     "base/network_change_notifier_unittest.cc",
     "base/network_change_notifier_win_unittest.cc",
-    "base/network_interfaces_getifaddrs_unittest.cc",
     "base/network_interfaces_linux_unittest.cc",
     "base/network_interfaces_unittest.cc",
     "base/network_interfaces_win_unittest.cc",
@@ -5657,9 +5654,9 @@
     ]
   }
 
-  # Use getifaddrs() on POSIX platforms, except Linux, Android and Fuchsia.
-  if (!is_posix || is_linux || is_android || is_fuchsia) {
-    sources -= [ "base/network_interfaces_getifaddrs_unittest.cc" ]
+  # Use getifaddrs() on POSIX platforms, except Linux and Android.
+  if (is_posix && !is_linux && !is_android) {
+    sources += [ "base/network_interfaces_getifaddrs_unittest.cc" ]
   }
 
   # Unit tests that aren't supported by the current ICU alternatives on Android.
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc
index bbbb3a2..dd866a9 100644
--- a/net/cert/multi_threaded_cert_verifier.cc
+++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -12,6 +12,7 @@
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/containers/linked_list.h"
+#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sha1.h"
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 04c050bf..97d25ef 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -148,21 +148,25 @@
   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 }
 
-TEST(CanonicalCookieTest, CreateInvalidSameSite) {
+TEST(CanonicalCookieTest, CreateNonStandardSameSite) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
   std::unique_ptr<CanonicalCookie> cookie;
   CookieOptions options;
 
-  // Invalid 'SameSite' attribute values.
   options.set_same_site_cookie_mode(
       CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
 
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Invalid", now, options);
-  EXPECT_EQ(nullptr, cookie.get());
+  // Non-standard value for the SameSite attribute.
+  cookie =
+      CanonicalCookie::Create(url, "A=2; SameSite=NonStandard", now, options);
+  EXPECT_TRUE(cookie.get());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 
+  // Omit value for the SameSite attribute.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, options);
-  EXPECT_EQ(nullptr, cookie.get());
+  EXPECT_TRUE(cookie.get());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 }
 
 TEST(CanonicalCookieTest, CreateInvalidHttpOnly) {
diff --git a/net/cookies/cookie_constants.h b/net/cookies/cookie_constants.h
index 61e1c0a0..3f5b3cf 100644
--- a/net/cookies/cookie_constants.h
+++ b/net/cookies/cookie_constants.h
@@ -37,7 +37,7 @@
 // Defaults to COOKIE_PRIORITY_DEFAULT for empty or unrecognized strings.
 NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority);
 
-// Converst the Set-Cookie header SameSite token |same_site| to a
+// Converts the Set-Cookie header SameSite token |same_site| to a
 // CookieSameSite. Defaults to CookieSameSite::DEFAULT_MODE for empty or
 // unrecognized strings.
 NET_EXPORT CookieSameSite StringToCookieSameSite(const std::string& same_site);
diff --git a/net/cookies/parsed_cookie.cc b/net/cookies/parsed_cookie.cc
index 1be10ee..450e869e 100644
--- a/net/cookies/parsed_cookie.cc
+++ b/net/cookies/parsed_cookie.cc
@@ -150,7 +150,7 @@
 ParsedCookie::~ParsedCookie() = default;
 
 bool ParsedCookie::IsValid() const {
-  return !pairs_.empty() && IsSameSiteAttributeValid();
+  return !pairs_.empty();
 }
 
 CookieSameSite ParsedCookie::SameSite() const {
@@ -501,8 +501,4 @@
   pairs_.erase(pairs_.begin() + index);
 }
 
-bool ParsedCookie::IsSameSiteAttributeValid() const {
-  return same_site_index_ == 0 || SameSite() != CookieSameSite::DEFAULT_MODE;
-}
-
 }  // namespace net
diff --git a/net/cookies/parsed_cookie.h b/net/cookies/parsed_cookie.h
index 8bc5e99..d6b951a 100644
--- a/net/cookies/parsed_cookie.h
+++ b/net/cookies/parsed_cookie.h
@@ -131,10 +131,6 @@
   // |index| refers to a position in |pairs_|.
   void ClearAttributePair(size_t index);
 
-  // Returns false if a 'SameSite' attribute is present, but has an unrecognized
-  // value. In particular, this includes attributes with empty values.
-  bool IsSameSiteAttributeValid() const;
-
   PairList pairs_;
   // These will default to 0, but that should never be valid since the
   // 0th index is the user supplied token/value, not an attribute.
diff --git a/net/cookies/parsed_cookie_unittest.cc b/net/cookies/parsed_cookie_unittest.cc
index e1e3f9b..fc7d206 100644
--- a/net/cookies/parsed_cookie_unittest.cc
+++ b/net/cookies/parsed_cookie_unittest.cc
@@ -467,7 +467,7 @@
   EXPECT_EQ("name=value", pc.ToCookieLine());
   EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
 
-  // Test each priority, expect case-insensitive compare.
+  // Test each samesite directive, expect case-insensitive compare.
   EXPECT_TRUE(pc.SetSameSite("strict"));
   EXPECT_EQ("name=value; samesite=strict", pc.ToCookieLine());
   EXPECT_EQ(CookieSameSite::STRICT_MODE, pc.SameSite());
@@ -483,24 +483,28 @@
   EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
   EXPECT_TRUE(pc.IsValid());
 
+  // Remove the SameSite attribute.
   EXPECT_TRUE(pc.SetSameSite(""));
   EXPECT_EQ("name=value", pc.ToCookieLine());
   EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
   EXPECT_TRUE(pc.IsValid());
 
   EXPECT_TRUE(pc.SetSameSite("Blah"));
-  EXPECT_FALSE(pc.IsValid());
+  EXPECT_EQ("name=value; samesite=Blah", pc.ToCookieLine());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, pc.SameSite());
+  EXPECT_TRUE(pc.IsValid());
 }
 
-TEST(ParsedCookieTest, InvalidSameSiteValue) {
+TEST(ParsedCookieTest, SameSiteValues) {
   struct TestCase {
     const char* cookie;
     bool valid;
     CookieSameSite mode;
   } cases[]{{"n=v; samesite=strict", true, CookieSameSite::STRICT_MODE},
             {"n=v; samesite=lax", true, CookieSameSite::LAX_MODE},
-            {"n=v; samesite=boo", false, CookieSameSite::DEFAULT_MODE},
-            {"n=v; samesite", false, CookieSameSite::DEFAULT_MODE}};
+            {"n=v; samesite=boo", true, CookieSameSite::NO_RESTRICTION},
+            {"n=v; samesite", true, CookieSameSite::NO_RESTRICTION},
+            {"n=v", true, CookieSameSite::DEFAULT_MODE}};
 
   for (const auto& test : cases) {
     SCOPED_TRACE(test.cookie);
diff --git a/net/dns/mojo_host_struct_traits.cc b/net/dns/mojo_host_struct_traits.cc
index 27332de..07f7a3a 100644
--- a/net/dns/mojo_host_struct_traits.cc
+++ b/net/dns/mojo_host_struct_traits.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "net/base/address_list.h"
 #include "net/interfaces/address_family_mojom_traits.h"
 
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc
index 82f508e..285e674f 100644
--- a/net/network_error_logging/network_error_logging_service.cc
+++ b/net/network_error_logging/network_error_logging_service.cc
@@ -10,7 +10,6 @@
 
 #include "base/json/json_reader.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
 #include "base/time/default_tick_clock.h"
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc
index 1b6027f..af38931 100644
--- a/net/socket/udp_socket_unittest.cc
+++ b/net/socket/udp_socket_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/containers/circular_deque.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/ssl/ssl_client_session_cache_unittest.cc b/net/ssl/ssl_client_session_cache_unittest.cc
index 461fb18..174c5744 100644
--- a/net/ssl/ssl_client_session_cache_unittest.cc
+++ b/net/ssl/ssl_client_session_cache_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "net/ssl/ssl_client_session_cache.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/simple_test_clock.h"
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index f7b559d..45640d69 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -144,8 +144,8 @@
   SSLConfigService* ssl_config_service() const {
     return ssl_config_service_.get();
   }
-  void set_ssl_config_service(SSLConfigService* service) {
-    ssl_config_service_ = service;
+  void set_ssl_config_service(scoped_refptr<SSLConfigService> service) {
+    ssl_config_service_ = std::move(service);
   }
 
   // Gets the HTTP Authentication Handler Factory for this context.
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index c975edc..dcd957b5 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -126,7 +126,7 @@
   }
 
   bool OnCanSetCookie(const URLRequest& request,
-                      const net::CanonicalCookie& cookie,
+                      const CanonicalCookie& cookie,
                       CookieOptions* options) override {
     return true;
   }
@@ -299,7 +299,7 @@
 
 #if BUILDFLAG(ENABLE_REPORTING)
 void URLRequestContextBuilder::set_reporting_policy(
-    std::unique_ptr<net::ReportingPolicy> reporting_policy) {
+    std::unique_ptr<ReportingPolicy> reporting_policy) {
   reporting_policy_ = std::move(reporting_policy);
 }
 #endif  // BUILDFLAG(ENABLE_REPORTING)
@@ -427,7 +427,7 @@
   if (ssl_config_service_) {
     // This takes a raw pointer, but |storage| will hold onto a reference to the
     // service.
-    storage->set_ssl_config_service(ssl_config_service_.get());
+    storage->set_ssl_config_service(ssl_config_service_);
   } else {
     storage->set_ssl_config_service(new SSLConfigServiceDefaults);
   }
@@ -613,13 +613,13 @@
   }
 #endif  // !BUILDFLAG(DISABLE_FTP_SUPPORT)
 
-  std::unique_ptr<net::URLRequestJobFactory> top_job_factory(job_factory);
+  std::unique_ptr<URLRequestJobFactory> top_job_factory(job_factory);
   if (!url_request_interceptors_.empty()) {
     // Set up interceptors in the reverse order.
 
     for (auto i = url_request_interceptors_.rbegin();
          i != url_request_interceptors_.rend(); ++i) {
-      top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
+      top_job_factory.reset(new URLRequestInterceptingJobFactory(
           std::move(top_job_factory), std::move(*i)));
     }
     url_request_interceptors_.clear();
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 3a526cc8..eae0d24a 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -81,14 +81,14 @@
 class NET_EXPORT URLRequestContextBuilder {
  public:
   using CreateInterceptingJobFactory =
-      base::OnceCallback<std::unique_ptr<net::URLRequestJobFactory>(
-          std::unique_ptr<net::URLRequestJobFactory> inner_job_factory)>;
+      base::OnceCallback<std::unique_ptr<URLRequestJobFactory>(
+          std::unique_ptr<URLRequestJobFactory> inner_job_factory)>;
 
   // Creates an HttpNetworkTransactionFactory given an HttpNetworkSession. Does
   // not take ownership of the session.
   using CreateHttpTransactionFactoryCallback =
-      base::OnceCallback<std::unique_ptr<net::HttpTransactionFactory>(
-          net::HttpNetworkSession* session)>;
+      base::OnceCallback<std::unique_ptr<HttpTransactionFactory>(
+          HttpNetworkSession* session)>;
 
   struct NET_EXPORT HttpCacheParams {
     enum Type {
@@ -159,7 +159,7 @@
   // ProxyResolutionService::SanitizeUrlPolicy::SAFE. Ignored if
   // a ProxyResolutionService is set directly.
   void set_pac_sanitize_url_policy(
-      net::ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy) {
+      ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy) {
     pac_sanitize_url_policy_ = pac_sanitize_url_policy;
   }
 
@@ -173,7 +173,7 @@
   }
 
   void set_ssl_config_service(
-      scoped_refptr<net::SSLConfigService> ssl_config_service) {
+      scoped_refptr<SSLConfigService> ssl_config_service) {
     ssl_config_service_ = std::move(ssl_config_service);
   }
 
@@ -293,8 +293,7 @@
   void SetCertVerifier(std::unique_ptr<CertVerifier> cert_verifier);
 
 #if BUILDFLAG(ENABLE_REPORTING)
-  void set_reporting_policy(
-      std::unique_ptr<net::ReportingPolicy> reporting_policy);
+  void set_reporting_policy(std::unique_ptr<ReportingPolicy> reporting_policy);
 
   void set_network_error_logging_enabled(bool network_error_logging_enabled) {
     network_error_logging_enabled_ = network_error_logging_enabled;
@@ -383,13 +382,13 @@
   base::FilePath transport_security_persister_path_;
   NetLog* net_log_;
   std::unique_ptr<HostResolver> host_resolver_;
-  net::HostResolver* shared_host_resolver_;
+  HostResolver* shared_host_resolver_;
   std::unique_ptr<ChannelIDService> channel_id_service_;
   std::unique_ptr<ProxyConfigService> proxy_config_service_;
   bool pac_quick_check_enabled_;
   ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy_;
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
-  scoped_refptr<net::SSLConfigService> ssl_config_service_;
+  scoped_refptr<SSLConfigService> ssl_config_service_;
   std::unique_ptr<NetworkDelegate> network_delegate_;
   std::unique_ptr<ProxyDelegate> proxy_delegate_;
   ProxyDelegate* shared_proxy_delegate_;
@@ -400,7 +399,7 @@
   std::unique_ptr<CTVerifier> ct_verifier_;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_;
 #if BUILDFLAG(ENABLE_REPORTING)
-  std::unique_ptr<net::ReportingPolicy> reporting_policy_;
+  std::unique_ptr<ReportingPolicy> reporting_policy_;
   bool network_error_logging_enabled_;
 #endif  // BUILDFLAG(ENABLE_REPORTING)
   std::vector<std::unique_ptr<URLRequestInterceptor>> url_request_interceptors_;
diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc
index e337311..4915c8f 100644
--- a/net/url_request/url_request_context_storage.cc
+++ b/net/url_request/url_request_context_storage.cc
@@ -86,7 +86,7 @@
 }
 
 void URLRequestContextStorage::set_ssl_config_service(
-    SSLConfigService* ssl_config_service) {
+    scoped_refptr<SSLConfigService> ssl_config_service) {
   context_->set_ssl_config_service(ssl_config_service);
   ssl_config_service_ = ssl_config_service;
 }
diff --git a/net/url_request/url_request_context_storage.h b/net/url_request/url_request_context_storage.h
index 9975977..655c42d 100644
--- a/net/url_request/url_request_context_storage.h
+++ b/net/url_request/url_request_context_storage.h
@@ -65,7 +65,8 @@
   void set_network_delegate(std::unique_ptr<NetworkDelegate> network_delegate);
   void set_proxy_resolution_service(
       std::unique_ptr<ProxyResolutionService> proxy_resolution_service);
-  void set_ssl_config_service(SSLConfigService* ssl_config_service);
+  void set_ssl_config_service(
+      scoped_refptr<SSLConfigService> ssl_config_service);
   void set_http_server_properties(
       std::unique_ptr<HttpServerProperties> http_server_properties);
   void set_cookie_store(std::unique_ptr<CookieStore> cookie_store);
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm
index 20f85fc..917df59 100644
--- a/remoting/ios/app/remoting_view_controller.mm
+++ b/remoting/ios/app/remoting_view_controller.mm
@@ -219,8 +219,24 @@
   [super viewWillAppear:animated];
 
   // Just in case the view controller misses the host list state event before
-  // gthe listener is registered.
+  // the listener is registered.
   [self refreshContent];
+  _hostListService->RequestFetch();
+
+  [NSNotificationCenter.defaultCenter
+      addObserver:self
+         selector:@selector(applicationDidBecomeActive:)
+             name:UIApplicationDidBecomeActiveNotification
+           object:nil];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+  [super viewWillDisappear:animated];
+
+  [NSNotificationCenter.defaultCenter
+      removeObserver:self
+                name:UIApplicationDidBecomeActiveNotification
+              object:nil];
 }
 
 - (UIStatusBarStyle)preferredStatusBarStyle {
@@ -329,7 +345,11 @@
 
 - (void)refreshContent {
   if (_hostListService->state() == HostListService::State::FETCHING) {
-    if (![self isAnyRefreshControlRefreshing]) {
+    // We don't need to show the fetching view when host list is being fetched
+    // while the previous host list is already on screen. Refresh control will
+    // handle the user-triggered refresh, and we don't need to show anything if
+    // that's a background refresh (e.g. user just closed the session).
+    if (self.contentViewController != _collectionViewController) {
       self.contentViewController = _fetchingViewController;
     }
     return;
@@ -406,4 +426,8 @@
   }
 }
 
+- (void)applicationDidBecomeActive:(UIApplication*)application {
+  _hostListService->RequestFetch();
+}
+
 @end
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 3964e23..04717f4 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -717,6 +717,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -894,6 +900,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -1490,6 +1502,32 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "LMY47W",
+              "device_type": "sprout"
+            }
+          ],
+          "expiration": 14400
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -2680,6 +2718,50 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "NRD91N",
+              "device_type": "bullhead"
+            }
+          ],
+          "expiration": 10800,
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -3400,6 +3482,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -3588,6 +3676,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -4326,6 +4420,30 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "coho"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -5218,6 +5336,30 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "gce_x86"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 0eea7d5..85f46621 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -1458,6 +1458,48 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "KTU84P",
+              "device_type": "hammerhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -3057,6 +3099,48 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "KTU84P",
+              "device_type": "hammerhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -4569,6 +4653,49 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "KTU84Z",
+              "device_type": "flo"
+            }
+          ],
+          "expiration": 10800,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -6077,6 +6204,50 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "expiration": 10800,
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7540,6 +7711,50 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "LMY49B",
+              "device_type": "flo"
+            }
+          ],
+          "expiration": 10800,
+          "hard_timeout": 120,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -9071,6 +9286,49 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -10628,6 +10886,48 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -12249,6 +12549,49 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MRA58Z",
+              "device_type": "flo"
+            }
+          ],
+          "expiration": 10800,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index a29b2c5..3643d32 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -225,6 +225,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -623,6 +629,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 79ee386..df4b6828 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -254,6 +254,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -643,6 +649,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -959,6 +971,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1267,6 +1285,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1568,6 +1592,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1882,6 +1912,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2226,6 +2262,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2570,6 +2612,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2914,6 +2962,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3258,6 +3312,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3602,6 +3662,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3946,6 +4012,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -4290,6 +4362,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -4634,6 +4712,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -4978,6 +5062,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -6497,6 +6587,48 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_service_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "KTU84P",
+              "device_type": "hammerhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7959,6 +8091,18 @@
             }
           ]
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
         "test": "media_unittests"
       },
       {
@@ -8411,6 +8555,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -8766,6 +8916,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -9079,6 +9235,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -9440,6 +9602,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -9772,6 +9940,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -10090,6 +10264,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -10449,6 +10629,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -10759,6 +10945,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -11103,6 +11295,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -11447,6 +11645,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -11791,6 +11995,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -12135,6 +12345,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -12479,6 +12695,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -12823,6 +13045,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -13167,6 +13395,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -13511,6 +13745,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -13855,6 +14095,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -14211,6 +14457,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -14678,6 +14930,17 @@
             }
           ]
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10"
+            }
+          ]
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e5eaa60..69ffc15 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -576,6 +576,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -965,6 +971,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1328,6 +1340,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -1730,6 +1748,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -2087,6 +2111,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2580,6 +2610,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2948,6 +2984,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3256,6 +3298,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3557,6 +3605,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -6271,12 +6325,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "services_unittests"
       }
     ]
@@ -6591,6 +6639,17 @@
             }
           ]
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "coho"
+            }
+          ]
+        },
         "test": "media_unittests"
       },
       {
@@ -6989,6 +7048,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -7376,6 +7441,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -7728,6 +7799,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -8332,6 +8409,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -8729,6 +8812,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "media_unittests"
       },
       {
@@ -9114,6 +9203,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -9422,6 +9517,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 1119b85..3d595d0 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -140,6 +140,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -349,6 +355,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2461,6 +2473,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 208548c..2baa541 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -247,6 +247,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -708,6 +714,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1169,6 +1181,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1644,6 +1662,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2128,6 +2152,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 452dac0..ffb836c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -351,6 +351,18 @@
             }
           ]
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
         "test": "media_unittests"
       },
       {
@@ -984,6 +996,16 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-batch-limit=1",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1497,6 +1519,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1935,6 +1963,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2407,6 +2441,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2818,6 +2858,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3165,6 +3211,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -3480,6 +3532,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 9c6d9f3..4a11a59 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -331,6 +331,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -940,6 +946,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -1486,6 +1498,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2158,6 +2176,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -2739,6 +2763,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter
index 61c81f0..9e691b5 100644
--- a/testing/buildbot/filters/fuchsia.base_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -18,8 +18,6 @@
 -FileProxyTest.SetTimes
 -FileUtilProxyTest.Touch
 -FileUtilTest.FileToFILE
--NativeLibraryTest.LoadLibrary
--NativeLibraryTest.LoadLibraryPreferOwnSymbols
 -PlatformThreadTest.ThreadPriorityCurrentThread
 -ProcessMemoryDumpTest.CountResidentBytes
 -ProcessMemoryDumpTest.CountResidentBytesInSharedMemory
@@ -28,6 +26,11 @@
 -SysInfoTest.AmountOfMem
 -SysInfoTest.AmountOfTotalDiskSpace
 
+# Remove this filter once the migration to packages is complete.
+# See crbug.com/805057.
+-NativeLibraryTest.LoadLibrary
+-NativeLibraryTest.LoadLibraryPreferOwnSymbols
+
 # These tests are affected by an issue with cloning namespace entries from
 # inside a package. See https://crbug.com/826018
 -ProcessUtilTest.CloneAlternateDir
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter
index 78c6295..385ae97a 100644
--- a/testing/buildbot/filters/mash.browser_tests.filter
+++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -71,6 +71,8 @@
 # aura::CrashInFlightChange::ChangeFailed() when searching PDF.
 -ChromeFindRequestManagerTest.*
 -PDFExtensionTest.*
+-PDFExtensionHitTestTest.*
+-PDFExtensionLoadTest.*
 
 # Need screenshot support. http://crbug.com/754899
 -ChromeScreenshotGrabberBrowserTest.*
diff --git a/testing/buildbot/filters/viz.browser_tests.filter b/testing/buildbot/filters/viz.browser_tests.filter
index b7cce1e0..5dca5ca0 100644
--- a/testing/buildbot/filters/viz.browser_tests.filter
+++ b/testing/buildbot/filters/viz.browser_tests.filter
@@ -25,7 +25,7 @@
 
 #### Compositor Frame Observation Timeouts
 # WaitForChildFrameSurfaceReady crashes crbug.com/787945
--PDFExtensionTest.ContextMenuCoordinates
+-PDFExtensionHitTestTest.ContextMenuCoordinates*
 -SitePerProcessDevToolsSanityTest.InputDispatchEventsToOOPIF
 -WebViewTests/WebViewTest.InterstitialPageFocusedWidget/1
 -WebViewTests/WebViewTest.ReloadAfterCrash/1
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 0b5c078d..3b75f1f 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2012,13 +2012,6 @@
       },
     },
   },
-  'media_service_unittests': {
-    'remove_from': [
-      'Linux Tests (dbg)(1)(32)',
-      'Linux ChromiumOS Tests (dbg)(1)',
-      'linux-chromeos-dbg',
-    ],
-  },
   'media_unittests': {
     'remove_from': [
       # chromium.linux
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 555f876c..ee1505ec 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -433,6 +433,7 @@
     'ipc_tests': {},
     'jingle_unittests': {},
     'media_blink_unittests': {},
+    'media_service_unittests': {},
     'media_unittests': {
       'android_swarming': {
         'hard_timeout': 900,
@@ -938,11 +939,6 @@
     },
   },
 
-  'linux_and_chromeos_non_clang_specific_chromium_gtests': {
-    # TOOD(kbr): rename back to linux_and_chromeos_specific_chromium_gtests.
-    'media_service_unittests': {},
-  },
-
   'linux_and_mac_non_clang_specific_chromium_gtests': {
     # TODO(kbr): merge back into linux_and_mac_specific_chromium_gtests.
     'snapshot_unittests': {},
@@ -1108,7 +1104,6 @@
   },
 
   'mojo_windows_specific_gtests': {
-    'media_service_unittests': {},
     'services_unittests': {},
   },
 
@@ -1962,7 +1957,6 @@
     'chromium_gtests_for_linux_and_chromeos_only',
     'chromium_gtests_for_non_clang_and_fyi_mac_win_devices_with_graphical_output',
     'chromium_gtests_for_non_clang_win_devices_with_graphical_output',
-    'linux_and_chromeos_non_clang_specific_chromium_gtests',
     'linux_and_mac_non_clang_specific_chromium_gtests',
     'linux_flavor_specific_chromium_gtests',
     'linux_incl_clang_specific_chromium_gtests',
@@ -2002,7 +1996,6 @@
     'chromium_gtests_for_linux_and_chromeos_only',
     'chromium_gtests_for_non_clang_and_fyi_mac_win_devices_with_graphical_output',
     'chromium_gtests_for_non_clang_win_devices_with_graphical_output',
-    'linux_and_chromeos_non_clang_specific_chromium_gtests',
     'linux_and_mac_non_clang_specific_chromium_gtests',
     'linux_chromeos_specific_gtests',
     'linux_flavor_specific_chromium_gtests',
@@ -2030,7 +2023,6 @@
     'chromium_gtests_for_linux_and_chromeos_only',
     'chromium_gtests_for_non_clang_and_fyi_mac_win_devices_with_graphical_output',
     'chromium_gtests_for_non_clang_win_devices_with_graphical_output',
-    'linux_and_chromeos_non_clang_specific_chromium_gtests',
     'linux_and_mac_non_clang_specific_chromium_gtests',
     'linux_chromeos_specific_gtests',
     'linux_chromeos_rel_mus_specific_gtests',
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 7ae110e..4ddbdc9 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -7,6 +7,8 @@
 /adobe/flash/symbols
 /amd/
 /android_ndk/
+/android_sdk/public/
+/android_sdk/sources/
 /android_protobuf/src
 /android_support_test_runner/lib/
 /android_system_sdk/*.jar
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 70048df..44e0805 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -4060,7 +4060,7 @@
 crbug.com/829921 external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html [ Pass Timeout ]
 
 # Sheriff 2018-04-11
-crbug.com/831701 [ Linux ] external/wpt/offscreen-canvas/compositing/2d.composite.uncovered.nocontext.source-in.worker.html [ Pass Timeout ]
+crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ]
 crbug.com/831686 [ Linux ] fast/webgl/texImage-imageBitmap-from-offscreen-canvas-resize.html [ Pass Timeout ]
 crbug.com/831685 [ Linux ] external/wpt/2dcontext/compositing/2d.composite.canvas.lighter.html [ Pass Timeout ]
 crbug.com/831673 [ Linux ] http/tests/devtools/reveal-objects.js [ Pass Timeout ]
@@ -4073,3 +4073,7 @@
 crbug.com/818426 [ Linux ] virtual/gpu/fast/canvas/canvas-lost-gpu-context.html [ Pass Timeout ]
 crbug.com/818324 [ Linux ] external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html [ Pass Timeout ]
 
+# Sheriff 2018-04-12
+crbug.com/818324 [ Linux ] external/wpt/html/syntax/parsing/html5lib_template.html?run_type=uri [ Pass Timeout ]
+crbug.com/831993 [ Linux ] virtual/gpu-rasterization/images/cross-fade-overflow-position.html [ Pass Timeout ]
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
index c48a136..8d1389cb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
@@ -138,13 +138,17 @@
       t.done();
     }));
   } else {
-    // Assert iframe loads.
-    i.onload = t.step_func(function () {
-      // Delay the check until after the postMessage has a chance to execute.
-      setTimeout(t.step_func_done(function () {
-        assert_true(loaded[urlId]);
-      }), 1);
-    });
+    // Assert iframe loads.  Note that the load event happens before the
+    // postMessage from the iframe is received, so wait for the latter.
+    window.addEventListener('message', t.step_func_done(e => {
+      if (e.source != i.contentWindow)
+        return;
+      assert_true(i.onloadReceived);
+      assert_true(loaded[urlId]);
+    }));
+    i.onload = function () {
+      i.onloadReceived = true;
+    };
   }
   document.body.appendChild(i);
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMarks.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMarks.html
similarity index 90%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMarks.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMarks.html
index 9ff307f..22d6726 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMarks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMarks.html
@@ -5,10 +5,11 @@
 <title>functionality test of window.performance.clearMarks</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 <script>
 setup({ explicit_done: true });
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMeasures.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMeasures.html
similarity index 91%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMeasures.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMeasures.html
index 098b05ce5..488bece3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_clearMeasures.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/clearMeasures.html
@@ -5,10 +5,11 @@
 <title>functionality test of window.performance.clearMeasures</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 <script>
 setup({ explicit_done: true });
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_mark.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/mark.html
similarity index 86%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_mark.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/mark.html
index 74cac73..a7074f1e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_mark.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/mark.html
@@ -5,10 +5,11 @@
 <title>functionality test of window.performance.mark</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 <script>
 setup({ explicit_done: true });
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_associate_with_navigation_timing.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_associated_with_navigation_timing.html
similarity index 90%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_associate_with_navigation_timing.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_associated_with_navigation_timing.html
index d9a4a2a..9fd4664 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_associate_with_navigation_timing.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_associated_with_navigation_timing.html
@@ -5,10 +5,11 @@
 <title>functionality test of window.performance.measure</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 <script>
 setup({ explicit_done: true });
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_exception.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_exception.html
similarity index 81%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_exception.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_exception.html
index e73bca3..8783ff7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure_exception.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measure_exception.html
@@ -5,10 +5,11 @@
 <title>exception test of window.performance.measure</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 </head>
 
 <body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measures.html
similarity index 88%
rename from third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure.html
rename to third_party/WebKit/LayoutTests/external/wpt/user-timing/measures.html
index b2899f4f..d0ab11e3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/submission/Intel/user-timing/test_user_timing_measure.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/measures.html
@@ -5,10 +5,11 @@
 <title>functionality test of window.performance.measure</title>
 <link rel="author" title="Intel" href="http://www.intel.com/" />
 <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<script src="/w3c/resources/testharness.js"></script>
-<script src="/w3c/resources/testharnessreport.js"></script>
-<script src="/w3c/webperf/resources/webperftestharness.js"></script>
-<script src="/w3c/webperf/resources/webperftestharnessextension.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/performance-timeline-utils.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<script src="resources/webperftestharnessextension.js"></script>
 <script>
 setup({ explicit_done: true });
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/resources/webperftestharnessextension.js b/third_party/WebKit/LayoutTests/external/wpt/user-timing/resources/webperftestharnessextension.js
index 579ee909..822376be 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/resources/webperftestharnessextension.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/resources/webperftestharnessextension.js
@@ -88,28 +88,29 @@
         }
     }
 }
+
 function performance_entrylist_checker(type)
 {
-    var entryType = type;
+    const entryType = type;
 
-    function entry_check(entry, expectedNames)
+    function entry_check(entry, expectedNames, testDescription = '')
     {
-        var msg = 'Entry \"' + entry.name + '\" should be one that we have set.';
+        const msg = testDescription + 'Entry \"' + entry.name + '\" should be one that we have set.';
         wp_test(function() { assert_in_array(entry.name, expectedNames, msg); }, msg);
-        test_equals(entry.entryType, entryType, 'entryType should be \"' + entryType + '\".');
+        test_equals(entry.entryType, entryType, testDescription + 'entryType should be \"' + entryType + '\".');
         if (type === "measure") {
-            test_true(isFinite(entry.startTime), 'startTime should be a number.');
-            test_true(isFinite(entry.duration), 'duration should be a number.');
+            test_true(isFinite(entry.startTime), testDescription + 'startTime should be a number.');
+            test_true(isFinite(entry.duration), testDescription + 'duration should be a number.');
         } else if (type === "mark") {
-            test_greater_than(entry.startTime, 0, 'startTime should greater than 0.');
-            test_equals(entry.duration, 0, 'duration of mark should be 0.');
+            test_greater_than(entry.startTime, 0, testDescription + 'startTime should greater than 0.');
+            test_equals(entry.duration, 0, testDescription + 'duration of mark should be 0.');
         }
     }
 
     function entrylist_order_check(entryList)
     {
-        var inOrder = true;
-        for (var i = 0; i < entryList.length - 1; ++i)
+        let inOrder = true;
+        for (let i = 0; i < entryList.length - 1; ++i)
         {
             if (entryList[i + 1].startTime < entryList[i].startTime) {
                 inOrder = false;
@@ -119,13 +120,13 @@
         return inOrder;
     }
 
-    function entrylist_check(entryList, expectedLength, expectedNames)
+    function entrylist_check(entryList, expectedLength, expectedNames, testDescription = '')
     {
-        test_equals(entryList.length, expectedLength, 'There should be ' + expectedLength + ' entries.');
-        test_true(entrylist_order_check(entryList), 'Entries in entrylist should be in order.');
-        for (var i = 0; i < entryList.length; ++i)
+        test_equals(entryList.length, expectedLength, testDescription + 'There should be ' + expectedLength + ' entries.');
+        test_true(entrylist_order_check(entryList), testDescription + 'Entries in entrylist should be in order.');
+        for (let i = 0; i < entryList.length; ++i)
         {
-            entry_check(entryList[i], expectedNames);
+            entry_check(entryList[i], expectedNames, testDescription + 'Entry_list ' + i + '. ');
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
index 81bf157..6b75a0f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
@@ -26,7 +26,6 @@
         navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}));
 }, "Verify that invalid domain error returned by mock is properly handled.");
 
-
 promise_test(t => {
   var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   delete customMakeCredOptions.challenge;
@@ -119,17 +118,31 @@
 
 promise_test(t => {
   mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
+      webauth.mojom.AuthenticatorStatus.AUTHENTICATOR_CRITERIA_UNSUPPORTED);
   return promise_rejects(t, "NotSupportedError",
       navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS}));
-}, "Verify that not supported error returned by mock is properly handled.");
+}, "Verify that authenticator criteria unsupported error returned by mock is properly handled.");
 
 promise_test(t => {
   mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.INVALID_STATE);
+      webauth.mojom.AuthenticatorStatus.ALGORITHM_UNSUPPORTED);
+  return promise_rejects(t, "NotSupportedError",
+      navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS}));
+}, "Verify that algorithm unsupported error returned by mock is properly handled.");
+
+promise_test(t => {
+  mockAuthenticator.setAuthenticatorStatus(
+      webauth.mojom.AuthenticatorStatus.CREDENTIAL_EXCLUDED);
   return promise_rejects(t, "InvalidStateError",
-    navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS}));
-}, "Verify that InvalidState (duplicate registration) returned by mock is properly handled.");
+      navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS}));
+}, "Verify that credential excluded error returned by mock is properly handled.");
+
+promise_test(t => {
+  mockAuthenticator.setAuthenticatorStatus(
+      webauth.mojom.AuthenticatorStatus.CREDENTIAL_NOT_RECOGNIZED);
+  return promise_rejects(t, "InvalidStateError",
+      navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS}));
+}, "Verify that credential not recognized error returned by mock is properly handled.");
 
 promise_test(_ => {
   mockAuthenticator.reset();
@@ -174,7 +187,7 @@
 promise_test(t => {
   mockAuthenticator.reset();
   mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
+      webauth.mojom.AuthenticatorStatus.AUTHENTICATOR_CRITERIA_UNSUPPORTED);
   var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   return promise_rejects(t, "NotSupportedError",
       navigator.credentials.create({publicKey: customMakeCredOptions}));
@@ -183,7 +196,7 @@
 promise_test(t => {
   mockAuthenticator.reset();
   mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
+      webauth.mojom.AuthenticatorStatus.AUTHENTICATOR_CRITERIA_UNSUPPORTED);
   var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.userVerification = 'required';
   return promise_rejects(t, "NotSupportedError",
@@ -200,14 +213,14 @@
   });
 }, "navigator.credentials.create() with userVerification discouraged");
 
-promise_test(_ => {
+promise_test(t => {
   mockAuthenticator.reset();
-  mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
+  mockAuthenticator.setAuthenticatorStatus(
+      webauth.mojom.AuthenticatorStatus.AUTHENTICATOR_CRITERIA_UNSUPPORTED);
   var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.authenticatorAttachment = 'platform';
-  return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
-      assertValidMakeCredentialResponse(r);
-  });
+  return promise_rejects(t, "NotSupportedError",
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with platform authenticatorAttachment");
 
 promise_test(_ => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
index 3157da2..9b6f414e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
@@ -145,13 +145,23 @@
 
 promise_test(t => {
   mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
+      webauth.mojom.AuthenticatorStatus.USER_VERIFICATION_UNSUPPORTED);
   return promise_rejects(t, "NotSupportedError",
       navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS}));
-}, "Verify that not supported error returned by mock is properly handled.");
+}, "Verify that user verification unsupported error returned by mock is properly handled.");
+
+promise_test(t => {
+  mockAuthenticator.setAuthenticatorStatus(
+      webauth.mojom.AuthenticatorStatus.EMPTY_ALLOW_CREDENTIALS);
+  var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
+  delete customGetCredentialOptions.allowCredentials;
+  return promise_rejects(t, "NotSupportedError",
+      navigator.credentials.get({ publicKey : customGetCredentialOptions}));
+}, "Verify that empty allow credentials error returned by mock is properly handled.");
+
 
 promise_test(function(t) {
-  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
   delete customGetCredentialOptions.challenge;
   return promise_rejects(t, new TypeError(),
       navigator.credentials.get({publicKey: customGetCredentialOptions}));
@@ -160,8 +170,9 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulGetAssertion();
-  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
   delete customGetCredentialOptions.rpId;
+  console.log(customGetCredentialOptions);
   return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => {
       assertValidGetCredentialResponse(r);
   });
@@ -170,7 +181,7 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulGetAssertion();
-  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
   delete customGetCredentialOptions.userVerification;
   return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => {
       assertValidGetCredentialResponse(r);
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
index 605817f4..8a51dd13 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
@@ -114,6 +114,16 @@
     navigator.credentials.get({ publicKey : customGetAssertionOptions}));
 }, "navigator.credentials.get() for unregistered device returns InvalidStateError");
 
+promise_test(async t => {
+  var customGetAssertionOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
+  var someOtherCredential = deepCopy(ACCEPTABLE_CREDENTIAL);
+  someOtherCredential.id = new TextEncoder().encode("someOtherCredential");
+  delete customGetAssertionOptions.allowCredentials;
+
+  return promise_rejects(t, "NotSupportedError",
+    navigator.credentials.get({ publicKey : customGetAssertionOptions}));
+}, "navigator.credentials.get() with empty allowCredentials returns NotSupportedError");
+
 promise_test(t => {
   return navigator.credentials.test.clearAuthenticators();
 }, "Clean up testing environment.");
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html
new file mode 100644
index 0000000..b8ac847
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Credential Manager: End-to-end tests for get() with a virtual authenticator.</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
+<script src="/gen/third_party/blink/public/platform/modules/webauth/authenticator.mojom.js"></script>
+<script src="/gen/third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/virtual-navigator-credentials.js"></script>
+<body>
+<script>
+
+if (document.location.host != "subdomain.example.test:8443") {
+  document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-get-from-nested-frame.html";
+  promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
+}
+
+promise_test(async _ => {
+  let authenticators = await navigator.credentials.test.authenticators();
+  assert_equals(authenticators.length, 0);
+  let testAuthenticator = await navigator.credentials.test.createAuthenticator();
+  assert_true(await testAuthenticator.generateAndRegisterKey(ACCEPTABLE_CREDENTIAL_ID, "subdomain.example.test"));
+}, "Set up the testing environment.");
+
+promise_test(async t => {
+  let testAuthenticator = await navigator.credentials.test.createAuthenticator();
+  assert_true(await testAuthenticator.generateAndRegisterKey(ACCEPTABLE_CREDENTIAL_ID, "subdomain.example.test"));
+  let keys = await testAuthenticator.registeredKeys();
+  assert_equals(keys.length, 1);
+  var customGetAssertionOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
+  var someOtherCredential = deepCopy(ACCEPTABLE_CREDENTIAL);
+  someOtherCredential.id = new TextEncoder().encode("someOtherCredential");
+  customGetAssertionOptions.allowCredentials = [someOtherCredential];
+
+  return promise_rejects(t, "InvalidStateError",
+    navigator.credentials.get({ publicKey : customGetAssertionOptions}));
+}, "navigator.credentials.get() for unregistered device returns InvalidStateError");
+
+promise_test(async t => {
+  var customGetAssertionOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
+  var someOtherCredential = deepCopy(ACCEPTABLE_CREDENTIAL);
+  someOtherCredential.id = new TextEncoder().encode("someOtherCredential");
+  delete customGetAssertionOptions.allowCredentials;
+
+  return promise_rejects(t, "NotSupportedError",
+    navigator.credentials.get({ publicKey : customGetAssertionOptions}));
+}, "navigator.credentials.get() with empty allowCredentials returns NotSupportedError");
+
+promise_test(t => {
+  return navigator.credentials.test.clearAuthenticators();
+}, "Clean up testing environment.");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/README b/third_party/WebKit/LayoutTests/http/tests/w3c/README
deleted file mode 100644
index 197f24c..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/README
+++ /dev/null
@@ -1,38 +0,0 @@
-This directory contains files imported from the W3C.
-
-== THIS DIRECTORY IS OBSOLETE ==
-
-Tests are now imported into LayoutTests/imported (see README there).
-
-The tests in LayoutTests/http/tests/w3c/webperf were imported from
-https://dvcs.w3.org/hg/webperf/ but have been migrated into the
-https://github.com/w3c/web-platform-tests repo:
-
-* HighResolutionTime -> hr-time/
-* navigation-timing -> navigation-timing/
-* resource-timing -> resource-timing/
-* UserTiming -> user-timing/
-
-This directory now contains:
-
-* Submissions that were not "approved" - these should be reviewed
-  for redundancy with approved tests in web-platform-tests
-
-* Tests that require a http/s server. Tracked as:
-  http://crbug.com/360762
-
-Please do not add additional tests to this directory, and strive
-to remove them. Removing this directory is tracked as:
-http://crbug.com/498037
-
-== Previous Documentation ==
-
-With only one exception (below), these files should not be modified directly. Instead, please
-source the files from the following locations:
-
-resources/testharness.js - and...
-resources/testharness.css - Fetch from http://w3c-test.org/resources/
-
-resources/testharnessreport.js - Modify directly. It's the vendor specific portion.
-
-webperf/ - Use Tools/Scripts/import-w3c-performance-wg-tests
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharness.js b/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharness.js
deleted file mode 100644
index ff16cfbd..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharness.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- */
-
-//
-// Helper Functions for NavigationTiming W3C tests
-//
-
-var performanceNamespace = window.performance;
-var timingAttributes = [
-    'connectEnd',
-    'connectStart',
-    'domComplete',
-    'domContentLoadedEventEnd',
-    'domContentLoadedEventStart',
-    'domInteractive',
-    'domLoading',
-    'domainLookupEnd',
-    'domainLookupStart',
-    'fetchStart',
-    'loadEventEnd',
-    'loadEventStart',
-    'navigationStart',
-    'redirectEnd',
-    'redirectStart',
-    'requestStart',
-    'responseEnd',
-    'responseStart',
-    'unloadEventEnd',
-    'unloadEventStart'
-];
-
-var namespace_check = false;
-
-//
-// All test() functions in the WebPerf test suite should use wp_test() instead.
-//
-// wp_test() validates the window.performance namespace exists prior to running tests and
-// immediately shows a single failure if it does not.
-//
-
-function wp_test(func, msg, properties)
-{
-    // only run the namespace check once
-    if (!namespace_check)
-    {
-        namespace_check = true;
-
-        if (performanceNamespace === undefined || performanceNamespace == null)
-        {
-            // show a single error that window.performance is undefined
-            test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
-        }
-    }
-
-    test(func, msg, properties);
-}
-
-function test_namespace(child_name, skip_root)
-{
-    if (skip_root === undefined) {
-        var msg = 'window.performance is defined';
-        wp_test(function () { assert_true(performanceNamespace !== undefined, msg); }, msg,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
-    }
-
-    if (child_name !== undefined) {
-        var msg2 = 'window.performance.' + child_name + ' is defined';
-        wp_test(function() { assert_true(performanceNamespace[child_name] !== undefined, msg2); }, msg2,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
-    }
-}
-
-function test_attribute_exists(parent_name, attribute_name, properties)
-{
-    var msg = 'window.performance.' + parent_name + '.' + attribute_name + ' is defined.';
-    wp_test(function() { assert_true(performanceNamespace[parent_name][attribute_name] !== undefined, msg); }, msg, properties);
-}
-
-function test_enum(parent_name, enum_name, value, properties)
-{
-    var msg = 'window.performance.' + parent_name + '.' + enum_name + ' is defined.';
-    wp_test(function() { assert_true(performanceNamespace[parent_name][enum_name] !== undefined, msg); }, msg, properties);
-
-    msg = 'window.performance.' + parent_name + '.' + enum_name + ' = ' + value;
-    wp_test(function() { assert_equals(performanceNamespace[parent_name][enum_name], value, msg); }, msg, properties);
-}
-
-function test_timing_order(attribute_name, greater_than_attribute, properties)
-{
-    // ensure it's not 0 first
-    var msg = "window.performance.timing." + attribute_name + " > 0";
-    wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] > 0, msg); }, msg, properties);
-
-    // ensure it's in the right order
-    msg = "window.performance.timing." + attribute_name + " >= window.performance.timing." + greater_than_attribute;
-    wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] >= performanceNamespace.timing[greater_than_attribute], msg); }, msg, properties);
-}
-
-function test_timing_greater_than(attribute_name, greater_than, properties)
-{
-    var msg = "window.performance.timing." + attribute_name + " > " + greater_than;
-    test_greater_than(performanceNamespace.timing[attribute_name], greater_than, msg, properties);
-}
-
-function test_timing_equals(attribute_name, equals, msg, properties)
-{
-    var test_msg = msg || "window.performance.timing." + attribute_name + " == " + equals;
-    test_equals(performanceNamespace.timing[attribute_name], equals, test_msg, properties);
-}
-
-//
-// Non-test related helper functions
-//
-
-function sleep_milliseconds(n)
-{
-    var start = new Date().getTime();
-    while (true) {
-        if ((new Date().getTime() - start) >= n) break;
-    }
-}
-
-//
-// Common helper functions
-//
-
-function test_true(value, msg, properties)
-{
-    wp_test(function () { assert_true(value, msg); }, msg, properties);
-}
-
-function test_equals(value, equals, msg, properties)
-{
-    wp_test(function () { assert_equals(value, equals, msg); }, msg, properties);
-}
-
-function test_greater_than(value, greater_than, msg, properties)
-{
-    wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties);
-}
-
-function test_greater_or_equals(value, greater_than, msg, properties)
-{
-    wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
-}
-
-function test_not_equals(value, notequals, msg, properties)
-{
-    wp_test(function() { assert_true(value !== notequals, msg); }, msg, properties);
-}
diff --git a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharnessextension.js b/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharnessextension.js
deleted file mode 100644
index e5168c23..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/w3c/webperf/resources/webperftestharnessextension.js
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- */
-
-var mark_names = [
-    '',
-    '1',
-    'abc',
-];
-
-var measures = [
-    [''],
-    ['2', 1],
-    ['aaa', 'navigationStart', ''],
-];
-
-function test_method_exists(method, method_name, properties)
-{
-    var msg;
-    if (typeof method === 'function')
-        msg = 'performance.' + method.name + ' is supported!';
-    else
-        msg = 'performance.' + method_name + ' is supported!';
-    wp_test(function() { assert_true(typeof method === 'function', msg); }, msg, properties);
-}
-
-function test_method_throw_exception(func_str, exception, msg)
-{
-    var exception_name = typeof exception === "object" ? exception.name : exception;
-    var msg = 'Invocation of ' + func_str + ' should throw ' + exception_name  + ' Exception.';
-    wp_test(function() { assert_throws(exception, function() {eval(func_str)}, msg); }, msg);
-}
-
-function test_noless_than(value, greater_than, msg, properties)
-{
-    wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
-}
-
-function test_fail(msg, properties)
-{
-    wp_test(function() { assert_unreached(); }, msg, properties);
-}
-
-function test_resource_entries(entries, expected_entries)
-{
-    // This is slightly convoluted so that we can sort the output.
-    var actual_entries = {};
-    var origin = window.location.protocol + "//" + window.location.host;
-
-    for (var i = 0; i < entries.length; ++i) {
-        var entry = entries[i];
-        var found = false;
-        for (var expected_entry in expected_entries) {
-            if (entry.name == origin + expected_entry) {
-                found = true;
-                if (expected_entry in actual_entries) {
-                    test_fail(expected_entry + ' is not expected to have duplicate entries');
-                }
-                actual_entries[expected_entry] = entry;
-                break;
-            }
-        }
-        if (!found) {
-            test_fail(entries[i].name + ' is not expected to be in the Resource Timing buffer');
-        }
-    }
-
-    sorted_urls = [];
-    for (var i in actual_entries) {
-        sorted_urls.push(i);
-    }
-    sorted_urls.sort();
-    for (var i in sorted_urls) {
-        var url = sorted_urls[i];
-        test_equals(actual_entries[url].initiatorType,
-                    expected_entries[url],
-                    origin + url + ' is expected to have initiatorType ' + expected_entries[url]);
-    }
-    for (var j in expected_entries) {
-        if (!(j in actual_entries)) {
-            test_fail(origin + j + ' is expected to be in the Resource Timing buffer');
-        }
-    }
-}
-function performance_entrylist_checker(type)
-{
-    var entryType = type;
-
-    function entry_check(entry, expectedNames, testDescription='')
-    {
-        var msg = testDescription + 'Entry \"' + entry.name + '\" should be one that we have set.';
-        wp_test(function() { assert_in_array(entry.name, expectedNames, msg); }, msg);
-        test_equals(entry.entryType, entryType, testDescription + 'entryType should be \"' + entryType + '\".');
-        if (type === "measure") {
-            test_true(isFinite(entry.startTime), testDescription + 'startTime should be a number.');
-            test_true(isFinite(entry.duration), testDescription + 'duration should be a number.');
-        } else if (type === "mark") {
-            test_greater_than(entry.startTime, 0, testDescription + 'startTime should greater than 0.');
-            test_equals(entry.duration, 0, testDescription + 'duration of mark should be 0.');
-        }
-    }
-
-    function entrylist_order_check(entryList)
-    {
-        var inOrder = true;
-        for (var i = 0; i < entryList.length - 1; ++i)
-        {
-            if (entryList[i + 1].startTime < entryList[i].startTime) {
-                inOrder = false;
-                break;
-            }
-        }
-        return inOrder;
-    }
-
-    function entrylist_check(entryList, expectedLength, expectedNames, testDescription='')
-    {
-        test_equals(entryList.length, expectedLength, testDescription + 'There should be ' + expectedLength + ' entries.');
-        test_true(entrylist_order_check(entryList), testDescription + 'Entries in entrylist should be in order.');
-        for (var i = 0; i < entryList.length; ++i)
-        {
-            if (testDescription != '')
-                entry_check(entryList[i], expectedNames, testDescription + 'Entry_list ' + i + '. ');
-            else
-                entry_check(entryList[i], expectedNames);
-        }
-    }
-
-    return{"entrylist_check":entrylist_check};
-}
-
-function PerformanceContext(context)
-{
-    this.performanceContext = context;
-}
-
-PerformanceContext.prototype =
-{
-
-    initialMeasures: function(item, index, array)
-    {
-        (this.performanceContext.measure     ||
-         this.performanceContext.mozMeasure  ||
-         this.performanceContext.msMeasure   ||
-         this.performanceContext.oMeasure    ||
-         this.performanceContext.webkitMeasure)
-        .apply(this.performanceContext, item);
-    },
-
-    mark: function()
-    {
-        (this.performanceContext.mark     ||
-         this.performanceContext.mozMark  ||
-         this.performanceContext.msMark   ||
-         this.performanceContext.oMark    ||
-         this.performanceContext.webkitMark)
-        .apply(this.performanceContext, arguments);
-    },
-
-    measure: function()
-    {
-        (this.performanceContext.measure     ||
-         this.performanceContext.mozMeasure  ||
-         this.performanceContext.msMeasure   ||
-         this.performanceContext.oMeasure    ||
-         this.performanceContext.webkitMeasure)
-        .apply(this.performanceContext, arguments);
-    },
-
-    clearMarks: function()
-    {
-        (this.performanceContext.clearMarks     ||
-         this.performanceContext.mozClearMarks  ||
-         this.performanceContext.msClearMarks   ||
-         this.performanceContext.oClearMarks    ||
-         this.performanceContext.webkitClearMarks)
-        .apply(this.performanceContext, arguments);
-
-    },
-
-    clearMeasures: function()
-    {
-        (this.performanceContext.clearMeasures     ||
-         this.performanceContext.mozClearMeasures  ||
-         this.performanceContext.msClearMeasures   ||
-         this.performanceContext.oClearMeasures    ||
-         this.performanceContext.webkitClearMeasures)
-        .apply(this.performanceContext, arguments);
-
-    },
-
-    getEntries: function()
-    {
-        return (this.performanceContext.getEntries     ||
-                this.performanceContext.mozGetEntries  ||
-                this.performanceContext.msGetEntries   ||
-                this.performanceContext.oGetEntries    ||
-                this.performanceContext.webkitGetEntries)
-                .apply(this.performanceContext, arguments);
-    },
-
-    getEntriesByType: function()
-    {
-        return (this.performanceContext.getEntriesByType     ||
-                this.performanceContext.mozGetEntriesByType  ||
-                this.performanceContext.msGetEntriesByType   ||
-                this.performanceContext.oGetEntriesByType    ||
-                this.performanceContext.webkitGetEntriesByType)
-                .apply(this.performanceContext, arguments);
-    },
-
-    getEntriesByName: function()
-    {
-        return (this.performanceContext.getEntriesByName     ||
-                this.performanceContext.mozGetEntriesByName  ||
-                this.performanceContext.msGetEntriesByName   ||
-                this.performanceContext.oGetEntriesByName    ||
-                this.performanceContext.webkitGetEntriesByName)
-                .apply(this.performanceContext, arguments);
-    },
-
-    setResourceTimingBufferSize: function()
-    {
-        return (this.performanceContext.setResourceTimingBufferSize     ||
-                this.performanceContext.mozSetResourceTimingBufferSize  ||
-                this.performanceContext.msSetResourceTimingBufferSize   ||
-                this.performanceContext.oSetResourceTimingBufferSize    ||
-                this.performanceContext.webkitSetResourceTimingBufferSize)
-                .apply(this.performanceContext, arguments);
-    },
-
-    registerResourceTimingBufferFullCallback: function(func)
-    {
-        if (typeof this.performanceContext.onresourcetimingbufferfull !== "undefined")
-            this.performanceContext.onresourcetimingbufferfull = func;
-        else if (typeof this.performanceContext.onmozresourcetimingbufferfull !== "undefined")
-            this.performanceContext.onmozresourcetimingbufferfull = func;
-        else if (typeof this.performanceContext.onmsresourcetimingbufferfull !== "undefined")
-            this.performanceContext.onmsresourcetimingbufferfull = func;
-        else if (typeof this.performanceContext.onoresourcetimingbufferfull !== "undefined")
-            this.performanceContext.onoresourcetimingbufferfull = func;
-        else if (typeof this.performanceContext.onwebkitresourcetimingbufferfull !== "undefined")
-            this.performanceContext.onwebkitresourcetimingbufferfull = func;
-    },
-
-    clearResourceTimings: function()
-    {
-        (this.performanceContext.clearResourceTimings     ||
-         this.performanceContext.mozClearResourceTimings  ||
-         this.performanceContext.msClearResourceTimings   ||
-         this.performanceContext.oClearResourceTimings    ||
-         this.performanceContext.webkitClearResourceTimings)
-        .apply(this.performanceContext, arguments);
-    }
-
-};
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url-expected.txt
new file mode 100644
index 0000000..de2ed11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url-expected.txt
@@ -0,0 +1,4 @@
+Verify that request interception doesn't mess mime types
+<h1>simple!</h1>
+
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url.js b/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url.js
new file mode 100644
index 0000000..7dc44c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/network/interception-file-url.js
@@ -0,0 +1,18 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startBlank(`Verify that request interception doesn't mess mime types`);
+
+  await dp.Network.enable();
+  await dp.Network.setRequestInterception({
+    patterns: [{ urlPattern: '*' }]
+  });
+  dp.Network.onRequestIntercepted(event => {
+    dp.Network.continueInterceptedRequest({
+      interceptionId: event.params.interceptionId
+    });
+  });
+  await dp.Runtime.enable();
+  await session.navigate('./resources/simple.html');
+  // If resource is interpreted as text/plain instead of text/html, the HTML will be escaped.
+  testRunner.log(await session.evaluate(() => document.body.innerHTML));
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/network/resources/simple.html b/third_party/WebKit/LayoutTests/inspector-protocol/network/resources/simple.html
new file mode 100644
index 0000000..2363f87f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/network/resources/simple.html
@@ -0,0 +1 @@
+<h1>simple!</h1>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move-expected.html
new file mode 100644
index 0000000..ec0b9a2d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move-expected.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+Passes if there is no residue when the black bar moving up.
+<div id="target"
+    style="position: relative; top: 40px; width: 100px; height: 100px; box-shadow: 0 8.2px 0 0 black"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move.html b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move.html
new file mode 100644
index 0000000..fbed0aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-move.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+Passes if there is no residue when the black bar moving up.
+<div id="target"
+    style="position: relative; top: 50px; width: 100px; height: 100px; box-shadow: 0 8.2px 0 0 black"></div>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+if (window.testRunner)
+  testRunner.waitUntilDone();
+
+var target_top = 50;
+function test() {
+  target_top -= 0.25;
+  console.log(target_top);
+  target.style.top = target_top + 'px';
+  if (window.testRunner && target_top <= 40) {
+    testRunner.notifyDone();
+  } else {
+    runAfterLayoutAndPaint(test);
+  }
+}
+onload = test;
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-zero-size-box-crash.html b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-zero-size-box-crash.html
new file mode 100644
index 0000000..f334ac2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/subpixel-shadow-zero-size-box-crash.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>test(function(){});</script>
+<div style="box-shadow: 0 5.5px; width: 0; height: 0"></div>
diff --git a/third_party/WebKit/PerformanceTests/Skipped b/third_party/WebKit/PerformanceTests/Skipped
deleted file mode 100644
index a240ea48..0000000
--- a/third_party/WebKit/PerformanceTests/Skipped
+++ /dev/null
@@ -1,48 +0,0 @@
-# Not enabled by default on some ports
-Mutation
-
-# Unstable SVG page loading tests
-SVG/Samurai.html
-
-# Takes too long to load
-SVG/SierpinskiCarpet.html
-
-SVG/France.html
-SVG/FrancoBolloGnomeEzechi.html
-SVG/GearFlowers.html
-SVG/HereGear.html
-
-# Takes 22s on MacBookPro
-SVG/MtSaintHelens.html
-
-# Do not conform to WebKit or Chromium perf test styles
-SunSpider
-XSSAuditor
-
-# https://bugs.webkit.org/show_bug.cgi?id=98708
-Layout/subtree-detaching.html
-
-# We have pure JS tests separately outside Dromaeo.
-Dromaeo
-
-# Bug 77024 - Web Inspector: tests in PerformanceTests/inspector/ are timing out
-inspector
-
-Canvas/drawimage.html
-# crbug.com/727919, crbug.com/736374
-Canvas/getImageDataColorManaged.html
-
-# Redundant with chromium's page cyclers.
-Replay
-
-# Microbenchmark that we aren't interested in monitoring.
-Bindings/gc-forest.html
-Bindings/gc-mini-tree.html
-Bindings/gc-tree.html
-Bindings/named-property-enumerator.html
-
-# Times out on Android. crbug.com/384857
-Animation/overlay-background-color-transitions.html
-
-# Assumes window.eventSender is always supported; it only is for "content-shell" performance runs.
-Editing/mouse-move-with-hidden-elements.html
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/config/builders.json b/third_party/WebKit/Tools/Scripts/webkitpy/common/config/builders.json
index cf1e2d0..fd69dfef 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/config/builders.json
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/config/builders.json
@@ -67,7 +67,7 @@
         "specifiers": ["Mac10.12", "Release"]
     },
     "mac_chromium_rel_ng": {
-        "bucket": "master.tryserver.chromium.mac",
+        "bucket": "luci.chromium.try",
         "port_name": "mac-mac10.12",
         "specifiers": ["Mac10.12", "Release"],
         "is_try_builder": true
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index 21f0db08..f76680b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1076,34 +1076,6 @@
     def path_to_never_fix_tests_file(self):
         return self._filesystem.join(self.layout_tests_dir(), 'NeverFixTests')
 
-    def _expectations_from_skipped_files(self, skipped_file_paths):
-        # TODO(qyearsley): Remove this if there are no more "Skipped" files.
-        tests_to_skip = []
-        for search_path in skipped_file_paths:
-            filename = self._filesystem.join(self._absolute_baseline_path(search_path), 'Skipped')
-            if not self._filesystem.exists(filename):
-                _log.debug('Skipped does not exist: %s', filename)
-                continue
-            _log.debug('Using Skipped file: %s', filename)
-            tests_to_skip.extend(self._tests_from_file(filename))
-        return tests_to_skip
-
-    @memoized
-    def skipped_perf_tests(self):
-        tests = self._expectations_from_skipped_files([self._perf_tests_dir()])
-        # Best to normalize directory names to not include the trailing slash.
-        # TODO(qyearsley): Explain why removing trailing slashes is needed here.
-        return sorted(test.rstrip('/') for test in tests)
-
-    def skips_perf_test(self, test_name):
-        for test_or_category in self.skipped_perf_tests():
-            if test_or_category == test_name:
-                return True
-            category = self._filesystem.join(self._perf_tests_dir(), test_or_category)
-            if self._filesystem.isdir(category) and test_name.startswith(test_or_category):
-                return True
-        return False
-
     def name(self):
         """Returns a name that uniquely identifies this particular type of port.
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 9c087b63..8c53b9a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -87,23 +87,6 @@
         self.assertIn('canvas', dirs)
         self.assertIn('css2.1', dirs)
 
-    def test_skipped_perf_tests(self):
-        port = self.make_port()
-
-        def add_text_file(dirname, filename, content='some content'):
-            dirname = port.host.filesystem.join(
-                PathFinder(port.host.filesystem).perf_tests_dir(), dirname)
-            port.host.filesystem.maybe_make_directory(dirname)
-            port.host.filesystem.write_text_file(port.host.filesystem.join(dirname, filename), content)
-
-        add_text_file('inspector', 'test1.html')
-        add_text_file('inspector', 'unsupported_test1.html')
-        add_text_file('inspector', 'test2.html')
-        add_text_file('inspector/resources', 'resource_file.html')
-        add_text_file('unsupported', 'unsupported_test2.html')
-        add_text_file('', 'Skipped', '\n'.join(['Layout', '', 'SunSpider', 'Supported/some-test.html']))
-        self.assertEqual(port.skipped_perf_tests(), ['Layout', 'SunSpider', 'Supported/some-test.html'])
-
     def test_get_option__set(self):
         options, _ = optparse.OptionParser().parse_args([])
         options.foo = 'bar'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac.py
index 819c953..95440a98f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac.py
@@ -94,7 +94,7 @@
 
     def path_to_apache_config_file(self):
         config_file_basename = 'apache2-httpd-' + self._apache_version()
-        if self._version == 'mac10.13':
+        if self.host.platform.os_version == 'mac10.13':
             config_file_basename += '-php7'
         return self._filesystem.join(self.apache_config_directory(), config_file_basename + '.conf')
 
diff --git a/third_party/android_sdk/LICENSE b/third_party/android_sdk/LICENSE
new file mode 100644
index 0000000..423bf3ab
--- /dev/null
+++ b/third_party/android_sdk/LICENSE
@@ -0,0 +1,217 @@
+Notice for all the files in this folder.
+------------------------------------------------------------
+
+
+   
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License"); you may not
+   use this file except in compliance with the License.
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+   License for the specific language governing permissions and limitations under
+   the License.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2011 Google Inc. All Rights Reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/third_party/android_sdk/OWNERS b/third_party/android_sdk/OWNERS
new file mode 100644
index 0000000..8b49e38a
--- /dev/null
+++ b/third_party/android_sdk/OWNERS
@@ -0,0 +1,11 @@
+agrieve@chromium.org
+jbudorick@chromium.org
+kerz@chromium.org
+michaelbai@chromium.org
+primiano@chromium.org
+rmcilroy@chromium.org
+sgurun@chromium.org
+shenghuazhang@chromium.org
+wangxianzhu@chromium.org
+wnwen@chromium.org
+yfriedman@chromium.org
\ No newline at end of file
diff --git a/third_party/android_sdk/README.chromium b/third_party/android_sdk/README.chromium
new file mode 100644
index 0000000..36112bd
--- /dev/null
+++ b/third_party/android_sdk/README.chromium
@@ -0,0 +1,24 @@
+Name: Android SDK
+URL: http://developer.android.com/sdk/index.html
+Version: 27
+  Android SDK Build-tools 27.0.3
+  Android SDK Emulator 27.1.12
+  Android SDK Extras 47.0.0
+  Android SDK Platform-tools 27.0.1
+  Android SDK Platform API 27
+  Android SDK Sources 27
+  Android SDK Tools 26.1.1
+Security Critical: no
+License: Apache Version 2.0
+
+Description:
+The Android SDK provide API libraries and developer tools necessary to
+build, test and debug for Android.
+
+Local Modifications:
+-In public/
+- Included previous version of tools/emma_device.jar, tools/emma.jar.
+- Included the Android support library and required extras packages.
+- Added extras/chromium/.
+
+No other modifications has been made to the public Android SDK/NDK.
diff --git a/third_party/android_sdk/cipd_build-tools.yaml b/third_party/android_sdk/cipd_build-tools.yaml
new file mode 100644
index 0000000..6507db75
--- /dev/null
+++ b/third_party/android_sdk/cipd_build-tools.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_build-tools.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/build-tools
+description: build-tools Android SDK Build Tools
+data:
+  - dir: public/build-tools
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_emulator.yaml b/third_party/android_sdk/cipd_emulator.yaml
new file mode 100644
index 0000000..eaa4719
--- /dev/null
+++ b/third_party/android_sdk/cipd_emulator.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_emulator.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/emulator
+description: emulator Android SDK Emulator library
+data:
+  - dir: public/emulator
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_extras.yaml b/third_party/android_sdk/cipd_extras.yaml
new file mode 100644
index 0000000..66ba4472
--- /dev/null
+++ b/third_party/android_sdk/cipd_extras.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_extras.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/extras
+description: extras Android SDK Extras library
+data:
+  - dir: public/extras
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_platform-tools.yaml b/third_party/android_sdk/cipd_platform-tools.yaml
new file mode 100644
index 0000000..264d774
--- /dev/null
+++ b/third_party/android_sdk/cipd_platform-tools.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_platform-tools.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/platform-tools
+description: platform-tools Android SDK Platform-tools library
+data:
+  - dir: public/platform-tools
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_platforms.yaml b/third_party/android_sdk/cipd_platforms.yaml
new file mode 100644
index 0000000..37c4e50
--- /dev/null
+++ b/third_party/android_sdk/cipd_platforms.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_platform.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/platforms
+description: platforms Android SDK Platforms library
+data:
+  - dir: public/platforms
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_sources.yaml b/third_party/android_sdk/cipd_sources.yaml
new file mode 100644
index 0000000..6f20f33
--- /dev/null
+++ b/third_party/android_sdk/cipd_sources.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_sources.yaml -tag version:$version
+package: chromium/third_party/android_sdk/sources
+description: sources Android SDK Sources library
+data:
+  - dir: sources/sources
\ No newline at end of file
diff --git a/third_party/android_sdk/cipd_tools.yaml b/third_party/android_sdk/cipd_tools.yaml
new file mode 100644
index 0000000..3f7d2f02
--- /dev/null
+++ b/third_party/android_sdk/cipd_tools.yaml
@@ -0,0 +1,10 @@
+# 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd_tools.yaml -tag version:$version
+package: chromium/third_party/android_sdk/public/tools
+description: tools Android SDK Tools library
+data:
+  - dir: public/tools
\ No newline at end of file
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc
index 2ce5229..94522e6 100644
--- a/third_party/blink/common/feature_policy/feature_policy.cc
+++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -285,6 +285,8 @@
                            {mojom::FeaturePolicyFeature::kUnsizedMedia,
                             FeaturePolicy::FeatureDefault::EnableForAll},
                            {mojom::FeaturePolicyFeature::kPictureInPicture,
+                            FeaturePolicy::FeatureDefault::EnableForAll},
+                           {mojom::FeaturePolicyFeature::kVerticalScroll,
                             FeaturePolicy::FeatureDefault::EnableForAll}}));
   return default_feature_list;
 }
diff --git a/third_party/blink/common/test/run_all_unittests.cc b/third_party/blink/common/test/run_all_unittests.cc
index 16280d27..a85d337 100644
--- a/third_party/blink/common/test/run_all_unittests.cc
+++ b/third_party/blink/common/test/run_all_unittests.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/test_suite.h"
 
 int main(int argc, char** argv) {
diff --git a/third_party/blink/public/mojom/feature_policy/feature_policy.mojom b/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
index e575ab0..7a8541b 100644
--- a/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
+++ b/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
@@ -83,6 +83,8 @@
   kUnsizedMedia,
   // Controls access to Picture-in-Picture.
   kPictureInPicture,
+  // Controls the ability to block and interfere with vertical scrolling.
+  kVerticalScroll,
 };
 
 // This struct holds feature policy whitelist data that needs to be replicated
diff --git a/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom b/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom
index ce5c476..6e3da929 100644
--- a/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom
+++ b/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom
@@ -25,9 +25,13 @@
   PENDING_REQUEST,
   PASSWORD_STORE_UNAVAILABLE,
   NOT_ALLOWED,
-  NOT_SUPPORTED,
+  AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+  ALGORITHM_UNSUPPORTED,
+  EMPTY_ALLOW_CREDENTIALS,
+  USER_VERIFICATION_UNSUPPORTED,
   INVALID_DOMAIN,
-  INVALID_STATE,
+  CREDENTIAL_EXCLUDED,
+  CREDENTIAL_NOT_RECOGNIZED,
   NOT_IMPLEMENTED,
   NOT_FOCUSED,
   UNKNOWN
diff --git a/third_party/blink/public/platform/modules/webauth/authenticator.mojom b/third_party/blink/public/platform/modules/webauth/authenticator.mojom
index 79e850f..b65e0af7 100644
--- a/third_party/blink/public/platform/modules/webauth/authenticator.mojom
+++ b/third_party/blink/public/platform/modules/webauth/authenticator.mojom
@@ -16,9 +16,13 @@
   SUCCESS,
   PENDING_REQUEST,
   NOT_ALLOWED_ERROR,
-  NOT_SUPPORTED_ERROR,
+  AUTHENTICATOR_CRITERIA_UNSUPPORTED,
+  ALGORITHM_UNSUPPORTED,
+  EMPTY_ALLOW_CREDENTIALS,
+  USER_VERIFICATION_UNSUPPORTED,
   INVALID_DOMAIN,
-  INVALID_STATE,
+  CREDENTIAL_EXCLUDED,
+  CREDENTIAL_NOT_RECOGNIZED,
   NOT_IMPLEMENTED,
   NOT_FOCUSED,
   UNKNOWN_ERROR,
diff --git a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
index 2d3c284..bd9a9ba 100644
--- a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
+++ b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_SCHEDULER_TEST_RENDERER_SCHEDULER_TEST_SUPPORT_H_
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 
 namespace base {
 class SequencedTaskRunner;
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 9720d37..469dbaa 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -87,6 +87,7 @@
   BLINK_PLATFORM_EXPORT static void EnableGenericSensorExtraClasses(bool);
   BLINK_PLATFORM_EXPORT static void EnableHeapCompaction(bool);
   BLINK_PLATFORM_EXPORT static void EnableInputMultipleFieldsUI(bool);
+  BLINK_PLATFORM_EXPORT static void EnableLazyFrameLoading(bool);
   BLINK_PLATFORM_EXPORT static void EnableLazyParseCSS(bool);
   BLINK_PLATFORM_EXPORT static void EnableMediaCapture(bool);
   BLINK_PLATFORM_EXPORT static void EnableMediaSession(bool);
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 8e6e07d9..da9e6ef3 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1829,6 +1829,7 @@
     "html/html_dimension_test.cc",
     "html/html_embed_element_test.cc",
     "html/html_frame_element_test.cc",
+    "html/html_frame_owner_element_test.cc",
     "html/html_iframe_element_test.cc",
     "html/html_image_element_test.cc",
     "html/html_link_element_sizes_attribute_test.cc",
diff --git a/third_party/blink/renderer/core/css/css_rule.cc b/third_party/blink/renderer/core/css/css_rule.cc
index 4286cad..95bf6ec9 100644
--- a/third_party/blink/renderer/core/css/css_rule.cc
+++ b/third_party/blink/renderer/core/css/css_rule.cc
@@ -49,12 +49,14 @@
   parent_is_rule_ = false;
   parent_style_sheet_ = style_sheet;
   ScriptWrappableMarkingVisitor::WriteBarrier(parent_style_sheet_);
+  MarkingVisitor::WriteBarrier(parent_style_sheet_);
 }
 
 void CSSRule::SetParentRule(CSSRule* rule) {
   parent_is_rule_ = true;
   parent_rule_ = rule;
   ScriptWrappableMarkingVisitor::WriteBarrier(parent_rule_);
+  MarkingVisitor::WriteBarrier(parent_rule_);
 }
 
 void CSSRule::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 5b47c6a..8652dc0 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -334,7 +334,7 @@
   DCHECK(data_.rare_data_);
   SetFlag(kHasRareDataFlag);
   ScriptWrappableMarkingVisitor::WriteBarrier(RareData());
-  ThreadState::Current()->Heap().WriteBarrier(RareData());
+  MarkingVisitor::WriteBarrier(RareData());
   return *RareData();
 }
 
diff --git a/third_party/blink/renderer/core/frame/frame_owner.h b/third_party/blink/renderer/core/frame/frame_owner.h
index 04c620a2..958b8a6 100644
--- a/third_party/blink/renderer/core/frame/frame_owner.h
+++ b/third_party/blink/renderer/core/frame/frame_owner.h
@@ -61,6 +61,9 @@
   virtual bool IsDisplayNone() const = 0;
   virtual AtomicString RequiredCsp() const = 0;
   virtual const ParsedFeaturePolicy& ContainerPolicy() const = 0;
+
+  // Returns whether or not children of the owned frame should be lazily loaded.
+  virtual bool ShouldLazyLoadChildren() const = 0;
 };
 
 // TODO(dcheng): This class is an internal implementation detail of provisional
@@ -100,6 +103,7 @@
     DEFINE_STATIC_LOCAL(ParsedFeaturePolicy, container_policy, ());
     return container_policy;
   }
+  bool ShouldLazyLoadChildren() const override { return false; }
 
  private:
   // Intentionally private to prevent redundant checks when the type is
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 8bbceae..dbe3218 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -224,7 +224,6 @@
       needs_scrollbars_update_(false),
       suppress_adjust_view_size_(false),
       allows_layout_invalidation_after_layout_clean_(true),
-      forcing_layout_parent_view_(false),
       needs_intersection_observation_(false),
       needs_forced_compositing_update_(false),
       main_thread_scrolling_reasons_(0),
@@ -1057,7 +1056,6 @@
     ScheduleOrthogonalWritingModeRootsForLayout();
   }
 
-
   DCHECK(!IsInPerformLayout());
   Lifecycle().AdvanceTo(DocumentLifecycle::kInPerformLayout);
 
@@ -1135,12 +1133,8 @@
 
   ScriptForbiddenScope forbid_script;
 
-  // forcing_layout_parent_view_ means that we got here recursively via a call
-  // to ForceLayoutParentViewIfNeeded.  In that case, we don't do anything
-  // here, since the original call to UpdateLayout will do its work.  This is
-  // not just an optimization: SVG document size negotiation relies on this.
   if (IsInPerformLayout() || ShouldThrottleRendering() ||
-      forcing_layout_parent_view_ || !frame_->GetDocument()->IsActive())
+      !frame_->GetDocument()->IsActive())
     return;
 
   TRACE_EVENT0("blink,benchmark", "LocalFrameView::layout");
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 070932b..8b4189d7c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -1315,7 +1315,6 @@
   bool needs_scrollbars_update_;
   bool suppress_adjust_view_size_;
   bool allows_layout_invalidation_after_layout_clean_;
-  bool forcing_layout_parent_view_;
   bool needs_intersection_observation_;
   bool needs_forced_compositing_update_;
 
diff --git a/third_party/blink/renderer/core/frame/remote_dom_window.cc b/third_party/blink/renderer/core/frame/remote_dom_window.cc
index 76a3cb62..2b6edf3 100644
--- a/third_party/blink/renderer/core/frame/remote_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/remote_dom_window.cc
@@ -4,9 +4,12 @@
 
 #include "third_party/blink/renderer/core/frame/remote_dom_window.h"
 
+#include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/frame/remote_frame_client.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
@@ -32,8 +35,46 @@
     MessageEvent* event,
     scoped_refptr<const SecurityOrigin> target,
     Document* source) {
-  GetFrame()->Client()->ForwardPostMessage(event, std::move(target),
-                                           source->GetFrame());
+  // Restrict the user gesture to be forwarded cross-process at most once. This
+  // helps avoid unbounded usage of the same user gesture by issuing multiple
+  // postMessages to OOPIFs from this process.  A complementary restriction on
+  // the receiver side prevents unbounded chaining of user gestures across
+  // processes.
+  bool has_user_gesture = UserGestureIndicator::ProcessingUserGesture() &&
+                          !UserGestureIndicator::WasForwardedCrossProcess();
+  if (has_user_gesture)
+    UserGestureIndicator::SetWasForwardedCrossProcess();
+
+  // To match same-process behavior, the IPC to forward postMessage
+  // cross-process should only be sent after the current script finishes
+  // running, to preserve relative ordering of IPCs.  See
+  // https://crbug.com/828529.
+  //
+  // TODO(alexmos, kenrb): PostTask isn't sufficient in some cases, such as
+  // when script triggers a layout change after calling postMessage(), which
+  // should also be observable by the target frame prior to receiving the
+  // postMessage. We might consider forcing layout in ForwardPostMessage or
+  // further delaying postMessage forwarding until after the next BeginFrame.
+  source->GetTaskRunner(TaskType::kPostedMessage)
+      ->PostTask(
+          FROM_HERE,
+          WTF::Bind(&RemoteDOMWindow::ForwardPostMessage, WrapPersistent(this),
+                    WrapPersistent(event), std::move(target),
+                    WrapPersistent(source), has_user_gesture));
+}
+
+void RemoteDOMWindow::ForwardPostMessage(
+    MessageEvent* event,
+    scoped_refptr<const SecurityOrigin> target,
+    Document* source,
+    bool has_user_gesture) {
+  // If the target frame was detached after the message was scheduled,
+  // don't deliver the message.
+  if (!GetFrame())
+    return;
+
+  GetFrame()->Client()->ForwardPostMessage(
+      event, std::move(target), source->GetFrame(), has_user_gesture);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_dom_window.h b/third_party/blink/renderer/core/frame/remote_dom_window.h
index c2c2957..66d9568 100644
--- a/third_party/blink/renderer/core/frame/remote_dom_window.h
+++ b/third_party/blink/renderer/core/frame/remote_dom_window.h
@@ -41,6 +41,11 @@
   // already RemoteDOMWindow.
   bool IsLocalDOMWindow() const override { return false; }
   bool IsRemoteDOMWindow() const override { return true; }
+
+  void ForwardPostMessage(MessageEvent*,
+                          scoped_refptr<const SecurityOrigin> target,
+                          Document* source,
+                          bool has_user_gesture);
 };
 
 DEFINE_TYPE_CASTS(RemoteDOMWindow,
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client.h b/third_party/blink/renderer/core/frame/remote_frame_client.h
index c5a6ee0..a01f396 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client.h
+++ b/third_party/blink/renderer/core/frame/remote_frame_client.h
@@ -35,7 +35,8 @@
   // Forwards a postMessage for a remote frame.
   virtual void ForwardPostMessage(MessageEvent*,
                                   scoped_refptr<const SecurityOrigin> target,
-                                  LocalFrame* source_frame) const = 0;
+                                  LocalFrame* source_frame,
+                                  bool has_user_gesture) const = 0;
 
   // Forwards a change to the rects of a remote frame. |local_frame_rect| is the
   // size of the frame in its parent's coordinate space prior to applying CSS
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
index e36dd74..d9dcfb1 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
@@ -141,17 +141,8 @@
 void RemoteFrameClientImpl::ForwardPostMessage(
     MessageEvent* event,
     scoped_refptr<const SecurityOrigin> target,
-    LocalFrame* source_frame) const {
-  // Restrict the user gesture to be forwarded cross-process at most once. This
-  // helps avoid unbounded usage of the same user gesture by issuing multiple
-  // postMessages to OOPIFs from this process.  A complementary restriction on
-  // the receiver side prevents unbounded chaining of user gestures across
-  // processes.
-  bool has_user_gesture = UserGestureIndicator::ProcessingUserGesture() &&
-                          !UserGestureIndicator::WasForwardedCrossProcess();
-  if (has_user_gesture)
-    UserGestureIndicator::SetWasForwardedCrossProcess();
-
+    LocalFrame* source_frame,
+    bool has_user_gesture) const {
   if (web_frame_->Client()) {
     web_frame_->Client()->ForwardPostMessage(
         WebLocalFrameImpl::FromFrame(source_frame), web_frame_,
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client_impl.h b/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
index 1d8a75f7c..6f1d77d 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
@@ -36,7 +36,8 @@
   void CheckCompleted() override;
   void ForwardPostMessage(MessageEvent*,
                           scoped_refptr<const SecurityOrigin> target,
-                          LocalFrame* source) const override;
+                          LocalFrame* source,
+                          bool has_user_gesture) const override;
   void FrameRectsChanged(const IntRect& local_frame_rect,
                          const IntRect& screen_space_rect) override;
   void UpdateRemoteViewportIntersection(const IntRect&) override;
diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.cc b/third_party/blink/renderer/core/frame/remote_frame_owner.cc
index b9b926f..ae9c65e 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_owner.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame_owner.cc
@@ -77,4 +77,11 @@
       ->IntrinsicSizingInfoChanged(intrinsic_sizing_info);
 }
 
+bool RemoteFrameOwner::ShouldLazyLoadChildren() const {
+  // Don't use lazy load for children inside an OOPIF, since there's a good
+  // chance that the parent FrameOwner was previously deferred by lazy load
+  // and then loaded in for whatever reason.
+  return false;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.h b/third_party/blink/renderer/core/frame/remote_frame_owner.h
index 251038f6..809c45c 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_owner.h
+++ b/third_party/blink/renderer/core/frame/remote_frame_owner.h
@@ -57,6 +57,7 @@
   const ParsedFeaturePolicy& ContainerPolicy() const override {
     return container_policy_;
   }
+  bool ShouldLazyLoadChildren() const final;
 
   void SetBrowsingContextContainerName(const WebString& name) {
     browsing_context_container_name_ = name;
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index 9b9b0fa..f6bd38c 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -20,6 +20,8 @@
 
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 
+#include <limits>
+
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
 #include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
@@ -31,6 +33,9 @@
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/remote_frame_view.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
@@ -40,6 +45,8 @@
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/length.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 
 namespace blink {
@@ -52,6 +59,41 @@
   return set;
 }
 
+bool DoesParentAllowLazyLoadingChildren(Document& document) {
+  LocalFrame* containing_frame = document.GetFrame();
+  if (!containing_frame)
+    return true;
+
+  // If the embedding document has no owner, then by default allow lazy loading
+  // children.
+  FrameOwner* containing_frame_owner = containing_frame->Owner();
+  if (!containing_frame_owner)
+    return true;
+
+  return containing_frame_owner->ShouldLazyLoadChildren();
+}
+
+// Determine if the |bounding_client_rect| for a frame indicates that the frame
+// is probably hidden according to some experimental heuristics. Since hidden
+// frames are often used for analytics or communication, and lazily loading them
+// could break their functionality, so these heuristics are used to recognize
+// likely hidden frames and immediately load them so that they can function
+// properly.
+bool IsFrameProbablyHidden(const DOMRectReadOnly& bounding_client_rect) {
+  // Tiny frames that are 4x4 or smaller are likely not intended to be seen by
+  // the user. Note that this condition includes frames marked as
+  // "display:none", since those frames would have dimensions of 0x0.
+  if (bounding_client_rect.width() < 4.1 || bounding_client_rect.height() < 4.1)
+    return true;
+
+  // Frames that are positioned completely off the page above or to the left are
+  // likely never intended to be visible to the user.
+  if (bounding_client_rect.right() < 0.0 || bounding_client_rect.bottom() < 0.0)
+    return true;
+
+  return false;
+}
+
 }  // namespace
 
 SubframeLoadingDisabler::SubtreeRootSet&
@@ -80,7 +122,9 @@
     : HTMLElement(tag_name, document),
       content_frame_(nullptr),
       embedded_content_view_(nullptr),
-      sandbox_flags_(kSandboxNone) {}
+      sandbox_flags_(kSandboxNone),
+      should_lazy_load_children_(DoesParentAllowLazyLoadingChildren(document)) {
+}
 
 LayoutEmbeddedContent* HTMLFrameOwnerElement::GetLayoutEmbeddedContent() const {
   // HTMLObjectElement and HTMLEmbedElement may return arbitrary layoutObjects
@@ -96,6 +140,11 @@
   DCHECK(!content_frame_ || content_frame_->Owner() != this);
   // Disconnected frames should not be allowed to load.
   DCHECK(isConnected());
+
+  // There should be no lazy load in progress since before SetContentFrame,
+  // |this| frame element should have been disconnected.
+  DCHECK(!lazy_load_intersection_observer_);
+
   content_frame_ = &frame;
 
   for (ContainerNode* node = this; node; node = node->ParentOrShadowHostNode())
@@ -106,6 +155,10 @@
   if (!content_frame_)
     return;
 
+  // There should not be a lazy load in progress right now since any pending
+  // lazy load should have already been cancelled in DisconnectContentFrame.
+  DCHECK(!lazy_load_intersection_observer_);
+
   DCHECK_EQ(content_frame_->Owner(), this);
   content_frame_ = nullptr;
 
@@ -117,6 +170,8 @@
   if (!ContentFrame())
     return;
 
+  CancelPendingLazyLoad();
+
   // Removing a subframe that was still loading can impact the result of
   // AllDescendantsAreComplete that is consulted by Document::ShouldComplete.
   // Therefore we might need to re-check this after removing the subframe.  The
@@ -296,6 +351,7 @@
   UpdateContainerPolicy();
 
   if (ContentFrame()) {
+    // TODO(sclittle): Support lazily loading frame navigations.
     ContentFrame()->Navigate(GetDocument(), url, replace_current_item,
                              UserGestureStatus::kNone);
     return true;
@@ -336,14 +392,79 @@
   if (IsPlugin())
     request.SetSkipServiceWorker(true);
 
-  child_frame->Loader().Load(FrameLoadRequest(&GetDocument(), request),
-                             child_load_type);
+  if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled() &&
+      should_lazy_load_children_ &&
+      // Only http:// or https:// URLs are eligible for lazy loading, excluding
+      // URLs like invalid or empty URLs, "about:blank", local file URLs, etc.
+      // that it doesn't make sense to lazily load.
+      url.ProtocolIsInHTTPFamily() &&
+      // Disallow lazy loading if javascript in the embedding document would be
+      // able to access the contents of the frame, since in those cases
+      // deferring the frame could break the page. Note that this check does not
+      // take any possible redirects of |url| into account.
+      !GetDocument().GetSecurityOrigin()->CanAccess(
+          SecurityOrigin::Create(url).get())) {
+    // Don't lazy load subresources inside a lazily loaded frame. This will make
+    // it possible for subresources in hidden frames to load that will
+    // never be visible, as well as make it so that deferred frames that have
+    // multiple layers of iframes inside them can load faster once they're near
+    // the viewport or visible.
+    should_lazy_load_children_ = false;
+
+    lazy_load_intersection_observer_ = IntersectionObserver::Create(
+        {Length(kLazyLoadRootMarginPx, kFixed)},
+        {std::numeric_limits<float>::min()}, &GetDocument(),
+        WTF::BindRepeating(&HTMLFrameOwnerElement::LoadIfHiddenOrNearViewport,
+                           WrapWeakPersistent(this), request, child_load_type));
+
+    lazy_load_intersection_observer_->observe(this);
+  } else {
+    child_frame->Loader().Load(FrameLoadRequest(&GetDocument(), request),
+                               child_load_type);
+  }
   return true;
 }
 
+void HTMLFrameOwnerElement::LoadIfHiddenOrNearViewport(
+    const ResourceRequest& resource_request,
+    FrameLoadType frame_load_type,
+    const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+  DCHECK(!entries.IsEmpty());
+  DCHECK_EQ(this, entries.back()->target());
+
+  if (!entries.back()->isIntersecting() &&
+      !IsFrameProbablyHidden(*entries.back()->boundingClientRect())) {
+    return;
+  }
+
+  // The content frame of this element should not have changed, since any
+  // pending lazy load should have been already been cancelled in
+  // DisconnectContentFrame() if the content frame changes.
+  DCHECK(ContentFrame());
+
+  // Note that calling FrameLoader::Load() causes this intersection observer to
+  // be disconnected.
+  ToLocalFrame(ContentFrame())
+      ->Loader()
+      .Load(FrameLoadRequest(&GetDocument(), resource_request),
+            frame_load_type);
+}
+
+void HTMLFrameOwnerElement::CancelPendingLazyLoad() {
+  if (!lazy_load_intersection_observer_)
+    return;
+  lazy_load_intersection_observer_->disconnect();
+  lazy_load_intersection_observer_.Clear();
+}
+
+bool HTMLFrameOwnerElement::ShouldLazyLoadChildren() const {
+  return should_lazy_load_children_;
+}
+
 void HTMLFrameOwnerElement::Trace(blink::Visitor* visitor) {
   visitor->Trace(content_frame_);
   visitor->Trace(embedded_content_view_);
+  visitor->Trace(lazy_load_intersection_observer_);
   HTMLElement::Trace(visitor);
   FrameOwner::Trace(visitor);
 }
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h
index 9f8299d..918b0f2 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -37,6 +37,8 @@
 
 class ExceptionState;
 class Frame;
+class IntersectionObserver;
+class IntersectionObserverEntry;
 class LayoutEmbeddedContent;
 class WebPluginContainerImpl;
 
@@ -110,10 +112,17 @@
   bool IsDisplayNone() const override { return !embedded_content_view_; }
   AtomicString RequiredCsp() const override { return g_null_atom; }
   const ParsedFeaturePolicy& ContainerPolicy() const override;
+  bool ShouldLazyLoadChildren() const final;
 
   // For unit tests, manually trigger the UpdateContainerPolicy method.
   void UpdateContainerPolicyForTests() { UpdateContainerPolicy(); }
 
+  void CancelPendingLazyLoad();
+
+  // TODO(sclittle): Make the root margins configurable via field trial
+  // params instead of just hardcoding the value here.
+  static constexpr int kLazyLoadRootMarginPx = 800;
+
   virtual void Trace(blink::Visitor*);
 
  protected:
@@ -166,11 +175,19 @@
     return kReferrerPolicyDefault;
   }
 
+  void LoadIfHiddenOrNearViewport(
+      const ResourceRequest&,
+      FrameLoadType,
+      const HeapVector<Member<IntersectionObserverEntry>>&);
+
   Member<Frame> content_frame_;
   Member<EmbeddedContentView> embedded_content_view_;
   SandboxFlags sandbox_flags_;
 
   ParsedFeaturePolicy container_policy_;
+
+  Member<IntersectionObserver> lazy_load_intersection_observer_;
+  bool should_lazy_load_children_;
 };
 
 DEFINE_ELEMENT_TYPE_CASTS(HTMLFrameOwnerElement, IsFrameOwnerElement());
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc b/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc
new file mode 100644
index 0000000..d2d41673
--- /dev/null
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc
@@ -0,0 +1,308 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+
+#include <algorithm>
+
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+namespace {
+
+class LazyLoadFramesTest : public SimTest {
+ public:
+  static constexpr int kViewportWidth = 800;
+  static constexpr int kViewportHeight = 600;
+
+  LazyLoadFramesTest() : scoped_lazy_frame_loading_for_test_(true) {}
+
+  void SetUp() override {
+    SimTest::SetUp();
+    WebView().Resize(WebSize(kViewportWidth, kViewportHeight));
+  }
+
+ private:
+  ScopedLazyFrameLoadingForTest scoped_lazy_frame_loading_for_test_;
+};
+
+TEST_F(LazyLoadFramesTest, SameOriginFrameIsNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  SimRequest child_frame_resource("https://example.com/subframe.html",
+                                  "text/html");
+
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx;'></div>
+        <iframe src='https://example.com/subframe.html'
+             style='width: 200px; height: 200px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx));
+
+  child_frame_resource.Complete("");
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+}
+
+TEST_F(LazyLoadFramesTest, AboveTheFoldFrameIsNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+                                  "text/html");
+
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx;'></div>
+        <iframe src='https://crossorigin.com/subframe.html'
+             style='width: 200px; height: 200px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight - 100));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  child_frame_resource.Complete("");
+
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+}
+
+TEST_F(LazyLoadFramesTest, BelowTheFoldButNearViewportFrameIsNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+                                  "text/html");
+
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx;'></div>
+        <iframe src='https://crossorigin.com/subframe.html'
+             style='width: 200px; height: 200px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight + 100));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  child_frame_resource.Complete("");
+
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+}
+
+TEST_F(LazyLoadFramesTest, HiddenAndTinyFramesAreNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+
+  SimRequest display_none_frame_resource(
+      "https://crossorigin.com/display_none.html", "text/html");
+  SimRequest tiny_frame_resource("https://crossorigin.com/tiny.html",
+                                 "text/html");
+  SimRequest tiny_width_frame_resource(
+      "https://crossorigin.com/tiny_width.html", "text/html");
+  SimRequest tiny_height_frame_resource(
+      "https://crossorigin.com/tiny_height.html", "text/html");
+  SimRequest off_screen_left_frame_resource(
+      "https://crossorigin.com/off_screen_left.html", "text/html");
+  SimRequest off_screen_top_frame_resource(
+      "https://crossorigin.com/off_screen_top.html", "text/html");
+
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <head><style>
+          /* Chrome by default sets borders for iframes, so explicitly specify
+           * no borders, padding, or margins here so that the dimensions of the
+           * tiny frames aren't artifically inflated past the dimensions that
+           * the lazy loading logic considers "tiny". */
+          iframe { border-style: none; padding: 0px; margin: 0px; }
+        </style></head>
+
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx'></div>
+        <iframe src='https://crossorigin.com/display_none.html'
+             style='display: none;'
+             onload='console.log("display none element onload");'></iframe>
+        <iframe src='https://crossorigin.com/tiny.html'
+             style='width: 4px; height: 4px;'
+             onload='console.log("tiny element onload");'></iframe>
+        <iframe src='https://crossorigin.com/tiny_width.html'
+             style='width: 0px; height: 200px;'
+             onload='console.log("tiny width element onload");'></iframe>
+        <iframe src='https://crossorigin.com/tiny_height.html'
+             style='width: 200px; height: 0px;'
+             onload='console.log("tiny height element onload");'></iframe>
+        <iframe src='https://crossorigin.com/off_screen_left.html'
+             style='position:relative;right:9000px;width:200px;height:200px;'
+             onload='console.log("off screen left element onload");'></iframe>
+        <iframe src='https://crossorigin.com/off_screen_top.html'
+             style='position:relative;bottom:9000px;width:200px;height:200px;'
+             onload='console.log("off screen top element onload");'></iframe>
+        </body>
+      )HTML",
+      kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  display_none_frame_resource.Complete("");
+  tiny_frame_resource.Complete("");
+  tiny_width_frame_resource.Complete("");
+  tiny_height_frame_resource.Complete("");
+  off_screen_left_frame_resource.Complete("");
+  off_screen_top_frame_resource.Complete("");
+
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("display none element onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("tiny element onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("tiny width element onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("tiny height element onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("off screen left element onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("off screen top element onload"));
+}
+
+TEST_F(LazyLoadFramesTest, CrossOriginFrameIsDeferredUntilNearViewport) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx;'></div>
+        <iframe src='https://crossorigin.com/subframe.html'
+             style='width: 400px; height: 400px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload"));
+
+  SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+                                  "text/html");
+
+  // Scroll down near the child frame. This should cause the child frame to get
+  // loaded.
+  GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+      ScrollOffset(0, kViewportHeight + 150), kProgrammaticScroll);
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  SimRequest nested_child_frame_resource("https://test.com/", "text/html");
+
+  // There's another nested cross origin iframe inside the first child frame,
+  // partway down such that it's not near the viewport. It should still be
+  // loaded immediately, and not deferred, since it's nested inside a frame that
+  // was previously deferred.
+  child_frame_resource.Complete(
+      "<div style='height: 200px;'></div>"
+      "<iframe src='https://test.com/' style='width: 200px; height: 200px;'>"
+      "</iframe>");
+
+  test::RunPendingTasks();
+  nested_child_frame_resource.Complete("");
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+}
+
+TEST_F(LazyLoadFramesTest, AboutBlankNavigationIsNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+                                  "text/html");
+
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='BodyOnload()'>
+        <script>
+          function BodyOnload() {
+            console.log('main body onload');
+            document.getElementsByTagName('iframe')[0].src =
+                'https://crossorigin.com/subframe.html';
+          }
+        </script>
+
+        <div style='height: %dpx;'></div>
+        <iframe
+             style='width: 200px; height: 200px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_EQ(1, static_cast<int>(std::count(ConsoleMessages().begin(),
+                                           ConsoleMessages().end(),
+                                           "child frame element onload")));
+
+  child_frame_resource.Complete("");
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  EXPECT_EQ(2, static_cast<int>(std::count(ConsoleMessages().begin(),
+                                           ConsoleMessages().end(),
+                                           "child frame element onload")));
+}
+
+TEST_F(LazyLoadFramesTest, JavascriptStringUrlIsNotDeferred) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  LoadURL("https://example.com/");
+
+  main_resource.Complete(String::Format(
+      R"HTML(
+        <body onload='console.log("main body onload");'>
+        <div style='height: %dpx;'></div>
+        <iframe src='javascript:"Hello World!";'
+             style='width: 200px; height: 200px;'
+             onload='console.log("child frame element onload");'></iframe>
+        </body>)HTML",
+      kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
+
+  EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+  EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+}
+
+}  // namespace
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 02dc14d..526d77a 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -5061,8 +5061,15 @@
 
   // Add in the final overflow with shadows, outsets and outline combined.
   LayoutRect visual_effect_overflow = BorderBoxRect();
-  visual_effect_overflow.Expand(ComputeVisualEffectOverflowOutsets());
+  LayoutRectOutsets outsets = ComputeVisualEffectOverflowOutsets();
+  visual_effect_overflow.Expand(outsets);
   AddSelfVisualOverflow(visual_effect_overflow);
+
+  if (overflow_) {
+    overflow_->SetHasSubpixelVisualEffectOutsets(
+        !IsIntegerValue(outsets.Top()) || !IsIntegerValue(outsets.Right()) ||
+        !IsIntegerValue(outsets.Bottom()) || !IsIntegerValue(outsets.Left()));
+  }
 }
 
 LayoutRectOutsets LayoutBox::ComputeVisualEffectOverflowOutsets() {
@@ -5991,4 +5998,12 @@
       GetLayoutBox().PhysicalLayoutOverflowRect();
 }
 
+float LayoutBox::VisualRectOutsetForRasterEffects() const {
+  // If the box has subpixel visual effect outsets, as the visual effect may be
+  // painted along the pixel-snapped border box, the pixels on the anti-aliased
+  // edge of the effect may overflow the calculated visual rect. Expand visual
+  // rect by one pixel in the case.
+  return overflow_ && overflow_->HasSubpixelVisualEffectOutsets() ? 1 : 0;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index 8125f26..927ac6b 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -1626,6 +1626,8 @@
 
   LayoutRect DebugRect() const override;
 
+  float VisualRectOutsetForRasterEffects() const override;
+
   // The CSS border box rect for this box.
   //
   // The rectangle is in this box's physical coordinates but with a
diff --git a/third_party/blink/renderer/core/layout/overflow_model.h b/third_party/blink/renderer/core/layout/overflow_model.h
index 56ef49e3..85aec7a 100644
--- a/third_party/blink/renderer/core/layout/overflow_model.h
+++ b/third_party/blink/renderer/core/layout/overflow_model.h
@@ -181,11 +181,19 @@
     layout_client_after_edge_ = client_after_edge;
   }
 
+  void SetHasSubpixelVisualEffectOutsets(bool b) {
+    has_subpixel_visual_effect_outsets_ = b;
+  }
+  bool HasSubpixelVisualEffectOutsets() const {
+    return has_subpixel_visual_effect_outsets_;
+  }
+
  private:
   LayoutRect layout_overflow_;
   LayoutRect self_visual_overflow_;
   LayoutRect contents_visual_overflow_;
   LayoutUnit layout_client_after_edge_;
+  bool has_subpixel_visual_effect_outsets_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(BoxOverflowModel);
 };
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index c885d419e..779ae4212 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -414,7 +414,8 @@
   void CheckCompleted() override {}
   void ForwardPostMessage(MessageEvent*,
                           scoped_refptr<const SecurityOrigin> target,
-                          LocalFrame* source_frame) const override {}
+                          LocalFrame* source_frame,
+                          bool has_user_gesture) const override {}
   void FrameRectsChanged(const IntRect& local_frame_rect,
                          const IntRect& transformed_frame_rect) override {}
   void UpdateRemoteViewportIntersection(
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 878f8f6..7633ffef 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -872,6 +872,9 @@
                        HistoryLoadType history_load_type) {
   DCHECK(frame_->GetDocument());
 
+  if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
+    element->CancelPendingLazyLoad();
+
   if (IsBackForwardLoadType(frame_load_type) && !frame_->IsNavigationAllowed())
     return;
 
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
index b84a8c6..d2e9793 100644
--- a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
+++ b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
@@ -649,12 +649,16 @@
       const metrics = await screenCaptureModel.fetchLayoutMetrics();
       if (!metrics)
         return null;
+
+      // Cap the height to not hit the GPU limit.
+      const contentHeight = Math.min((1 << 14) / this._appliedDeviceScaleFactor, metrics.contentHeight);
       deviceMetrics = {
         width: Math.floor(metrics.contentWidth),
-        height: Math.floor(metrics.contentHeight),
+        height: Math.floor(contentHeight),
         deviceScaleFactor: this._appliedDeviceScaleFactor,
         mobile: this._isMobile(),
       };
+
       clip = {x: 0, y: 0, width: deviceMetrics.width, height: deviceMetrics.height, scale: 1};
 
       if (this._device) {
diff --git a/third_party/blink/renderer/devtools/front_end/inline_editor/cssShadowEditor.css b/third_party/blink/renderer/devtools/front_end/inline_editor/cssShadowEditor.css
index 1c849b8a..7dfa69e 100644
--- a/third_party/blink/renderer/devtools/front_end/inline_editor/cssShadowEditor.css
+++ b/third_party/blink/renderer/devtools/front_end/inline_editor/cssShadowEditor.css
@@ -88,4 +88,5 @@
     width: 52px;
     margin-right: 8px;
     text-align: right;
+    box-shadow: var(--focus-ring-inactive-shadow);
 }
diff --git a/third_party/blink/renderer/devtools/front_end/main/module.json b/third_party/blink/renderer/devtools/front_end/main/module.json
index c51f586..7d58386fa 100644
--- a/third_party/blink/renderer/devtools/front_end/main/module.json
+++ b/third_party/blink/renderer/devtools/front_end/main/module.json
@@ -34,12 +34,7 @@
             "actionId": "inspector_main.focus-debuggee",
             "className": "InspectorMain.FocusDebuggeeActionDelegate",
             "order": 100,
-            "title": "Focus debuggee",
-            "bindings": [
-                {
-                    "shortcut": "F12"
-                }
-            ]
+            "title": "Focus debuggee"
         },
         {
             "type": "action",
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 001f904..8d2f508 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -260,6 +260,7 @@
     "media_controls/elements/media_control_input_element_test.cc",
     "media_controls/elements/media_control_loading_panel_element_test.cc",
     "media_controls/elements/media_control_overlay_play_button_element_test.cc",
+    "media_controls/elements/media_control_panel_element_test.cc",
     "media_controls/elements/media_control_scrubbing_message_element_test.cc",
     "media_controls/elements/media_control_timeline_element_test.cc",
     "media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc",
diff --git a/third_party/blink/renderer/modules/cachestorage/InspectorCacheStorageAgent.cpp b/third_party/blink/renderer/modules/cachestorage/InspectorCacheStorageAgent.cpp
index 8bc225d7..42c0c55 100644
--- a/third_party/blink/renderer/modules/cachestorage/InspectorCacheStorageAgent.cpp
+++ b/third_party/blink/renderer/modules/cachestorage/InspectorCacheStorageAgent.cpp
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <memory>
 #include <utility>
-#include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_cache.h"
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
index a867a368..40bf9cb 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
@@ -108,8 +108,16 @@
 TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
     const AuthenticatorStatus& status) {
   switch (status) {
-    case webauth::mojom::blink::AuthenticatorStatus::NOT_SUPPORTED_ERROR:
-      return CredentialManagerError::NOT_SUPPORTED;
+    case webauth::mojom::blink::AuthenticatorStatus::
+        AUTHENTICATOR_CRITERIA_UNSUPPORTED:
+      return CredentialManagerError::AUTHENTICATOR_CRITERIA_UNSUPPORTED;
+    case webauth::mojom::blink::AuthenticatorStatus::ALGORITHM_UNSUPPORTED:
+      return CredentialManagerError::ALGORITHM_UNSUPPORTED;
+    case webauth::mojom::blink::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS:
+      return CredentialManagerError::EMPTY_ALLOW_CREDENTIALS;
+    case webauth::mojom::blink::AuthenticatorStatus::
+        USER_VERIFICATION_UNSUPPORTED:
+      return CredentialManagerError::USER_VERIFICATION_UNSUPPORTED;
     case webauth::mojom::blink::AuthenticatorStatus::NOT_ALLOWED_ERROR:
       return CredentialManagerError::NOT_ALLOWED;
     case webauth::mojom::blink::AuthenticatorStatus::UNKNOWN_ERROR:
@@ -118,8 +126,10 @@
       return CredentialManagerError::PENDING_REQUEST;
     case webauth::mojom::blink::AuthenticatorStatus::INVALID_DOMAIN:
       return CredentialManagerError::INVALID_DOMAIN;
-    case webauth::mojom::blink::AuthenticatorStatus::INVALID_STATE:
-      return CredentialManagerError::INVALID_STATE;
+    case webauth::mojom::blink::AuthenticatorStatus::CREDENTIAL_EXCLUDED:
+      return CredentialManagerError::CREDENTIAL_EXCLUDED;
+    case webauth::mojom::blink::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED:
+      return CredentialManagerError::CREDENTIAL_NOT_RECOGNIZED;
     case webauth::mojom::blink::AuthenticatorStatus::NOT_IMPLEMENTED:
       return CredentialManagerError::NOT_IMPLEMENTED;
     case webauth::mojom::blink::AuthenticatorStatus::NOT_FOCUSED:
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
index bd627b68..35750d90 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -247,16 +247,42 @@
           kNotAllowedError,
           "The operation either timed out or was not allowed. See: "
           "https://w3c.github.io/webauthn/#sec-assertion-privacy.");
-    case CredentialManagerError::NOT_SUPPORTED:
-      return DOMException::Create(
-          kNotSupportedError,
-          "Parameters for this operation are not supported.");
+    case CredentialManagerError::AUTHENTICATOR_CRITERIA_UNSUPPORTED:
+      return DOMException::Create(kNotSupportedError,
+                                  "The specified `authenticatorSelection` "
+                                  "criteria cannot be fulfilled by CTAP1/U2F "
+                                  "authenticators, and CTAP2 authenticators "
+                                  "are not yet supported.");
+    case CredentialManagerError::ALGORITHM_UNSUPPORTED:
+      return DOMException::Create(kNotSupportedError,
+                                  "None of the algorithms specified in "
+                                  "`pubKeyCredParams` are compatible with "
+                                  "CTAP1/U2F authenticators, and CTAP2 "
+                                  "authenticators are not yet supported.");
+    case CredentialManagerError::EMPTY_ALLOW_CREDENTIALS:
+      return DOMException::Create(kNotSupportedError,
+                                  "The `allowCredentials` list cannot be left "
+                                  "empty for CTAP1/U2F authenticators, and "
+                                  "support for CTAP2 authenticators is not yet "
+                                  "implemented.");
+    case CredentialManagerError::USER_VERIFICATION_UNSUPPORTED:
+      return DOMException::Create(kNotSupportedError,
+                                  "The specified `userVerification` "
+                                  "requirement cannot be fulfilled by "
+                                  "CTAP1/U2F authenticators, and CTAP2 "
+                                  "authenticators are not yet supported.");
     case CredentialManagerError::INVALID_DOMAIN:
       return DOMException::Create(kSecurityError, "This is an invalid domain.");
-    case CredentialManagerError::INVALID_STATE:
+    case CredentialManagerError::CREDENTIAL_EXCLUDED:
       return DOMException::Create(
           kInvalidStateError,
-          "Attempting to register an already-registered key.");
+          "The user attempted to register an authenticator that contains one "
+          "of the credentials already registered with the relying party.");
+    case CredentialManagerError::CREDENTIAL_NOT_RECOGNIZED:
+      return DOMException::Create(kInvalidStateError,
+                                  "The user attempted to use an authenticator "
+                                  "that recognized none of the provided "
+                                  "credentials.");
     case CredentialManagerError::NOT_IMPLEMENTED:
       return DOMException::Create(kNotSupportedError, "Not implemented");
     case CredentialManagerError::NOT_FOCUSED:
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
index 6dea889..91e142f 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
@@ -14,21 +14,64 @@
 
 namespace {
 
-// This is matching the `transition` property from mediaControls.css
-const double kFadeOutDuration = 0.3;
-
 // This is the class name to hide the panel.
 const char kTransparentClassName[] = "transparent";
 
 }  // anonymous namespace
 
+// Listens for the 'transitionend' event.
+class MediaControlPanelElement::TransitionEventListener final
+    : public EventListener {
+ public:
+  using Callback = base::RepeatingCallback<void()>;
+
+  // |element| is the element to listen for the 'transitionend' event on.
+  // |callback| is the callback to call when the event is handled.
+  explicit TransitionEventListener(Element* element, Callback callback)
+      : EventListener(EventListener::kCPPEventListenerType),
+        callback_(callback),
+        element_(element) {
+    DCHECK(callback_);
+    DCHECK(element_);
+
+    element->addEventListener(EventTypeNames::transitionend, this, false);
+  }
+
+  void Detach() {
+    element_->removeEventListener(EventTypeNames::transitionend, this, false);
+  }
+
+  bool operator==(const EventListener& other) const override {
+    return this == &other;
+  }
+
+  virtual void Trace(blink::Visitor* visitor) {
+    EventListener::Trace(visitor);
+    visitor->Trace(element_);
+  }
+
+ private:
+  void handleEvent(ExecutionContext* context, Event* event) {
+    if (event->type() == EventTypeNames::transitionend) {
+      callback_.Run();
+      return;
+    }
+
+    NOTREACHED();
+  }
+
+  Callback callback_;
+  Member<Element> element_;
+};
+
 MediaControlPanelElement::MediaControlPanelElement(
     MediaControlsImpl& media_controls)
     : MediaControlDivElement(media_controls, kMediaControlsPanel),
-      transition_timer_(
-          media_controls.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
+      event_listener_(new MediaControlPanelElement::TransitionEventListener(
           this,
-          &MediaControlPanelElement::TransitionTimerFired) {
+          WTF::BindRepeating(
+              &MediaControlPanelElement::HandleTransitionEndEvent,
+              WrapWeakPersistent(this)))) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-panel"));
 }
 
@@ -49,11 +92,11 @@
   if (opaque_)
     return;
 
-  removeAttribute("class");
   opaque_ = true;
 
   if (is_displayed_) {
     SetIsWanted(true);
+    removeAttribute("class");
     DidBecomeVisible();
   }
 }
@@ -65,7 +108,15 @@
   setAttribute("class", kTransparentClassName);
 
   opaque_ = false;
-  StartTimer();
+}
+
+void MediaControlPanelElement::RemovedFrom(ContainerNode*) {
+  event_listener_->Detach();
+}
+
+void MediaControlPanelElement::Trace(blink::Visitor* visitor) {
+  MediaControlDivElement::Trace(visitor);
+  visitor->Trace(event_listener_);
 }
 
 void MediaControlPanelElement::SetKeepDisplayedForAccessibility(bool value) {
@@ -86,30 +137,15 @@
   return MediaControlElementsHelper::IsUserInteractionEvent(event);
 }
 
-void MediaControlPanelElement::StartTimer() {
-  StopTimer();
-
-  // The timer is required to set the property display:'none' on the panel,
-  // such that captions are correctly displayed at the bottom of the video
-  // at the end of the fadeout transition.
-  // FIXME: Racing a transition with a setTimeout like this is wrong.
-  transition_timer_.StartOneShot(kFadeOutDuration, FROM_HERE);
-}
-
-void MediaControlPanelElement::StopTimer() {
-  transition_timer_.Stop();
-}
-
-void MediaControlPanelElement::TransitionTimerFired(TimerBase*) {
-  if (!opaque_ && !keep_displayed_for_accessibility_)
-    SetIsWanted(false);
-
-  StopTimer();
-}
-
 void MediaControlPanelElement::DidBecomeVisible() {
   DCHECK(is_displayed_ && opaque_);
   MediaElement().MediaControlsDidBecomeVisible();
 }
 
+void MediaControlPanelElement::HandleTransitionEndEvent() {
+  // Hide the element in the DOM once we have finished the transition.
+  if (!opaque_ && !keep_displayed_for_accessibility_)
+    SetIsWanted(false);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h
index 6183f5f..6fa195d 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h
@@ -6,20 +6,21 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_PANEL_ELEMENT_H_
 
 #include "third_party/blink/renderer/modules/media_controls/elements/media_control_div_element.h"
-#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
 
 namespace blink {
 
+class ContainerNode;
 class Event;
 class MediaControlsImpl;
-class TimerBase;
 
-class MediaControlPanelElement final : public MediaControlDivElement {
+class MODULES_EXPORT MediaControlPanelElement final
+    : public MediaControlDivElement {
  public:
   explicit MediaControlPanelElement(MediaControlsImpl&);
 
  public:
-  // Methods called by `MediaContrlsImpl`.
+  // Methods called by `MediaControlsImpl`.
   void SetIsDisplayed(bool);
   bool IsOpaque() const;
   void MakeOpaque();
@@ -27,20 +28,25 @@
 
   void SetKeepDisplayedForAccessibility(bool);
 
+  // Node override;
+  void RemovedFrom(ContainerNode*);
+
+  virtual void Trace(blink::Visitor*);
+
  private:
+  class TransitionEventListener;
+
   void DefaultEventHandler(Event*) override;
   bool KeepEventInNode(Event*) override;
 
-  void StartTimer();
-  void StopTimer();
-  void TransitionTimerFired(TimerBase*);
   void DidBecomeVisible();
+  void HandleTransitionEndEvent();
 
   bool is_displayed_ = false;
   bool opaque_ = true;
   bool keep_displayed_for_accessibility_ = false;
 
-  TaskRunnerTimer<MediaControlPanelElement> transition_timer_;
+  Member<TransitionEventListener> event_listener_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element_test.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element_test.cc
new file mode 100644
index 0000000..1c3c458
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element_test.cc
@@ -0,0 +1,67 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/core/html/media/html_media_element.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
+
+namespace blink {
+
+class MediaControlPanelElementTest : public PageTestBase {
+ public:
+  void SetUp() final {
+    // Create page and add a video element with controls.
+    PageTestBase::SetUp();
+    media_element_ = HTMLVideoElement::Create(GetDocument());
+    media_element_->SetBooleanAttribute(HTMLNames::controlsAttr, true);
+    GetDocument().body()->AppendChild(media_element_);
+
+    // Create instance of MediaControlInputElement to run tests on.
+    media_controls_ =
+        static_cast<MediaControlsImpl*>(media_element_->GetMediaControls());
+    ASSERT_NE(media_controls_, nullptr);
+    panel_element_ = new MediaControlPanelElement(*media_controls_);
+  }
+
+ protected:
+  void SimulateTransitionEnd() { TriggerEvent(EventTypeNames::transitionend); }
+
+  void ExpectPanelIsDisplayed() { EXPECT_TRUE(GetPanel().IsWanted()); }
+
+  void ExpectPanelIsNotDisplayed() { EXPECT_FALSE(GetPanel().IsWanted()); }
+
+  MediaControlPanelElement& GetPanel() { return *panel_element_.Get(); }
+
+ private:
+  void TriggerEvent(const AtomicString& name) {
+    Event* event = Event::Create(name);
+    GetPanel().DispatchEvent(event);
+  }
+
+  Persistent<HTMLMediaElement> media_element_;
+  Persistent<MediaControlsImpl> media_controls_;
+  Persistent<MediaControlPanelElement> panel_element_;
+};
+
+TEST_F(MediaControlPanelElementTest, StateTransitions) {
+  GetPanel().SetIsDisplayed(true);
+  GetPanel().MakeOpaque();
+
+  ExpectPanelIsDisplayed();
+  SimulateTransitionEnd();
+
+  GetPanel().MakeTransparent();
+
+  SimulateTransitionEnd();
+  ExpectPanelIsNotDisplayed();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
index 587e0f90..a800a13 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
@@ -157,6 +157,10 @@
   return true;
 }
 
+void SimulateTransitionEnd(Element& element) {
+  element.DispatchEvent(Event::Create(EventTypeNames::transitionend));
+}
+
 // This must match MediaControlDownloadButtonElement::DownloadActionMetrics.
 enum DownloadActionMetrics {
   kShown = 0,
@@ -1037,6 +1041,7 @@
 
   // Once user interaction stops, controls can hide.
   platform_->RunForPeriodSeconds(2);
+  SimulateTransitionEnd(*panel);
   EXPECT_FALSE(IsElementVisible(*panel));
 }
 
diff --git a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
index 79dcb59c..c8b84dc 100644
--- a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -73,11 +73,15 @@
   background:
     -webkit-image-set(url('default_100_percent/modern/gradient_bg.png') 1x)
     repeat-x bottom left;
+
+  opacity: 1;
+  transition: opacity 0.25s cubic-bezier(0.25, 0.1, 0.25, 1);
 }
 
 audio::-webkit-media-controls-panel.transparent,
 video::-webkit-media-controls-panel.transparent {
   opacity: 0;
+  transition: opacity 1s cubic-bezier(0.25, 0.1, 0.25, 1);
 }
 
 video::-webkit-media-controls-panel.scrubbing-message {
@@ -142,6 +146,20 @@
   display: none;
 }
 
+audio::-internal-media-controls-button-panel,
+video::-internal-media-controls-button-panel,
+audio::-webkit-media-controls-timeline,
+video::-webkit-media-controls-timeline {
+  opacity: 1;
+  transition: opacity 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
+}
+
+.transparent div[pseudo="-internal-media-controls-button-panel"],
+.transparent input[pseudo="-webkit-media-controls-timeline"] {
+  opacity: 0;
+  transition: opacity 0.75s cubic-bezier(0.25, 0.1, 0.25, 1);
+}
+
 /**
  * Media Buttons
  */
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
index 5b49530..51a427d 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
@@ -27,7 +27,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc b/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc
index 78f81307..b92e32a 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc
+++ b/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc
@@ -27,7 +27,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/web/web_speech_grammar.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
index 3bfbebb..38678861 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
@@ -42,12 +42,6 @@
   }
 }
 
-WebThread* AudioWorklet::GetBackingThread() {
-  DCHECK(IsMainThread());
-  DCHECK(GetMessagingProxy());
-  return GetMessagingProxy()->GetBackingWebThread();
-}
-
 BaseAudioContext* AudioWorklet::GetBaseAudioContext() const {
   DCHECK(IsMainThread());
   return context_.Get();
@@ -69,7 +63,7 @@
 
 bool AudioWorklet::IsReady() {
   DCHECK(IsMainThread());
-  return GetMessagingProxy() && GetBackingThread();
+  return GetMessagingProxy() && GetMessagingProxy()->GetBackingWorkerThread();
 }
 
 bool AudioWorklet::NeedsToCreateGlobalScope() {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet.h b/third_party/blink/renderer/modules/webaudio/audio_worklet.h
index e51b092..98b6c46 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet.h
@@ -40,8 +40,6 @@
   // in AudioWorklet or BaseAudioContext.
   void NotifyGlobalScopeIsUpdated();
 
-  WebThread* GetBackingThread();
-
   BaseAudioContext* GetBaseAudioContext() const;
 
   // Returns |nullptr| if there is no active WorkletGlobalScope().
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
index d479341..996496a 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
@@ -78,11 +78,6 @@
   return processor_info_map_.at(name);
 }
 
-WebThread* AudioWorkletMessagingProxy::GetBackingWebThread() {
-  auto worklet_thread = static_cast<AudioWorkletThread*>(GetWorkerThread());
-  return worklet_thread->GetSharedBackingThread();
-}
-
 WorkerThread* AudioWorkletMessagingProxy::GetBackingWorkerThread() {
   return GetWorkerThread();
 }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
index 89714b2..4308120ca 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
@@ -16,7 +16,6 @@
 class CrossThreadAudioWorkletProcessorInfo;
 class ExecutionContext;
 class MessagePortChannel;
-class WebThread;
 class WorkerThread;
 
 // AudioWorkletMessagingProxy is a main thread interface for
@@ -56,7 +55,7 @@
   const Vector<CrossThreadAudioParamInfo> GetParamInfoListForProcessor(
       const String& name) const;
 
-  WebThread* GetBackingWebThread();
+  // Returns a WorkerThread object backs the AudioWorkletThread instance.
   WorkerThread* GetBackingWorkerThread();
 
   void Trace(Visitor*);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
index fc342e0..6cf5fe5 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
@@ -55,8 +55,11 @@
   }
 
   if (Context()->GetExecutionContext()) {
-    task_runner_ =
-        Context()->GetExecutionContext()->GetTaskRunner(TaskType::kUnthrottled);
+    // Cross-thread tasks between AWN/AWP is okay to be throttled, thus
+    // kMiscPlatformAPI. It is for post-creation/destruction chores.
+    main_thread_task_runner_ = Context()->GetExecutionContext()->GetTaskRunner(
+        TaskType::kMiscPlatformAPI);
+    DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
   }
 
   Initialize();
@@ -82,8 +85,7 @@
   // Render and update the node state when the processor is ready with no error.
   // We also need to check if the global scope is valid before we request
   // the rendering in the AudioWorkletGlobalScope.
-  if (processor_ && !processor_->hasErrorOccured() &&
-      Context()->CheckWorkletGlobalScopeOnRenderingThread()) {
+  if (processor_ && !processor_->hasErrorOccured()) {
     Vector<AudioBus*> input_buses;
     Vector<AudioBus*> output_buses;
     for (unsigned i = 0; i < NumberOfInputs(); ++i) {
@@ -161,7 +163,7 @@
     processor_ = processor;
   } else {
     PostCrossThreadTask(
-        *task_runner_, FROM_HERE,
+        *main_thread_task_runner_, FROM_HERE,
         CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError,
                         WrapRefCounted(this),
                         AudioWorkletProcessorErrorState::kConstructionError));
@@ -176,7 +178,7 @@
   AudioWorkletProcessorErrorState error_state = processor_->GetErrorState();
   if (error_state == AudioWorkletProcessorErrorState::kProcessError) {
     PostCrossThreadTask(
-        *task_runner_, FROM_HERE,
+        *main_thread_task_runner_, FROM_HERE,
         CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError,
                         WrapRefCounted(this),
                         error_state));
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
index e29122f..2919c5962 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
@@ -84,8 +84,7 @@
   // method or the value of |tail_time_|.
   bool RequiresTailProcessing() const { return true; }
 
-  // A reference to the main thread task runner.
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
 };
 
 class AudioWorkletNode final : public AudioNode,
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
index 1e844fc7..c86777f0 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -1006,7 +1006,9 @@
   DCHECK(IsMainThread());
   DCHECK(audioWorklet()->IsReady());
 
-  worklet_backing_worker_thread_ =
+  // At this point, the WorkletGlobalScope must be ready so it is safe to keep
+  // the reference to the AudioWorkletThread for the future worklet operation.
+  audio_worklet_thread_ =
       audioWorklet()->GetMessagingProxy()->GetBackingWorkerThread();
 
   // If the context is running or suspended, restart the destination to switch
@@ -1020,27 +1022,12 @@
 void BaseAudioContext::UpdateWorkletGlobalScopeOnRenderingThread() {
   DCHECK(!IsMainThread());
 
-  // Only if the worklet is properly initialized and ready.
-  if (worklet_backing_worker_thread_) {
+  if (audio_worklet_thread_) {
     AudioWorkletGlobalScope* global_scope =
-        ToAudioWorkletGlobalScope(
-              worklet_backing_worker_thread_->GlobalScope());
-
-    // When BaseAudioContext is being torn down, AudioWorkletGlobalScope might
-    // be already gone at this point because it's destroyed on the main thread
-    // but the audio thread may not have stopped. So we check |global_scope|
-    // before we update it.
-    if (global_scope) {
-      global_scope->SetCurrentFrame(CurrentSampleFrame());
-    }
+        ToAudioWorkletGlobalScope(audio_worklet_thread_->GlobalScope());
+    DCHECK(global_scope);
+    global_scope->SetCurrentFrame(CurrentSampleFrame());
   }
 }
 
-bool BaseAudioContext::CheckWorkletGlobalScopeOnRenderingThread() {
-  DCHECK(!IsMainThread());
-
-  return worklet_backing_worker_thread_ &&
-         worklet_backing_worker_thread_->GlobalScope();
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
index 26623cb..19527b1 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -341,22 +341,11 @@
   // the first script evaluation.
   void NotifyWorkletIsReady();
 
-  // Update the information in AudioWorkletGlobalScope if necessary. Must be
-  // called from the rendering thread. Does nothing when the global scope
-  // does not exist.
+  // Update the information in AudioWorkletGlobalScope synchronously on the
+  // worklet rendering thread. Must be called from the rendering thread.
+  // Does nothing when the worklet global scope does not exist.
   void UpdateWorkletGlobalScopeOnRenderingThread();
 
-  // In the shut-down process, the AudioWorkletGlobalScope can already be gone
-  // while the backing worker thread is still running. This is called by
-  // AudioWorkletHandler before it requests the render task to the processor
-  // which lives on the AudioWorkletGlobalScope. Returns true if there is a
-  // valid WorkletGloblaScope for the worklet-related task.
-  //
-  // TODO(hongchan): This is a short-term fix for https://crbug.com/822725.
-  // The lifetime of the render task should be managed by not the explicit
-  // context check but per-global-scope task queues.
-  bool CheckWorkletGlobalScopeOnRenderingThread();
-
  protected:
   enum ContextType { kRealtimeContext, kOfflineContext };
 
@@ -529,9 +518,12 @@
 
   Member<AudioWorklet> audio_worklet_;
 
-  // Only for the access to AudioWorkletGlobalScope from the render thread.
-  // Use the WebThread in the destination nodes for the task scheduling.
-  WorkerThread* worklet_backing_worker_thread_ = nullptr;
+  // In order to update some information (e.g. current frame) in
+  // AudioWorkletGlobalScope *synchronously*, the context needs to keep the
+  // reference to the WorkerThread associated with the AudioWorkletGlobalScope.
+  // This cannot be nullptr once it is assigned from AudioWorkletThread until
+  // the BaseAudioContext goes away.
+  WorkerThread* audio_worklet_thread_ = nullptr;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
index c077de3..50b4033 100644
--- a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
 #include "third_party/blink/renderer/core/dom/exception_code.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
 #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
 
 namespace blink {
@@ -90,11 +91,13 @@
 void DefaultAudioDestinationHandler::StartDestination() {
   DCHECK(!destination_->IsPlaying());
 
-  // Use Experimental AudioWorkletThread only when AudioWorklet is enabled, and
-  // the worklet thread and the global scope are ready.
-  if (Context()->audioWorklet() && Context()->audioWorklet()->IsReady()) {
-    destination_->StartWithWorkletThread(
-        Context()->audioWorklet()->GetBackingThread());
+  AudioWorklet* audio_worklet = Context()->audioWorklet();
+  if (audio_worklet && audio_worklet->IsReady()) {
+    // This task runner is only used to fire the audio render callback, so it
+    // MUST not be throttled to avoid potential audio glitch.
+    destination_->StartWithWorkletTaskRunner(
+        audio_worklet->GetMessagingProxy()->GetBackingWorkerThread()
+                     ->GetTaskRunner(TaskType::kUnthrottled));
   } else {
     destination_->Start();
   }
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
index adeccd8..dc9595e 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
 #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
@@ -58,8 +59,9 @@
   SetInternalChannelInterpretation(AudioBus::kSpeakers);
 
   if (Context()->GetExecutionContext()) {
-    task_runner_ = Context()->GetExecutionContext()->GetTaskRunner(
-        TaskType::kMediaElementEvent);
+    main_thread_task_runner_ = Context()->GetExecutionContext()->GetTaskRunner(
+        TaskType::kMiscPlatformAPI);
+    DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
   }
 }
 
@@ -93,7 +95,6 @@
     return;
 
   render_thread_.reset();
-  worklet_backing_thread_ = nullptr;
 
   AudioHandler::Uninitialize();
 }
@@ -108,14 +109,14 @@
 
 void OfflineAudioDestinationHandler::StartRendering() {
   DCHECK(IsMainThread());
-  DCHECK(GetRenderingThread());
   DCHECK(render_target_);
+  DCHECK(render_thread_task_runner_);
 
   // Rendering was not started. Starting now.
   if (!is_rendering_started_) {
     is_rendering_started_ = true;
     PostCrossThreadTask(
-        *GetRenderingThread()->GetTaskRunner(), FROM_HERE,
+        *render_thread_task_runner_, FROM_HERE,
         CrossThreadBind(&OfflineAudioDestinationHandler::StartOfflineRendering,
                         WrapRefCounted(this)));
     return;
@@ -124,7 +125,7 @@
   // Rendering is already started, which implicitly means we resume the
   // rendering by calling |doOfflineRendering| on the render thread.
   PostCrossThreadTask(
-      *GetRenderingThread()->GetTaskRunner(), FROM_HERE,
+      *render_thread_task_runner_, FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::DoOfflineRendering,
                       WrapRefCounted(this)));
 }
@@ -144,19 +145,12 @@
     AudioBuffer* render_target) {
   DCHECK(IsMainThread());
 
-  // Use Experimental AudioWorkletThread only when AudioWorklet is enabled, and
-  // the worklet thread and the global scope are ready.
-  if (Context()->audioWorklet() && Context()->audioWorklet()->IsReady()) {
-    worklet_backing_thread_ = Context()->audioWorklet()->GetBackingThread();
-  } else {
-    render_thread_ = Platform::Current()->CreateThread(
-        WebThreadCreationParams(WebThreadType::kOfflineAudioRenderThread));
-  }
-
   render_target_ = render_target;
   render_bus_ = AudioBus::Create(render_target->numberOfChannels(),
                                  AudioUtilities::kRenderQuantumFrames);
   DCHECK(render_bus_);
+
+  PrepareTaskRunnerForRendering();
 }
 
 void OfflineAudioDestinationHandler::StartOfflineRendering() {
@@ -200,7 +194,7 @@
     bool has_lock = ProcessHeap::CrossThreadPersistentMutex().TryLock();
     if (!has_lock) {
       // To ensure that the rendering step eventually happens, repost.
-      GetRenderingThread()->GetTaskRunner()->PostTask(
+      render_thread_task_runner_->PostTask(
           FROM_HERE,
           WTF::Bind(&OfflineAudioDestinationHandler::DoOfflineRendering,
                     WrapRefCounted(this)));
@@ -250,7 +244,7 @@
 
   // The actual rendering has been suspended. Notify the context.
   PostCrossThreadTask(
-      *task_runner_, FROM_HERE,
+      *main_thread_task_runner_, FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::NotifySuspend,
                       WrapRefCounted(this), Context()->CurrentSampleFrame()));
 }
@@ -260,7 +254,7 @@
 
   // The actual rendering has been completed. Notify the context.
   PostCrossThreadTask(
-      *task_runner_, FROM_HERE,
+      *main_thread_task_runner_, FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::NotifyComplete,
                       WrapRefCounted(this)));
 }
@@ -275,7 +269,6 @@
 void OfflineAudioDestinationHandler::NotifyComplete() {
   DCHECK(IsMainThread());
 
-  // Nullify the rendering thread to save the system resource.
   render_thread_.reset();
 
   // The OfflineAudioContext might be gone.
@@ -359,27 +352,46 @@
   return false;
 }
 
-WebThread* OfflineAudioDestinationHandler::GetRenderingThread() {
-  DCHECK(IsInitialized());
+void OfflineAudioDestinationHandler::PrepareTaskRunnerForRendering() {
+  DCHECK(IsMainThread());
 
-  if (worklet_backing_thread_) {
-    return worklet_backing_thread_;
+  AudioWorklet* audio_worklet = Context()->audioWorklet();
+  if (audio_worklet && audio_worklet->IsReady()) {
+    if (!render_thread_) {
+      // The context (re)started with the AudioWorklet mode. Assign the task
+      // runner only when it is not set yet.
+      if (!render_thread_task_runner_) {
+        render_thread_task_runner_ =
+            audio_worklet->GetMessagingProxy()->GetBackingWorkerThread()
+                         ->GetTaskRunner(TaskType::kMiscPlatformAPI);
+      }
+    } else {
+      // The AudioWorklet is activated and the render task runner should be
+      // changed.
+      render_thread_ = nullptr;
+      render_thread_task_runner_ =
+          audio_worklet->GetMessagingProxy()->GetBackingWorkerThread()
+                       ->GetTaskRunner(TaskType::kMiscPlatformAPI);
+    }
+  } else {
+    if (!render_thread_) {
+      // The context started from the non-AudioWorklet mode.
+      render_thread_ = Platform::Current()->CreateThread(
+          WebThreadCreationParams(WebThreadType::kOfflineAudioRenderThread));
+      render_thread_task_runner_ = render_thread_->GetTaskRunner();
+    }
   }
 
-  DCHECK(render_thread_);
-  return render_thread_.get();
+  // The task runner MUST be valid at this point.
+  DCHECK(render_thread_task_runner_);
 }
 
 void OfflineAudioDestinationHandler::RestartRendering() {
   DCHECK(IsMainThread());
 
-  // If the worklet thread is not assigned yet, that means the context has
-  // started without a valid WorkletGlobalScope. Assign the worklet thread,
-  // and it will be picked up when the GetRenderingThread() is called next.
-  if (Context()->audioWorklet() && Context()->audioWorklet()->IsReady() &&
-      !worklet_backing_thread_) {
-    worklet_backing_thread_ = Context()->audioWorklet()->GetBackingThread();
-  }
+  // The rendering thread might have been changed, so we need to set up the
+  // task runner again.
+  PrepareTaskRunnerForRendering();
 };
 
 // ----------------------------------------------------------------
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
index 25a082f..1928524 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
@@ -123,11 +123,13 @@
                             AudioBus* destination_bus,
                             size_t number_of_frames);
 
-  // The context can run on two types of threads: when the AudioWorklet is
-  // enabled, the context runs on AudioWorkletThread whereas it runs on the
-  // normal WebThread owned by AudioDestination without AudioWorklet feature.
-  // This method returns the current thread regardless of the thread type.
-  WebThread* GetRenderingThread();
+  // Prepares a task runner for the rendering based on the operation mode
+  // (i.e. non-AudioWorklet or AudioWorklet). This is called when the
+  // rendering restarts such as context.resume() after context.suspend().
+  // The only possible transition is from the non-AudioWorklet mode to the
+  // AudioWorklet mode. Once the AudioWorklet mode is activated, the task runner
+  // from AudioWorkletThread will be used until the rendering is finished.
+  void PrepareTaskRunnerForRendering();
 
   // This AudioHandler renders into this AudioBuffer.
   // This Persistent doesn't make a reference cycle including the owner
@@ -136,13 +138,6 @@
   // Temporary AudioBus for each render quantum.
   scoped_refptr<AudioBus> render_bus_;
 
-  // Rendering thread.
-  std::unique_ptr<WebThread> render_thread_;
-
-  // The experimental worklet rendering thread. Points the thread borrowed from
-  // AudioWorkletThread.
-  WebThread* worklet_backing_thread_ = nullptr;
-
   // These variables are for counting the number of frames for the current
   // progress and the remaining frames to be processed.
   size_t frames_processed_;
@@ -156,7 +151,12 @@
   unsigned number_of_channels_;
   float sample_rate_;
 
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  // The rendering thread for the non-AudioWorklet mode. For the AudioWorklet
+  // node, AudioWorkletThread will drive the rendering.
+  std::unique_ptr<WebThread> render_thread_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
 };
 
 class OfflineAudioDestinationNode final : public AudioDestinationNode {
diff --git a/third_party/blink/renderer/platform/audio/audio_destination.cc b/third_party/blink/renderer/platform/audio/audio_destination.cc
index bb261935..962fd2b 100644
--- a/third_party/blink/renderer/platform/audio/audio_destination.cc
+++ b/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -106,9 +106,6 @@
   TRACE_EVENT_BEGIN2("webaudio", "AudioDestination::Render",
                      "callback_buffer_size", number_of_frames, "frames skipped",
                      prior_frames_skipped);
-  DCHECK(
-      !(worklet_backing_thread_ && worklet_backing_thread_->IsCurrentThread()));
-
   CHECK_EQ(destination_data.size(), number_of_output_channels_);
   CHECK_EQ(number_of_frames, callback_buffer_size_);
 
@@ -132,11 +129,11 @@
 
   size_t frames_to_render = fifo_->Pull(output_bus_.get(), number_of_frames);
 
-  // Use the dual-thread rendering model if the thread from AudioWorkletThread
-  // is available.
-  if (worklet_backing_thread_) {
+ // Use the dual-thread rendering model if the AudioWorklet is activated.
+  if (worklet_task_runner_) {
     PostCrossThreadTask(
-        *worklet_backing_thread_->GetTaskRunner(), FROM_HERE,
+        *worklet_task_runner_,
+        FROM_HERE,
         CrossThreadBind(&AudioDestination::RequestRender, WrapRefCounted(this),
                         number_of_frames, frames_to_render, delay,
                         delay_timestamp, prior_frames_skipped));
@@ -158,9 +155,6 @@
                "frames_to_render", frames_to_render, "timestamp (s)",
                delay_timestamp);
 
-  DCHECK(
-      !worklet_backing_thread_ || worklet_backing_thread_->IsCurrentThread());
-
   frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
   AudioIOPosition output_position;
   output_position.position =
@@ -205,13 +199,13 @@
   }
 }
 
-void AudioDestination::StartWithWorkletThread(
-    WebThread* worklet_backing_thread) {
+void AudioDestination::StartWithWorkletTaskRunner(
+    scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner) {
   DCHECK(IsMainThread());
 
   if (web_audio_device_ && !is_playing_) {
     TRACE_EVENT0("webaudio", "AudioDestination::Start");
-    worklet_backing_thread_ = worklet_backing_thread;
+    worklet_task_runner_ = std::move(worklet_task_runner);
     web_audio_device_->Start();
     is_playing_ = true;
   }
@@ -225,7 +219,7 @@
   if (web_audio_device_ && is_playing_) {
     TRACE_EVENT0("webaudio", "AudioDestination::Stop");
     web_audio_device_->Stop();
-    worklet_backing_thread_ = nullptr;
+    worklet_task_runner_ = nullptr;
     is_playing_ = false;
   }
 }
diff --git a/third_party/blink/renderer/platform/audio/audio_destination.h b/third_party/blink/renderer/platform/audio/audio_destination.h
index 973ddad..b73e61a 100644
--- a/third_party/blink/renderer/platform/audio/audio_destination.h
+++ b/third_party/blink/renderer/platform/audio/audio_destination.h
@@ -94,8 +94,9 @@
   virtual void Start();
   virtual void Stop();
 
-  // For AudioWorklet experimental threading.
-  void StartWithWorkletThread(WebThread* worklet_backing_thread);
+  // Starts the destination with the AudioWorklet support.
+  void StartWithWorkletTaskRunner(
+      scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner);
 
   // Getters must be accessed from the main thread.
   size_t CallbackBufferSize() const;
@@ -124,9 +125,9 @@
   size_t callback_buffer_size_;
   bool is_playing_;
 
-  // The experimental rendering thread from AudioWorkletThread. This stays
-  // |nullptr| when AudioWorklet is not enabled.
-  WebThread* worklet_backing_thread_ = nullptr;
+  // The task runner for AudioWorklet operation. This is only valid when
+  // the AudioWorklet is activated.
+  scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner_;
 
   // Can be accessed by both threads: resolves the buffer size mismatch between
   // the WebAudio engine and the callback function from the actual audio device.
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 5316fdbd..d65f6e9d 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -156,6 +156,10 @@
   RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableLazyFrameLoading(bool enable) {
+  RuntimeEnabledFeatures::SetLazyFrameLoadingEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableLazyParseCSS(bool enable) {
   RuntimeEnabledFeatures::SetLazyParseCSSEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
index 03b60ea98..13c9392 100644
--- a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
+++ b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
@@ -216,6 +216,8 @@
       return true;
     case mojom::FeaturePolicyFeature::kUnsizedMedia:
       return RuntimeEnabledFeatures::FeaturePolicyExperimentalFeaturesEnabled();
+    case mojom::FeaturePolicyFeature::kVerticalScroll:
+      return RuntimeEnabledFeatures::FeaturePolicyExperimentalFeaturesEnabled();
     default:
       return false;
   }
@@ -268,6 +270,8 @@
                                    mojom::FeaturePolicyFeature::kSyncScript);
       default_feature_name_map.Set("unsized-media",
                                    mojom::FeaturePolicyFeature::kUnsizedMedia);
+      default_feature_name_map.Set(
+          "vertical-scroll", mojom::FeaturePolicyFeature::kVerticalScroll);
     }
     if (RuntimeEnabledFeatures::FeaturePolicyAutoplayFeatureEnabled()) {
       default_feature_name_map.Set("autoplay",
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index e7711c9e..0122380a 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -29,7 +29,6 @@
 #include <utility>
 
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "components/viz/common/resources/transferable_resource.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc b/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
index 7f7aae1..de63be8 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/resources/layer_tree_resource_provider.h"
 #include "cc/resources/video_resource_updater.h"
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc
index 7b8e31d..f4509a7e 100644
--- a/third_party/blink/renderer/platform/heap/heap.cc
+++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -738,16 +738,13 @@
   return true;
 }
 
-void ThreadHeap::WriteBarrier(const void* value) {
-  if (!value || !thread_state_->IsIncrementalMarking())
-    return;
-
-  WriteBarrierInternal(PageFromObject(value), value);
-}
-
-void ThreadHeap::WriteBarrierInternal(BasePage* page, const void* value) {
+void ThreadHeap::WriteBarrier(void* value) {
   DCHECK(thread_state_->IsIncrementalMarking());
   DCHECK(value);
+  // '-1' is used to indicate deleted values.
+  DCHECK_NE(value, reinterpret_cast<void*>(-1));
+
+  BasePage* const page = PageFromObject(value);
   HeapObjectHeader* const header =
       page->IsLargeObjectPage()
           ? static_cast<LargeObjectPage*>(page)->GetHeapObjectHeader()
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h
index 66e11283..f18a6f95 100644
--- a/third_party/blink/renderer/platform/heap/heap.h
+++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -465,9 +465,6 @@
   enum SnapshotType { kHeapSnapshot, kFreelistSnapshot };
   void TakeSnapshot(SnapshotType);
 
-  // Write barrier used after adding an object to the graph.
-  void WriteBarrier(const void* value);
-
 #if defined(ADDRESS_SANITIZER)
   void PoisonEagerArena();
   void PoisonAllHeaps();
@@ -495,9 +492,9 @@
 
   void InvokeEphemeronCallbacks(Visitor*);
 
-  // Fast write barrier assuming that incremental marking is running and
-  // |value| is not nullptr.
-  void WriteBarrierInternal(BasePage*, const void* value);
+  // Write barrier assuming that incremental marking is running and value is not
+  // nullptr. Use MarkingVisitor::WriteBarrier as entrypoint.
+  void WriteBarrier(void* value);
 
   ThreadState* thread_state_;
   ThreadHeapStats stats_;
@@ -532,6 +529,7 @@
   static ThreadHeap* main_thread_heap_;
 
   friend class incremental_marking_test::IncrementalMarkingScopeBase;
+  friend class MarkingVisitor;
   template <typename T>
   friend class Member;
   friend class ThreadState;
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h
index 6219338e..58e6656 100644
--- a/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -129,12 +129,7 @@
   static bool ExpandHashTableBacking(void*, size_t);
 
   static void BackingWriteBarrier(void* address) {
-#if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
-    if (!address || !ThreadState::IsAnyIncrementalMarking())
-      return;
-    ThreadState* state = PageFromObject(address)->Arena()->GetThreadState();
-    state->Heap().WriteBarrier(address);
-#endif
+    MarkingVisitor::WriteBarrier(address);
   }
 
   template <typename Return, typename Metadata>
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index 729feaf..c1db012 100644
--- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -256,16 +256,15 @@
   {
     ExpectWriteBarrierFires<Object> scope(ThreadState::Current(), {object});
     EXPECT_FALSE(object->IsMarked());
-    ThreadState::Current()->Heap().WriteBarrier(object);
+    MarkingVisitor::WriteBarrier(object);
     EXPECT_TRUE(object->IsMarked());
   }
 }
 
 TEST(IncrementalMarkingTest, ManualWriteBarrierBailoutWhenMarkingIsOff) {
   Object* object = Object::Create();
-  ThreadHeap& heap = ThreadState::Current()->Heap();
   EXPECT_FALSE(object->IsMarked());
-  heap.WriteBarrier(object);
+  MarkingVisitor::WriteBarrier(object);
   EXPECT_FALSE(object->IsMarked());
 }
 
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.h b/third_party/blink/renderer/platform/heap/marking_visitor.h
index db73a7c..ec072aca4 100644
--- a/third_party/blink/renderer/platform/heap/marking_visitor.h
+++ b/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MARKING_VISITOR_H_
 
 #include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
 #include "third_party/blink/renderer/platform/heap/heap_page.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
 
@@ -34,6 +35,8 @@
 
   static std::unique_ptr<MarkingVisitor> Create(ThreadState*, MarkingMode);
 
+  inline static void WriteBarrier(void* value);
+
   MarkingVisitor(ThreadState*, MarkingMode);
   virtual ~MarkingVisitor();
 
@@ -170,6 +173,19 @@
   }
 }
 
+inline void MarkingVisitor::WriteBarrier(void* value) {
+#if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
+  if (!ThreadState::IsAnyIncrementalMarking() || !value)
+    return;
+
+  ThreadState* const thread_state = ThreadState::Current();
+  if (!thread_state->IsIncrementalMarking())
+    return;
+
+  thread_state->Heap().WriteBarrier(value);
+#endif  // BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
+}
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MARKING_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/heap/member.h b/third_party/blink/renderer/platform/heap/member.h
index 318d61608..10e22d4 100644
--- a/third_party/blink/renderer/platform/heap/member.h
+++ b/third_party/blink/renderer/platform/heap/member.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
 #include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "third_party/blink/renderer/platform/heap/marking_visitor.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
@@ -270,17 +271,11 @@
   }
 
  protected:
-  ALWAYS_INLINE void WriteBarrier(const T* value) const {
+  ALWAYS_INLINE void WriteBarrier(T* value) const {
 #if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
-    if (LIKELY(value && !this->IsHashTableDeletedValue()) &&
-        ThreadState::IsAnyIncrementalMarking()) {
-      ThreadState* const thread_state = ThreadState::Current();
-      if (thread_state->IsIncrementalMarking()) {
-        // The following method for retrieving a page works as allocation of
-        // mixins on large object pages is prohibited.
-        BasePage* const page = PageFromObject(value);
-        thread_state->Heap().WriteBarrierInternal(page, value);
-      }
+    if (LIKELY(!this->IsHashTableDeletedValue())) {
+      MarkingVisitor::WriteBarrier(
+          const_cast<typename std::remove_const<T>::type*>(value));
     }
 #endif  // BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
   }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 480a52b..619f376 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -614,6 +614,9 @@
       name: "LayoutNGFragmentCaching",
     },
     {
+      name: "LazyFrameLoading",
+    },
+    {
       name: "LazyInitializeMediaControls",
       // This is enabled by features::kLazyInitializeMediaControls.
     },
diff --git a/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
index 604ed61a..776ca64 100644
--- a/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc
index f9e66791..98b4c60 100644
--- a/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/third_party/blink/renderer/platform/scheduler/child/task_runner_impl.cc b/third_party/blink/renderer/platform/scheduler/child/task_runner_impl.cc
index 396b19f..56ec26c 100644
--- a/third_party/blink/renderer/platform/scheduler/child/task_runner_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/task_runner_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/child/web_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/child/web_scheduler_impl.cc
index 4af1b1dc..eb441b5 100644
--- a/third_party/blink/renderer/platform/scheduler/child/web_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/web_scheduler_impl.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_runner_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
index 19191c5..a38cde6 100644
--- a/third_party/blink/renderer/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_simple_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
index e7a1135..c5e3720d 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
index 53825c1a..df387275 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
@@ -6,7 +6,6 @@
 
 #include <cstdint>
 
-#include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
index b99fe706..6eade22 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
@@ -7,7 +7,6 @@
 #include <cstdint>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc
index a222c64..c04c216 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include "base/command_line.h"
+#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/time/default_tick_clock.h"
diff --git a/third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc b/third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc
index e9c7bff7..92390ab 100644
--- a/third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc
+++ b/third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/time/time_override.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/renderer/queueing_time_estimator.cc b/third_party/blink/renderer/platform/scheduler/renderer/queueing_time_estimator.cc
index b0b9c77..75a6ed7 100644
--- a/third_party/blink/renderer/platform/scheduler/renderer/queueing_time_estimator.cc
+++ b/third_party/blink/renderer/platform/scheduler/renderer/queueing_time_estimator.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/scheduler/renderer/queueing_time_estimator.h"
 
-#include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
 
 #include <algorithm>
diff --git a/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.cc b/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.cc
index 957a0bc..fda14d3 100644
--- a/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/time/default_tick_clock.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc b/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc
index c4a16ae..9b1e876 100644
--- a/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/values.h"
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc
index 8b43c1e..506fda0 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
index 4ed248ca..fe4fb13d 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc b/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc
index 4a35ef9..743f827f1e 100644
--- a/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc
+++ b/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc
@@ -32,7 +32,6 @@
 #include <string.h>
 #include <unicode/ucol.h>
 #include <memory>
-#include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index a879498..ef97e284 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Thursday March 29 2018
+Date: Monday April 09 2018
 Branch: master
-Commit: d636fe53af525c30f3bbd7224e7e56d447d0eb3d
+Commit: be5df6080154e58db88fa3640e127efd18c04bde
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
index ad8928bf..9770717 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
@@ -1723,10 +1723,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
index 2ad16428..4e665cc 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -3642,10 +3642,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
index 4f34b7a..49a73711 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -2955,10 +2955,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
index 2ad16428..4e665cc 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -3642,10 +3642,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
index 4f34b7a..49a73711 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -2955,10 +2955,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
index ad8928bf..9770717 100644
--- a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
@@ -1723,10 +1723,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index f93e75fe..cf24c88 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  7
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "233-gd636fe53a"
+#define VERSION_EXTRA  "262-gbe5df6080"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.7.0-233-gd636fe53a"
-#define VERSION_STRING      " v1.7.0-233-gd636fe53a"
+#define VERSION_STRING_NOSP "v1.7.0-262-gbe5df6080"
+#define VERSION_STRING      " v1.7.0-262-gbe5df6080"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
index 2ad16428..4e665cc 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -3642,10 +3642,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
index 4f34b7a..49a73711 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -2955,10 +2955,10 @@
 #define vpx_highbd_avg_8x8 vpx_highbd_avg_8x8_c
 
 void vpx_highbd_comp_avg_pred_c(uint16_t* comp_pred,
-                                const uint8_t* pred8,
+                                const uint16_t* pred,
                                 int width,
                                 int height,
-                                const uint8_t* ref8,
+                                const uint16_t* ref,
                                 int ref_stride);
 #define vpx_highbd_comp_avg_pred vpx_highbd_comp_avg_pred_c
 
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn
index 93d4cc0..46abef1 100644
--- a/third_party/sqlite/BUILD.gn
+++ b/third_party/sqlite/BUILD.gn
@@ -215,7 +215,7 @@
     ]
   }
 
-  if (is_posix) {
+  if (is_posix || is_fuchsia) {
     defines += [
       # Allow xSleep() call on Unix to use usleep() rather than sleep(), so it
       # will have microsecond precision.  Should only affect contended
diff --git a/tools/android/sdk_updater/update_sdk.py b/tools/android/sdk_updater/update_sdk.py
index 7fad775..f1e9fd8 100755
--- a/tools/android/sdk_updater/update_sdk.py
+++ b/tools/android/sdk_updater/update_sdk.py
@@ -35,6 +35,7 @@
 """
 
 import argparse
+import contextlib
 import os
 import re
 import shutil
@@ -46,7 +47,14 @@
 _SRC_ROOT = os.path.realpath(
     os.path.join(os.path.dirname(__file__), '..', '..', '..'))
 
-_SDK_ROOT = os.path.join(_SRC_ROOT, 'third_party', 'android_sdk', 'public')
+_SRC_DEPS_PATH = os.path.join(_SRC_ROOT, 'DEPS')
+
+_SDK_PUBLIC_ROOT = os.path.join(_SRC_ROOT, 'third_party', 'android_sdk',
+                                'public')
+
+_SDK_SOURCES_ROOT = os.path.join(_SRC_ROOT, 'third_party', 'android_sdk',
+                                 'sources')
+
 
 # TODO(shenghuazhang): Update sdkmanager path when gclient can download SDK
 # via CIPD: crug/789809
@@ -56,7 +64,7 @@
 _ANDROID_CONFIG_GNI_PATH = os.path.join(_SRC_ROOT, 'build', 'config',
                                         'android', 'config.gni')
 
-_TOOLS_LIB_PATH = os.path.join(_SDK_ROOT, 'tools', 'lib')
+_TOOLS_LIB_PATH = os.path.join(_SDK_PUBLIC_ROOT, 'tools', 'lib')
 
 _DEFAULT_DOWNLOAD_PACKAGES = [
   'build-tools',
@@ -65,10 +73,12 @@
   'tools'
 ]
 
+# TODO(shenghuazhang): Search package versions from available packages through
+# the sdkmanager, instead of hardcoding the package names w/ version.
 _DEFAULT_PACKAGES_DICT = {
   'build-tools': 'build-tools;27.0.3',
   'platforms': 'platforms;android-27',
-  'sources': 'sources;android-26',
+  'sources': 'sources;android-27',
 }
 
 _GN_ARGUMENTS_TO_UPDATE = {
@@ -90,7 +100,7 @@
   If package isn't provided, update build-tools, platform-tools, platforms,
   and tools.
   """
-  for pkg in arguments.packages:
+  for pkg in arguments.package:
     # If package is not a sdk-style path, try to match a default path to it.
     if pkg in _DEFAULT_PACKAGES_DICT:
       print 'Coercing %s to %s' % (pkg, _DEFAULT_PACKAGES_DICT[pkg])
@@ -108,7 +118,7 @@
     subprocess.check_call(download_sdk_cmd)
 
 
-def _FindPackageVersion(package):
+def _FindPackageVersion(package, sdk_root):
   """Find sdk package version
 
   Two options for package version:
@@ -118,8 +128,10 @@
   """
   sdkmanager_list_cmd = [
       _SDKMANAGER_PATH,
-      '--list'
+      '--list',
+      '--sdk_root=%s' % sdk_root,
   ]
+
   if package in _DEFAULT_PACKAGES_DICT:
     # Get the version after ';' from package name
     package = _DEFAULT_PACKAGES_DICT[package]
@@ -143,14 +155,13 @@
     # by the first new line, the check loop should be ended when reaches a '\n'.
     output = subprocess.check_output(sdkmanager_list_cmd)
     for line in output.splitlines():
-      if package in line:
+      if ' ' + package + ' ' in line:
         # if found package path, catch its version which in the first '|...|'
         return line.split('|')[1].strip()
       if line == '\n': # Reaches the end of 'Installed packages' list
         break
     raise Exception('Cannot find the version of package %s' % package)
 
-
 def _ReplaceVersionInFile(file_path, pattern, version, dry_run=False):
   """Replace the version of sdk package argument in file.
 
@@ -165,21 +176,18 @@
     dry_run: Bool. To show what packages would be created and packages, without
              actually doing either.
   """
-  try:
-    with tempfile.NamedTemporaryFile(delete=False) as temp_file:
-      with open(file_path) as f:
-        for line in f:
-          new_line = re.sub(pattern, r'\g<1>"%s"\n' % version, line)
-          if new_line != line:
-            print '    Note: file %s argument %s would be updated to "%s".' % (
-                  file_path, line.strip(), version)
-          temp_file.write(new_line)
+  with tempfile.NamedTemporaryFile() as temp_file:
+    with open(file_path) as f:
+      for line in f:
+        new_line = re.sub(pattern, r'\g<1>"%s"\n' % version, line)
+        if new_line != line:
+          print ('    Note: file "%s" argument ' % file_path  +
+                '"%s" would be updated to "%s".' % (line.strip(), version))
+        temp_file.write(new_line)
     if not dry_run:
+      temp_file.flush()
       shutil.move(temp_file.name, file_path)
-
-  finally:
-    if os.path.exists(temp_file.name):
-      os.remove(temp_file.name)
+      temp_file.delete = False
 
 
 def UploadSdkPackage(sdk_root, dry_run, service_url, package, yaml_file,
@@ -205,8 +213,8 @@
     raise IOError('Cannot find .yaml file for package %s' % package)
 
   if dry_run:
-    print 'This `package` command (without -n/--dry-run) would create and',
-    print 'upload the package %s version:%s to CIPD.' % (package, pkg_version)
+    print ('This `package` command (without -n/--dry-run) would create and ' +
+           'upload the package %s version:%s to CIPD.' % (package, pkg_version))
   else:
     upload_sdk_cmd = [
       'cipd', 'create',
@@ -220,6 +228,65 @@
 
     subprocess.check_call(upload_sdk_cmd)
 
+@contextlib.contextmanager
+def UpdateDepsFile(package, pkg_version, deps_path, dry_run,
+                   release_version=None):
+  """Find the sdk pkg version in DEPS and modify it as cipd uploading version.
+
+  TODO(shenghuazhang): use DEPS edition operations after issue crbug.com/760633
+  fixed.
+
+  DEPS file hooks sdk package with version with suffix -crX, e.g. '26.0.2-cr1'.
+  If pkg_version is the base number of the existing version in DEPS, e.g.
+  '26.0.2', return '26.0.2-cr2' as the version uploading to CIPD. If not the
+  base number, return ${pkg_version}-cr0.
+
+  Args:
+    package: The name of the package.
+    pkg_version: The new version of the package.
+    deps_path: Path to deps file which gclient hooks sdk pkg w/ versions.
+    dry_run: Bool. To show what packages would be created and packages, without
+             actually doing either.
+    release_version: Android sdk release version e.g. 'o_mr1', 'p'.
+  """
+  var_package = package
+  if release_version:
+    var_package = release_version + '_' + var_package
+  package_var_pattern = re.compile(
+      # Match the argument with "'sdk_*_version': 'version:" with whitespaces.
+      r'(^\s*\'android_sdk_%s_version\'\s*:\s*\'version:)' % var_package +
+      # version number with right single quote. E.g. 27.0.1-cr0.
+      r'([-\w\s.]+)'
+      # End of string
+      r'(\',?$)'
+  )
+
+  with tempfile.NamedTemporaryFile() as temp_file:
+    with open(deps_path) as f:
+      for line in f:
+        new_line = line
+        found = re.match(package_var_pattern, line)
+        if found:
+          # Check if pkg_version as base version already exists in deps
+          deps_version = found.group(2)
+          match = re.match(r'%s-cr([\d+])' % pkg_version, deps_version)
+          suffix_number = 0
+          if match:
+            suffix_number = 1 + int(match.group(1))
+          version = '%s-cr%d' % (pkg_version, suffix_number)
+          new_line = re.sub(package_var_pattern, r'\g<1>%s\g<3>' % version,
+                            line)
+          print ('    Note: deps file "%s" argument ' % deps_path +
+                 '"%s" would be updated to "%s".' % (line.strip(), version))
+        temp_file.write(new_line)
+
+    yield version
+
+    if not dry_run:
+      temp_file.flush()
+      shutil.move(temp_file.name, deps_path)
+      temp_file.delete = False
+
 
 def ChangeVersionInGNI(package, arg_version, gn_args_dict, gni_file_path,
                        dry_run):
@@ -278,14 +345,21 @@
   for package in packages:
     pkg_version = arguments.version
     if not pkg_version:
-      pkg_version = _FindPackageVersion(package)
-    UploadSdkPackage(arguments.sdk_root, arguments.dry_run,
-                     arguments.service_url, package, arguments.yaml_file,
-                     pkg_version, arguments.verbose)
+      pkg_version = _FindPackageVersion(package, arguments.sdk_root)
+
+    # Upload SDK package to cipd, and update the package version hooking
+    # in DEPS file.
+    with UpdateDepsFile(package, pkg_version, _SRC_DEPS_PATH,
+                        arguments.dry_run) as deps_pkg_version:
+      UploadSdkPackage(os.path.join(arguments.sdk_root, '..'),
+                       arguments.dry_run, arguments.service_url, package,
+                       arguments.yaml_file, deps_pkg_version,
+                       arguments.verbose)
 
     if package in _GN_ARGUMENTS_TO_UPDATE:
+      # Update the package version config in gn file
       arg_version = _GetArgVersion(pkg_version, package)
-      ChangeVersionInGNI(package, pkg_version, _GN_ARGUMENTS_TO_UPDATE,
+      ChangeVersionInGNI(package, arg_version, _GN_ARGUMENTS_TO_UPDATE,
                          _ANDROID_CONFIG_GNI_PATH, arguments.dry_run)
 
 
@@ -302,16 +376,15 @@
   download_parser.set_defaults(func=_DownloadSdk)
   download_parser.add_argument(
       '-p',
-      '--packages',
-      nargs='+',
+      '--package',
+      nargs=1,
       default=_DEFAULT_DOWNLOAD_PACKAGES,
-      help='The packages of the SDK needs to be installed/updated. ' +
+      help='The package of the SDK needs to be installed/updated. ' +
            'Note that package name should be a sdk-style path e.g. ' +
            '"platforms;android-27" or "platform-tools". If package ' +
            'is not specified, update "build-tools;27.0.3", "tools" ' +
            '"platform-tools" and "platforms;android-27" by default.')
   download_parser.add_argument('--sdk-root',
-                               default=_SDK_ROOT,
                                help='base path to the Android SDK root')
   download_parser.add_argument('-v', '--verbose',
                                action='store_true',
@@ -346,7 +419,6 @@
                               help='The url of the CIPD service.',
                               default='https://chrome-infra-packages.appspot.com')
   package_parser.add_argument('--sdk-root',
-                               default=_SDK_ROOT,
                                help='base path to the Android SDK root')
   package_parser.add_argument('-v', '--verbose',
                               action='store_true',
@@ -354,6 +426,12 @@
 
   args = parser.parse_args()
 
+  if not args.sdk_root:
+    if args.package and 'sources' in args.package:
+      args.sdk_root = _SDK_SOURCES_ROOT
+    else:
+      args.sdk_root = _SDK_PUBLIC_ROOT
+
   args.func(args)
 
 
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 9c86513c..713d2827 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -1471,6 +1471,9 @@
 </action>
 
 <action name="Android.ChromeHome.Survey.ShowSurveyInfoBar">
+  <obsolete>
+    Deprecated 4/2018. Replaced with Android.Survey.ShowSurveyInfoBar action.
+  </obsolete>
   <owner>danielpark@chromium.org</owner>
   <description>The survey infobar was displayed.</description>
 </action>
@@ -1859,6 +1862,11 @@
   </description>
 </action>
 
+<action name="Android.Survey.ShowSurveyInfoBar">
+  <owner>danielpark@chromium.org</owner>
+  <description>The survey infobar was displayed.</description>
+</action>
+
 <action name="AppCloseButton_Clk">
   <obsolete>Unused as of 08/2017</obsolete>
   <owner>jamescook@chromium.org</owner>
@@ -17170,15 +17178,42 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithAccount_FromAvatarBubbleSignin">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with an account in the
+    avatar bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithAccount_FromBookmarkBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with an account in the
+    bookmark bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithAccount_FromBookmarkManager">
   <owner>jlebel@chromium.org</owner>
   <description>
-    Recorded when starting sign-in using the promo view, with a default account,
-    from bookmarks manager
+    Recorded when the personalized sign-in promo is shown with an account in the
+    in the bookmark manager.
     (signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER).
   </description>
 </action>
 
+<action name="Signin_ImpressionWithAccount_FromExtensionInstallBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with an account in the
+    extension install bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithAccount_FromNTPContentSuggestions">
   <owner>bsazonov@chromium.org</owner>
   <description>
@@ -17188,6 +17223,15 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithAccount_FromPasswordBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with no account in the
+    password saved bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithAccount_FromRecentTabs">
   <owner>jlebel@chromium.org</owner>
   <description>
@@ -17212,6 +17256,24 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithNoAccount_FromAvatarBubbleSignin">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with no account in the
+    avatar bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithNoAccount_FromBookmarkBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with no account in the
+    bookmark bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithNoAccount_FromBookmarkManager">
   <owner>jlebel@chromium.org</owner>
   <description>
@@ -17221,6 +17283,15 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithNoAccount_FromExtensionInstallBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with no account in the
+    extension install bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithNoAccount_FromNTPContentSuggestions">
   <owner>bsazonov@chromium.org</owner>
   <description>
@@ -17230,6 +17301,15 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithNoAccount_FromPasswordBubble">
+  <owner>msarda@chromium.org</owner>
+  <description>
+    Recorded when the personalized sign-in promo is shown with no account in the
+    password saved bubble.
+    (signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE).
+  </description>
+</action>
+
 <action name="Signin_ImpressionWithNoAccount_FromRecentTabs">
   <owner>jlebel@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 484ef49..e0f3176 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -43081,7 +43081,7 @@
 
 <enum name="SurveyFilteringResult">
   <int value="0" label="Survey info bar already displayed"/>
-  <int value="1" label="Chrome Home enabled for less than one week"/>
+  <int value="1" label="Chrome Home enabled for less than one week [removed]"/>
   <int value="2" label="Force Survey On command present"/>
   <int value="3" label="User already sampled today"/>
   <int value="4" label="Max number is missing"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e3e52d6..1dea406 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -854,12 +854,18 @@
 
 <histogram name="Android.ChromeHome.Survey.DownloadResponseCode"
     enum="SurveyDownloadResponseCodes">
+  <obsolete>
+    Deprecated 04/2018. Replaced with Android.Survey.DownloadResponseCode.
+  </obsolete>
   <owner>danielpark@chromium.org</owner>
   <summary>The response code of the completed survey download request.</summary>
 </histogram>
 
 <histogram name="Android.ChromeHome.Survey.InfoBarClosingState"
     enum="InfoBarClosingStates">
+  <obsolete>
+    Deprecated 04/2018. Replaced with Android.Survey.InfoBarClosingState.
+  </obsolete>
   <owner>danielpark@chromium.org</owner>
   <summary>
     If the infobar was visible when it was closed and if it was closed directly
@@ -868,6 +874,9 @@
 </histogram>
 
 <histogram name="Android.ChromeHome.Survey.ShowSurvey" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 04/2018. Replaced with Android.Survey.ShowSurvey.
+  </obsolete>
   <owner>danielpark@chromium.org</owner>
   <summary>
     Whether or not the survey was successfully shown after its download.
@@ -876,6 +885,9 @@
 
 <histogram name="Android.ChromeHome.Survey.SurveyFilteringResults"
     enum="SurveyFilteringResult">
+  <obsolete>
+    Deprecated 04/2018. Replaced with Android.Survey.SurveyFilteringResults.
+  </obsolete>
   <owner>danielpark@chromium.org</owner>
   <summary>
     The result of the survey filtering process. Each enum represents a different
@@ -1845,6 +1857,38 @@
   </summary>
 </histogram>
 
+<histogram name="Android.Survey.DownloadResponseCode"
+    enum="SurveyDownloadResponseCodes">
+  <owner>danielpark@chromium.org</owner>
+  <summary>The response code of the completed survey download request.</summary>
+</histogram>
+
+<histogram name="Android.Survey.InfoBarClosingState"
+    enum="InfoBarClosingStates">
+  <owner>danielpark@chromium.org</owner>
+  <summary>
+    If the infobar was visible when it was closed and if it was closed directly
+    or not.
+  </summary>
+</histogram>
+
+<histogram name="Android.Survey.ShowSurvey" enum="BooleanSuccess">
+  <owner>danielpark@chromium.org</owner>
+  <summary>
+    Whether or not the survey was successfully shown after its download.
+  </summary>
+</histogram>
+
+<histogram name="Android.Survey.SurveyFilteringResults"
+    enum="SurveyFilteringResult">
+  <owner>danielpark@chromium.org</owner>
+  <summary>
+    The result of the survey filtering process. Each enum represents a different
+    filter that caught the user. This is recorded on cold starts when we check
+    if a user qualifies for a survey.
+  </summary>
+</histogram>
+
 <histogram name="Android.SysUtilsLowEndMatches" enum="BooleanEqual">
   <owner>mariakhomenko@chromium.org</owner>
   <summary>
@@ -8150,7 +8194,10 @@
 <histogram name="BlinkGC.TimeForCoalesce" units="ms">
   <owner>haraken@chromium.org</owner>
   <owner>hpayer@chromium.org</owner>
-  <summary>Duration of memory coalesce operation in the Blink GC.</summary>
+  <summary>
+    Duration of memory coalesce operation in the Blink GC.  Reported once per
+    coalesce operation.
+  </summary>
 </histogram>
 
 <histogram name="BlinkGC.TimeForGlobalWeakProcessing" units="ms">
@@ -12416,7 +12463,7 @@
   <owner>pnoland@chromium.org</owner>
   <summary>
     Android: The integer status code of network requests made by the feed
-    library's networking host. This code includes both protocol(1xx-5xx)  and
+    library's networking host. This code includes both protocol(1xx-5xx) and
     non-protocol(-xxx) errors. Recorded when a request completes.
   </summary>
 </histogram>
@@ -12544,6 +12591,40 @@
   </summary>
 </histogram>
 
+<histogram name="ContextualSuggestions.FetchErrorCode" enum="NetErrorCodes">
+  <owner>pnoland@chromium.org</owner>
+  <summary>
+    Android: The net::Error status code of contextual suggestion fetches.
+    Recorded when a fetch completes.
+  </summary>
+</histogram>
+
+<histogram name="ContextualSuggestions.FetchRequestProtoSizeKB" units="KB">
+  <owner>pnoland@chromium.org</owner>
+  <summary>
+    Android: The size of the serialized and base64-encoded proto sent to the
+    server when fetching contextual suggestions. Recorded when a fetch is
+    initiated.
+  </summary>
+</histogram>
+
+<histogram name="ContextualSuggestions.FetchResponseCode"
+    enum="HttpResponseCode">
+  <owner>pnoland@chromium.org</owner>
+  <summary>
+    Android: The http status code of contextual suggestion fetches. Recorded
+    when a fetch completes.
+  </summary>
+</histogram>
+
+<histogram name="ContextualSuggestions.FetchResponseSizeKB" units="KB">
+  <owner>pnoland@chromium.org</owner>
+  <summary>
+    Android: The size of the response body received when a contextual
+    suggestions fetch completes. Recorded when the response is received.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Cookie.AgeFor" units="days">
   <owner>mkwst@chromium.org</owner>
   <owner>tnagel@chromium.org</owner>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 045b9e1c..150cb0b 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -142,7 +142,7 @@
  <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="59824433" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="device/geolocation/network_location_request.cc"/>
  <item id="network_time_component" hash_code="46188932" type="0" content_hash_code="28051857" os_list="linux,windows" file_path="components/network_time/network_time_tracker.cc"/>
  <item id="notification_image_reporter" hash_code="70126372" type="0" content_hash_code="29754543" os_list="linux,windows" file_path="chrome/browser/safe_browsing/notification_image_reporter.cc"/>
- <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" deprecated="2018-04-09" content_hash_code="29742597" file_path="components/ntp_snippets/contextual/contextual_json_request.cc"/>
+ <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" content_hash_code="71905054" os_list="linux,windows" file_path="components/ntp_snippets/contextual/contextual_suggestions_fetch.cc"/>
  <item id="ntp_snippets_fetch" hash_code="15418154" type="0" content_hash_code="10078959" os_list="linux,windows" file_path="components/ntp_snippets/remote/json_request.cc"/>
  <item id="oauth2_access_token_fetcher" hash_code="27915688" type="0" content_hash_code="33501872" os_list="linux,windows" file_path="google_apis/gaia/oauth2_access_token_fetcher_impl.cc"/>
  <item id="oauth2_api_call_flow" hash_code="29188932" type="2" content_hash_code="108831236" os_list="linux,windows" policy_fields="-1" file_path="google_apis/gaia/oauth2_api_call_flow.cc"/>
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index 81d8fb5..0bca9825 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
diff --git a/ui/accessibility/platform/ax_snapshot_node_android_platform.cc b/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
index 998ae65..7ef8a5c 100644
--- a/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
+++ b/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_enums.mojom.h"
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 10940e1..cea1307 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/surface_layer.h"
 #include "components/viz/common/features.h"
diff --git a/ui/android/resources/nine_patch_resource.cc b/ui/android/resources/nine_patch_resource.cc
index d665072..4e9a26b 100644
--- a/ui/android/resources/nine_patch_resource.cc
+++ b/ui/android/resources/nine_patch_resource.cc
@@ -4,7 +4,6 @@
 
 #include "ui/android/resources/nine_patch_resource.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/layers/nine_patch_layer.h"
 #include "ui/gfx/geometry/point_f.h"
 
diff --git a/ui/android/resources/resource.cc b/ui/android/resources/resource.cc
index 5ac17fa0..385f253 100644
--- a/ui/android/resources/resource.cc
+++ b/ui/android/resources/resource.cc
@@ -4,7 +4,6 @@
 
 #include "ui/android/resources/resource.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/memory_usage_estimator.h"
 
 namespace ui {
diff --git a/ui/android/resources/resource_manager_impl_unittest.cc b/ui/android/resources/resource_manager_impl_unittest.cc
index 58a1621..ab9055b 100644
--- a/ui/android/resources/resource_manager_impl_unittest.cc
+++ b/ui/android/resources/resource_manager_impl_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/process_memory_dump.h"
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index e3a5139..2ff9ed17 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -14,7 +14,6 @@
 
 #include "ash/app_list/model/search/search_box_model.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/app_list/views/indicator_chip_view.cc b/ui/app_list/views/indicator_chip_view.cc
index 879baec..af4af1e 100644
--- a/ui/app_list/views/indicator_chip_view.cc
+++ b/ui/app_list/views/indicator_chip_view.cc
@@ -4,7 +4,6 @@
 
 #include "ui/app_list/views/indicator_chip_view.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/background.h"
diff --git a/ui/app_list/views/page_switcher.cc b/ui/app_list/views/page_switcher.cc
index fede1cc..9de6f76e 100644
--- a/ui/app_list/views/page_switcher.cc
+++ b/ui/app_list/views/page_switcher.cc
@@ -8,7 +8,6 @@
 
 #include "base/i18n/number_formatting.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/app_list/app_list_constants.h"
diff --git a/ui/app_list/views/pulsing_block_view.cc b/ui/app_list/views/pulsing_block_view.cc
index c6e375de..361460e 100644
--- a/ui/app_list/views/pulsing_block_view.cc
+++ b/ui/app_list/views/pulsing_block_view.cc
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/app_list/views/search_result_answer_card_view_unittest.cc b/ui/app_list/views/search_result_answer_card_view_unittest.cc
index 0c70bed..006d72c 100644
--- a/ui/app_list/views/search_result_answer_card_view_unittest.cc
+++ b/ui/app_list/views/search_result_answer_card_view_unittest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/unguessable_token.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/app_list/views/search_result_list_view_unittest.cc b/ui/app_list/views/search_result_list_view_unittest.cc
index 2e69a06..74818c2a 100644
--- a/ui/app_list/views/search_result_list_view_unittest.cc
+++ b/ui/app_list/views/search_result_list_view_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "ash/app_list/model/search/search_model.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/app_list/app_list_features.h"
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc
index 7cb957c..bb53f165 100644
--- a/ui/app_list/views/search_result_page_view.cc
+++ b/ui/app_list/views/search_result_page_view.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_util.h"
 #include "ui/app_list/app_list_view_delegate.h"
diff --git a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
index d48afb6..137a32b 100644
--- a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "ash/app_list/model/app_list_model.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/ui/arc/notification/arc_notification_content_view.cc b/ui/arc/notification/arc_notification_content_view.cc
index c297a3d..8f56e7d6 100644
--- a/ui/arc/notification/arc_notification_content_view.cc
+++ b/ui/arc/notification/arc_notification_content_view.cc
@@ -6,7 +6,6 @@
 
 #include "ash/wm/window_util.h"
 #include "base/auto_reset.h"
-#include "base/memory/ptr_util.h"
 #include "components/exo/notification_surface.h"
 #include "components/exo/surface.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/arc/notification/arc_notification_item_impl.cc b/ui/arc/notification/arc_notification_item_impl.cc
index ffa7b4cd..40b317f87 100644
--- a/ui/arc/notification/arc_notification_item_impl.cc
+++ b/ui/arc/notification/arc_notification_item_impl.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "ash/shelf/shelf_constants.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/arc/notification/arc_notification_delegate.h"
diff --git a/ui/arc/notification/arc_notification_manager_unittest.cc b/ui/arc/notification/arc_notification_manager_unittest.cc
index 5053235c..1ef695c 100644
--- a/ui/arc/notification/arc_notification_manager_unittest.cc
+++ b/ui/arc/notification/arc_notification_manager_unittest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/arc/arc_bridge_service.h"
diff --git a/ui/arc/notification/arc_notification_surface_manager_impl.cc b/ui/arc/notification/arc_notification_surface_manager_impl.cc
index 29778a78..72c834d5 100644
--- a/ui/arc/notification/arc_notification_surface_manager_impl.cc
+++ b/ui/arc/notification/arc_notification_surface_manager_impl.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "components/exo/notification_surface.h"
 #include "ui/arc/notification/arc_notification_surface_impl.h"
 
diff --git a/ui/arc/notification/arc_notification_view_unittest.cc b/ui/arc/notification/arc_notification_view_unittest.cc
index 4d23eca..bac3ab6 100644
--- a/ui/arc/notification/arc_notification_view_unittest.cc
+++ b/ui/arc/notification/arc_notification_view_unittest.cc
@@ -7,7 +7,6 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/utf_string_conversions.h"
 #include "third_party/skia/include/core/SkColor.h"
diff --git a/ui/aura/env.cc b/ui/aura/env.cc
index e6b5ad0..b32f9f5d 100644
--- a/ui/aura/env.cc
+++ b/ui/aura/env.cc
@@ -6,7 +6,6 @@
 
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_local.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "ui/aura/client/aura_constants.h"
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc
index 827c9dc..39c305e 100644
--- a/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/ui/aura/mus/client_surface_embedder.cc b/ui/aura/mus/client_surface_embedder.cc
index 98e7ab5..74f31fd 100644
--- a/ui/aura/mus/client_surface_embedder.cc
+++ b/ui/aura/mus/client_surface_embedder.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/mus/client_surface_embedder.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/dip_util.h"
 
diff --git a/ui/aura/mus/drag_drop_controller_mus.cc b/ui/aura/mus/drag_drop_controller_mus.cc
index 532b036..fa518e2 100644
--- a/ui/aura/mus/drag_drop_controller_mus.cc
+++ b/ui/aura/mus/drag_drop_controller_mus.cc
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/auto_reset.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/map.h"
diff --git a/ui/aura/mus/drag_drop_controller_mus_unittest.cc b/ui/aura/mus/drag_drop_controller_mus_unittest.cc
index d5be374..24227cf7 100644
--- a/ui/aura/mus/drag_drop_controller_mus_unittest.cc
+++ b/ui/aura/mus/drag_drop_controller_mus_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/callback_forward.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc
index 88eae4e..ef87de61 100644
--- a/ui/aura/mus/input_method_mus.cc
+++ b/ui/aura/mus/input_method_mus.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
 #include "services/ui/public/interfaces/ime/ime.mojom.h"
 #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
diff --git a/ui/aura/mus/mus_context_factory.cc b/ui/aura/mus/mus_context_factory.cc
index f2b4dc0..73badbb 100644
--- a/ui/aura/mus/mus_context_factory.cc
+++ b/ui/aura/mus/mus_context_factory.cc
@@ -5,7 +5,6 @@
 #include "ui/aura/mus/mus_context_factory.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "cc/base/switches.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/host/renderer_settings_creation.h"
diff --git a/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc b/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc
index 7ce7c71..225a515 100644
--- a/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc
+++ b/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
diff --git a/ui/aura/mus/property_converter.cc b/ui/aura/mus/property_converter.cc
index 7a0a67e..ae2ce3a 100644
--- a/ui/aura/mus/property_converter.cc
+++ b/ui/aura/mus/property_converter.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/mus/property_converter.h"
 
-#include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/window_manager.mojom.h"
diff --git a/ui/aura/mus/user_activity_forwarder_unittest.cc b/ui/aura/mus/user_activity_forwarder_unittest.cc
index 9d011c0..249cc0a 100644
--- a/ui/aura/mus/user_activity_forwarder_unittest.cc
+++ b/ui/aura/mus/user_activity_forwarder_unittest.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/ui/common/task_runner_test_base.h"
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc
index 5bf0348..1959681 100644
--- a/ui/aura/mus/window_port_mus.cc
+++ b/ui/aura/mus/window_port_mus.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/mus/window_port_mus.h"
 
-#include "base/memory/ptr_util.h"
 #include "components/viz/client/local_surface_id_provider.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "ui/aura/client/aura_constants.h"
diff --git a/ui/aura/mus/window_tree_host_mus.cc b/ui/aura/mus/window_tree_host_mus.cc
index e6d8ae39..639f2629 100644
--- a/ui/aura/mus/window_tree_host_mus.cc
+++ b/ui/aura/mus/window_tree_host_mus.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/mus/window_tree_host_mus.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/env.h"
 #include "ui/aura/mus/input_method_mus.h"
 #include "ui/aura/mus/window_port_mus.h"
diff --git a/ui/aura/mus/window_tree_host_mus_unittest.cc b/ui/aura/mus/window_tree_host_mus_unittest.cc
index 3d7714e..39a7302 100644
--- a/ui/aura/mus/window_tree_host_mus_unittest.cc
+++ b/ui/aura/mus/window_tree_host_mus_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/mus/window_tree_host_mus.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/test/aura_mus_test_base.h"
diff --git a/ui/aura/test/aura_test_base.cc b/ui/aura/test/aura_test_base.cc
index ba0f3f8..a86418c 100644
--- a/ui/aura/test/aura_test_base.cc
+++ b/ui/aura/test/aura_test_base.cc
@@ -5,7 +5,6 @@
 #include "ui/aura/test/aura_test_base.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "ui/aura/client/window_parenting_client.h"
 #include "ui/aura/mus/property_utils.h"
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index dec50b8b..63873d2 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -5,7 +5,6 @@
 #include "ui/aura/test/aura_test_helper.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/focus_client.h"
diff --git a/ui/aura/test/mus/test_window_tree_client_setup.cc b/ui/aura/test/mus/test_window_tree_client_setup.cc
index aedb921..e8872d7 100644
--- a/ui/aura/test/mus/test_window_tree_client_setup.cc
+++ b/ui/aura/test/mus/test_window_tree_client_setup.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/test/mus/test_window_tree_client_setup.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/test/mus/test_window_manager_client.h"
 #include "ui/aura/test/mus/test_window_tree.h"
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 815056d5..c8b3654 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -14,7 +14,6 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/ui/aura/window_port_for_shutdown.cc b/ui/aura/window_port_for_shutdown.cc
index 6b71728..1b47442e 100644
--- a/ui/aura/window_port_for_shutdown.cc
+++ b/ui/aura/window_port_for_shutdown.cc
@@ -4,7 +4,6 @@
 
 #include "ui/aura/window_port_for_shutdown.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "ui/aura/window.h"
 
diff --git a/ui/base/class_property_unittest.cc b/ui/base/class_property_unittest.cc
index 6651c0e..ae9e901 100644
--- a/ui/base/class_property_unittest.cc
+++ b/ui/base/class_property_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ui/base/cocoa/menu_controller.mm b/ui/base/cocoa/menu_controller.mm
index 384804ab..bf27efe 100644
--- a/ui/base/cocoa/menu_controller.mm
+++ b/ui/base/cocoa/menu_controller.mm
@@ -7,7 +7,6 @@
 #include "base/cancelable_callback.h"
 #include "base/logging.h"
 #include "base/mac/bind_objc_block.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/base/accelerators/accelerator.h"
diff --git a/ui/base/dragdrop/os_exchange_data_provider_builder_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_builder_mac.mm
index 8eb42de5..e8d108a 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_builder_mac.mm
+++ b/ui/base/dragdrop/os_exchange_data_provider_builder_mac.mm
@@ -4,7 +4,6 @@
 
 #include "ui/base/dragdrop/os_exchange_data_provider_builder_mac.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_mac.h"
 
 namespace ui {
diff --git a/ui/base/dragdrop/os_exchange_data_provider_factory.cc b/ui/base/dragdrop/os_exchange_data_provider_factory.cc
index 2837e79..9c3a9ab2 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_factory.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_factory.cc
@@ -4,7 +4,6 @@
 
 #include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 
 #if defined(USE_X11)
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc
index 85762b2..2aa2920a 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_win.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -18,7 +18,6 @@
 #include "base/i18n/file_util_icu.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/scoped_hdc.h"
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index 31cf380..b11f08e 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -15,7 +15,6 @@
 #include "base/bind.h"
 #include "base/i18n/char_iterator.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/third_party/icu/icu_utf.h"
diff --git a/ui/base/ime/linux/fake_input_method_context_factory.cc b/ui/base/ime/linux/fake_input_method_context_factory.cc
index ec651ce..f8d3102e 100644
--- a/ui/base/ime/linux/fake_input_method_context_factory.cc
+++ b/ui/base/ime/linux/fake_input_method_context_factory.cc
@@ -4,7 +4,6 @@
 
 #include "ui/base/ime/linux/fake_input_method_context_factory.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/base/ime/linux/fake_input_method_context.h"
 
 namespace ui {
diff --git a/ui/base/l10n/l10n_util_unittest.cc b/ui/base/l10n/l10n_util_unittest.cc
index 2bfd8c8..35dc475 100644
--- a/ui/base/l10n/l10n_util_unittest.cc
+++ b/ui/base/l10n/l10n_util_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/i18n/rtl.h"
 #include "base/i18n/time_formatting.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/base/models/list_model.h b/ui/base/models/list_model.h
index d55719c..d8abe8a 100644
--- a/ui/base/models/list_model.h
+++ b/ui/base/models/list_model.h
@@ -13,7 +13,6 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/observer_list.h"
 #include "ui/base/models/list_model_observer.h"
 
diff --git a/ui/base/models/list_model_unittest.cc b/ui/base/models/list_model_unittest.cc
index 38ec5404..b5917bf 100644
--- a/ui/base/models/list_model_unittest.cc
+++ b/ui/base/models/list_model_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ui {
diff --git a/ui/base/models/tree_node_iterator_unittest.cc b/ui/base/models/tree_node_iterator_unittest.cc
index a986c5d..b1c09f50 100644
--- a/ui/base/models/tree_node_iterator_unittest.cc
+++ b/ui/base/models/tree_node_iterator_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/base/models/tree_node_iterator.h"
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/models/tree_node_model.h"
 
diff --git a/ui/base/models/tree_node_model_unittest.cc b/ui/base/models/tree_node_model_unittest.cc
index 0649f656..b39d82bc 100644
--- a/ui/base/models/tree_node_model_unittest.cc
+++ b/ui/base/models/tree_node_model_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/base/nine_image_painter_factory.cc b/ui/base/nine_image_painter_factory.cc
index 12f5953..57d41f5 100644
--- a/ui/base/nine_image_painter_factory.cc
+++ b/ui/base/nine_image_painter_factory.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/nine_image_painter.h"
 
diff --git a/ui/base/resource/data_pack.cc b/ui/base/resource/data_pack.cc
index 170fa1d..f6cbde5 100644
--- a/ui/base/resource/data_pack.cc
+++ b/ui/base/resource/data_pack.cc
@@ -14,7 +14,6 @@
 #include "base/files/memory_mapped_file.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index dc7eb15..bc8da0f0 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -16,7 +16,6 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
diff --git a/ui/base/resource/resource_bundle_android.cc b/ui/base/resource/resource_bundle_android.cc
index a91fdabe..2ebf50ba 100644
--- a/ui/base/resource/resource_bundle_android.cc
+++ b/ui/base/resource/resource_bundle_android.cc
@@ -8,7 +8,6 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "jni/ResourceBundle_jni.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/base/resource/resource_bundle_win.cc b/ui/base/resource/resource_bundle_win.cc
index 54fca6fa..d9f74a56 100644
--- a/ui/base/resource/resource_bundle_win.cc
+++ b/ui/base/resource/resource_bundle_win.cc
@@ -5,7 +5,6 @@
 #include "ui/base/resource/resource_bundle_win.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "skia/ext/image_operations.h"
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc
index cefa609..17b750b 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/x/selection_utils.h"
 #include "ui/base/x/x11_window_event_manager.h"
 #include "ui/events/platform/x11/x11_event_source.h"
diff --git a/ui/chromeos/events/event_rewriter_chromeos.cc b/ui/chromeos/events/event_rewriter_chromeos.cc
index 021e4c0..02d15a2b 100644
--- a/ui/chromeos/events/event_rewriter_chromeos.cc
+++ b/ui/chromeos/events/event_rewriter_chromeos.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/chromeos/ime/candidate_window_view.cc b/ui/chromeos/ime/candidate_window_view.cc
index e2f993a..55c93a5 100644
--- a/ui/chromeos/ime/candidate_window_view.cc
+++ b/ui/chromeos/ime/candidate_window_view.cc
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "services/ui/public/cpp/property_type_converters.h"
diff --git a/ui/compositor/callback_layer_animation_observer_unittest.cc b/ui/compositor/callback_layer_animation_observer_unittest.cc
index 6ea60b7..eff7ee4 100644
--- a/ui/compositor/callback_layer_animation_observer_unittest.cc
+++ b/ui/compositor/callback_layer_animation_observer_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/test/layer_animation_observer_test_api.h"
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc
index 38bd26b..3d965dd 100644
--- a/ui/compositor/layer_animation_element.cc
+++ b/ui/compositor/layer_animation_element.cc
@@ -8,7 +8,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "cc/animation/animation_id_provider.h"
 #include "cc/animation/keyframe_model.h"
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index 6dc9a0ca..389cedcbf 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/compositor/layer_owner.cc b/ui/compositor/layer_owner.cc
index 2806e81..ed68ad2 100644
--- a/ui/compositor/layer_owner.cc
+++ b/ui/compositor/layer_owner.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 
 namespace ui {
 
diff --git a/ui/compositor/layer_owner_unittest.cc b/ui/compositor/layer_owner_unittest.cc
index 3a6b60b..2e6fb20 100644
--- a/ui/compositor/layer_owner_unittest.cc
+++ b/ui/compositor/layer_owner_unittest.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/null_task_runner.h"
 #include "cc/animation/single_keyframe_effect_animation.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 8cd56c6..c56eee9 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
diff --git a/ui/compositor/test/test_suite.cc b/ui/compositor/test/test_suite.cc
index c06f20780..897997b9 100644
--- a/ui/compositor/test/test_suite.cc
+++ b/ui/compositor/test/test_suite.cc
@@ -5,7 +5,6 @@
 #include "ui/compositor/test/test_suite.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "ui/compositor/compositor.h"
diff --git a/ui/display/manager/chromeos/display_change_observer_unittest.cc b/ui/display/manager/chromeos/display_change_observer_unittest.cc
index e714181e..ce955f2 100644
--- a/ui/display/manager/chromeos/display_change_observer_unittest.cc
+++ b/ui/display/manager/chromeos/display_change_observer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/manager/fake_display_snapshot.h"
diff --git a/ui/display/manager/chromeos/display_configurator.cc b/ui/display/manager/chromeos/display_configurator.cc
index e8e50bff..e939dba 100644
--- a/ui/display/manager/chromeos/display_configurator.cc
+++ b/ui/display/manager/chromeos/display_configurator.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "chromeos/system/devicemode.h"
 #include "ui/display/display.h"
diff --git a/ui/display/manager/chromeos/display_configurator_unittest.cc b/ui/display/manager/chromeos/display_configurator_unittest.cc
index 8961eb53..623add6 100644
--- a/ui/display/manager/chromeos/display_configurator_unittest.cc
+++ b/ui/display/manager/chromeos/display_configurator_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chromeos/chromeos_switches.cc"
diff --git a/ui/display/manager/chromeos/touch_device_manager_unittest.cc b/ui/display/manager/chromeos/touch_device_manager_unittest.cc
index 472f0ba..6ae54c1 100644
--- a/ui/display/manager/chromeos/touch_device_manager_unittest.cc
+++ b/ui/display/manager/chromeos/touch_device_manager_unittest.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/display/manager/chromeos/touch_transform_controller_unittest.cc b/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
index a9107fd..35b769b 100644
--- a/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
+++ b/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/manager/chromeos/default_touch_transform_setter.h"
diff --git a/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc b/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
index c1dcc99..526d70e 100644
--- a/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
+++ b/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index ea79989..a6bd25b 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -17,7 +17,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
diff --git a/ui/display/manager/fake_display_delegate.cc b/ui/display/manager/fake_display_delegate.cc
index 8d47679..c03a926 100644
--- a/ui/display/manager/fake_display_delegate.cc
+++ b/ui/display/manager/fake_display_delegate.cc
@@ -10,7 +10,6 @@
 #include "base/command_line.h"
 #include "base/hash.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
diff --git a/ui/display/manager/fake_display_snapshot.cc b/ui/display/manager/fake_display_snapshot.cc
index a21aaa28..9bdbd1d 100644
--- a/ui/display/manager/fake_display_snapshot.cc
+++ b/ui/display/manager/fake_display_snapshot.cc
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
diff --git a/ui/events/blink/compositor_thread_event_queue.cc b/ui/events/blink/compositor_thread_event_queue.cc
index 63c2386a..d279679 100644
--- a/ui/events/blink/compositor_thread_event_queue.cc
+++ b/ui/events/blink/compositor_thread_event_queue.cc
@@ -4,7 +4,6 @@
 
 #include "ui/events/blink/compositor_thread_event_queue.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/web_input_event_traits.h"
diff --git a/ui/events/blink/event_with_callback.cc b/ui/events/blink/event_with_callback.cc
index a3e0b210b..1e23768 100644
--- a/ui/events/blink/event_with_callback.cc
+++ b/ui/events/blink/event_with_callback.cc
@@ -4,7 +4,6 @@
 
 #include "ui/events/blink/event_with_callback.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/did_overscroll_params.h"
 #include "ui/events/blink/web_input_event_traits.h"
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 167d474..0ae50266 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -12,7 +12,6 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc
index a94dec00..cc8d67e 100644
--- a/ui/events/gestures/blink/web_gesture_curve_impl.cc
+++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/platform/web_float_size.h"
diff --git a/ui/events/ozone/device/device_manager.cc b/ui/events/ozone/device/device_manager.cc
index 59db5c5..7952fcbb 100644
--- a/ui/events/ozone/device/device_manager.cc
+++ b/ui/events/ozone/device/device_manager.cc
@@ -4,7 +4,6 @@
 
 #include "ui/events/ozone/device/device_manager.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 
 #if defined(USE_UDEV)
diff --git a/ui/events/ozone/device/udev/device_manager_udev.cc b/ui/events/ozone/device/udev/device_manager_udev.cc
index 655285f..16421005 100644
--- a/ui/events/ozone/device/udev/device_manager_udev.cc
+++ b/ui/events/ozone/device/udev/device_manager_udev.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
diff --git a/ui/events/ozone/evdev/event_converter_test_util.cc b/ui/events/ozone/evdev/event_converter_test_util.cc
index ebbbbd5..52d339c 100644
--- a/ui/events/ozone/evdev/event_converter_test_util.cc
+++ b/ui/events/ozone/evdev/event_converter_test_util.cc
@@ -6,7 +6,6 @@
 
 #include <stdint.h>
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/ozone/device/device_manager.h"
 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
 #include "ui/events/ozone/evdev/event_factory_evdev.h"
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc
index 5d7539e9..2d44b91 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
index d3123c89..b768ad6 100644
--- a/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
@@ -18,7 +18,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
diff --git a/ui/events/ozone/evdev/input_controller_evdev.cc b/ui/events/ozone/evdev/input_controller_evdev.cc
index f94687e..3834a69b 100644
--- a/ui/events/ozone/evdev/input_controller_evdev.cc
+++ b/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 
 #include "base/callback.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
diff --git a/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc b/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
index a5d1a48..1b0d7121 100644
--- a/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
+++ b/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
@@ -4,7 +4,6 @@
 
 #include "ui/events/ozone/evdev/touch_filter/false_touch_finder.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/ozone/evdev/touch_filter/edge_touch_filter.h"
diff --git a/ui/events/ozone/gamepad/gamepad_mapping.cc b/ui/events/ozone/gamepad/gamepad_mapping.cc
index 6e1d96c..26c6b73c 100644
--- a/ui/events/ozone/gamepad/gamepad_mapping.cc
+++ b/ui/events/ozone/gamepad/gamepad_mapping.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/ozone/evdev/event_device_info.h"
 #include "ui/events/ozone/gamepad/generic_gamepad_mapping.h"
 #include "ui/events/ozone/gamepad/static_gamepad_mapping.h"
diff --git a/ui/events/ozone/gamepad/generic_gamepad_mapping.cc b/ui/events/ozone/gamepad/generic_gamepad_mapping.cc
index 3b0ef4d3..d18ff45 100644
--- a/ui/events/ozone/gamepad/generic_gamepad_mapping.cc
+++ b/ui/events/ozone/gamepad/generic_gamepad_mapping.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/events/ozone/evdev/event_device_info.h"
 #include "ui/events/ozone/gamepad/generic_gamepad_mapping.h"
 #include "ui/events/ozone/gamepad/webgamepad_constants.h"
diff --git a/ui/events/ozone/gamepad/generic_gamepad_mapping_unittest.cc b/ui/events/ozone/gamepad/generic_gamepad_mapping_unittest.cc
index 7ac37b4..2f40517 100644
--- a/ui/events/ozone/gamepad/generic_gamepad_mapping_unittest.cc
+++ b/ui/events/ozone/gamepad/generic_gamepad_mapping_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
index fb89349..0830460 100644
--- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
+++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/dom/dom_code.h"
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc
index 9e832438..cdd9ce7 100644
--- a/ui/events/platform/platform_event_source.cc
+++ b/ui/events/platform/platform_event_source.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/threading/thread_local.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
diff --git a/ui/events/platform/platform_event_source_unittest.cc b/ui/events/platform/platform_event_source_unittest.cc
index a54663084..d9a069e 100644
--- a/ui/events/platform/platform_event_source_unittest.cc
+++ b/ui/events/platform/platform_event_source_unittest.cc
@@ -13,7 +13,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/ui/events/platform/x11/x11_event_source_glib.cc b/ui/events/platform/x11/x11_event_source_glib.cc
index b5af868d..e82e4c6 100644
--- a/ui/events/platform/x11/x11_event_source_glib.cc
+++ b/ui/events/platform/x11/x11_event_source_glib.cc
@@ -7,7 +7,6 @@
 #include <glib.h>
 #include "ui/gfx/x/x11.h"
 
-#include "base/memory/ptr_util.h"
 
 namespace ui {
 
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc
index 2183b35..63826141 100644
--- a/ui/events/platform/x11/x11_event_source_libevent.cc
+++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
diff --git a/ui/events/system_input_injector.cc b/ui/events/system_input_injector.cc
index 3d9207d..bbeb84d 100644
--- a/ui/events/system_input_injector.cc
+++ b/ui/events/system_input_injector.cc
@@ -4,7 +4,6 @@
 
 #include "ui/events/system_input_injector.h"
 
-#include "base/memory/ptr_util.h"
 
 namespace ui {
 
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc
index ced8d330..c602b542 100644
--- a/ui/events/test/event_generator.cc
+++ b/ui/events/test/event_generator.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/tick_clock.h"
diff --git a/ui/events/test/scoped_event_test_tick_clock.h b/ui/events/test/scoped_event_test_tick_clock.h
index 84516d83..baaece6 100644
--- a/ui/events/test/scoped_event_test_tick_clock.h
+++ b/ui/events/test/scoped_event_test_tick_clock.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_TEST_SCOPED_EVENT_TEST_TICK_CLOCK_H_
 #define UI_EVENTS_TEST_SCOPED_EVENT_TEST_TICK_CLOCK_H_
 
-#include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "ui/events/base_event_utils.h"
 
diff --git a/ui/events/test/test_event_target.cc b/ui/events/test/test_event_target.cc
index 996c6fe..15dc3e41 100644
--- a/ui/events/test/test_event_target.cc
+++ b/ui/events/test/test_event_target.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/event.h"
 #include "ui/events/event_target_iterator.h"
 #include "ui/events/event_targeter.h"
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc
index e056288..4ca7049 100644
--- a/ui/events/x/events_x_unittest.cc
+++ b/ui/events/x/events_x_unittest.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/gfx/animation/animation.cc b/ui/gfx/animation/animation.cc
index 469b5260..90342df 100644
--- a/ui/gfx/animation/animation.cc
+++ b/ui/gfx/animation/animation.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/animation/animation.h"
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/gfx/animation/animation_container.h"
 #include "ui/gfx/animation/animation_delegate.h"
diff --git a/ui/gfx/animation/animation_test_api.cc b/ui/gfx/animation/animation_test_api.cc
index b1c345d..4f3c99d 100644
--- a/ui/gfx/animation/animation_test_api.cc
+++ b/ui/gfx/animation/animation_test_api.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/animation/animation_test_api.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "ui/gfx/animation/animation.h"
 
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc
index 6aad90f..fb64a68 100644
--- a/ui/gfx/color_transform.cc
+++ b/ui/gfx/color_transform.cc
@@ -11,7 +11,6 @@
 #include <sstream>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkColorSpaceXform.h"
diff --git a/ui/gfx/gpu_fence_handle.h b/ui/gfx/gpu_fence_handle.h
index 093626c8..29a9c09 100644
--- a/ui/gfx/gpu_fence_handle.h
+++ b/ui/gfx/gpu_fence_handle.h
@@ -5,7 +5,6 @@
 #ifndef UI_GFX_GPU_FENCE_HANDLE_H_
 #define UI_GFX_GPU_FENCE_HANDLE_H_
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/gfx/gfx_export.h"
 
diff --git a/ui/gfx/image/canvas_image_source.h b/ui/gfx/image/canvas_image_source.h
index 6e0b21c3c..20e13ac 100644
--- a/ui/gfx/image/canvas_image_source.h
+++ b/ui/gfx/image/canvas_image_source.h
@@ -9,7 +9,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gfx_export.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/ui/gfx/image/mojo/image_traits_unittest.cc b/ui/gfx/image/mojo/image_traits_unittest.cc
index bca8f37..de87d86 100644
--- a/ui/gfx/image/mojo/image_traits_unittest.cc
+++ b/ui/gfx/image/mojo/image_traits_unittest.cc
@@ -6,7 +6,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/gfx/interpolated_transform.cc b/ui/gfx/interpolated_transform.cc
index f5bb4f4..5771a1e3 100644
--- a/ui/gfx/interpolated_transform.cc
+++ b/ui/gfx/interpolated_transform.cc
@@ -6,7 +6,6 @@
 
 #include <cmath>
 
-#include "base/memory/ptr_util.h"
 
 #include "base/logging.h"
 #include "ui/gfx/animation/tween.h"
diff --git a/ui/gfx/interpolated_transform_unittest.cc b/ui/gfx/interpolated_transform_unittest.cc
index 40ed89a..6856c2c0 100644
--- a/ui/gfx/interpolated_transform_unittest.cc
+++ b/ui/gfx/interpolated_transform_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/interpolated_transform.h"
 
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/rect.h"
 
diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
index 171bc56..d2968ffe 100644
--- a/ui/gfx/paint_vector_icon.cc
+++ b/ui/gfx/paint_vector_icon.cc
@@ -10,7 +10,6 @@
 #include "base/i18n/rtl.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/trace_event/trace_event.h"
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 0e642e9f..39702db 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -13,7 +13,6 @@
 #include "base/feature_list.h"
 #include "base/i18n/break_iterator.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/numerics/ranges.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 15b596fd..b1fb906 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/format_macros.h"
 #include "base/i18n/break_iterator.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/gfx/skia_paint_util.cc b/ui/gfx/skia_paint_util.cc
index 83753af..50279d1d 100644
--- a/ui/gfx/skia_paint_util.cc
+++ b/ui/gfx/skia_paint_util.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/skia_paint_util.h"
 
-#include "base/memory/ptr_util.h"
 #include "cc/paint/paint_image_builder.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkMaskFilter.h"
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index cbba4c9..81d80ca 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/gpu_fence.h"
 #include "ui/gl/gl_export.h"
 
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index 250bb1c2..2313b1f 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index f4493d6..c9d3d892e 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/memory/protected_memory.h"
 #include "base/memory/protected_memory_cfi.h"
-#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 2e266e6..9c77b7a 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -15,7 +15,6 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc
index ba1b165..d58e64f 100644
--- a/ui/gl/init/gl_initializer_mac.cc
+++ b/ui/gl/init/gl_initializer_mac.cc
@@ -135,28 +135,38 @@
 }
 
 #if BUILDFLAG(USE_EGL_ON_MAC)
-const char kGLESv2ANGLELibraryName[] = "Libraries/libGLESv2.dylib";
-const char kEGLANGLELibraryName[] = "Libraries/libEGL.dylib";
+const char kGLESv2ANGLELibraryName[] = "libGLESv2.dylib";
+const char kEGLANGLELibraryName[] = "libEGL.dylib";
 
-const char kGLESv2SwiftShaderLibraryName[] =
-    "Libraries/libswiftshader_libGLESv2.dylib";
-const char kEGLSwiftShaderLibraryName[] =
-    "Libraries/libswiftshader_libEGL.dylib";
+const char kGLESv2SwiftShaderLibraryName[] = "libswiftshader_libGLESv2.dylib";
+const char kEGLSwiftShaderLibraryName[] = "libswiftshader_libEGL.dylib";
 
 bool InitializeStaticEGLInternal(GLImplementation implementation) {
-  base::FilePath module_path = base::mac::FrameworkBundlePath();
+  // Some unit test targets depend on Angle/SwiftShader but aren't built
+  // as app bundles. In that case, the .dylib is next to the executable.
+  base::FilePath base_dir;
+  if (base::mac::AmIBundled()) {
+    base_dir = base::mac::FrameworkBundlePath().Append("Libraries/");
+  } else {
+    if (!PathService::Get(base::FILE_EXE, &base_dir)) {
+      LOG(ERROR) << "PathService::Get failed.";
+      return false;
+    }
+    base_dir = base_dir.DirName();
+  }
+
   base::FilePath glesv2_path;
   base::FilePath egl_path;
   if (implementation == kGLImplementationSwiftShaderGL) {
 #if BUILDFLAG(ENABLE_SWIFTSHADER)
-    glesv2_path = module_path.Append(kGLESv2SwiftShaderLibraryName);
-    egl_path = module_path.Append(kEGLSwiftShaderLibraryName);
+    glesv2_path = base_dir.Append(kGLESv2SwiftShaderLibraryName);
+    egl_path = base_dir.Append(kEGLSwiftShaderLibraryName);
 #else
     return false;
 #endif
   } else {
-    glesv2_path = module_path.Append(kGLESv2ANGLELibraryName);
-    egl_path = module_path.Append(kEGLANGLELibraryName);
+    glesv2_path = base_dir.Append(kGLESv2ANGLELibraryName);
+    egl_path = base_dir.Append(kEGLANGLELibraryName);
   }
 
   base::NativeLibrary gles_library = LoadLibraryAndPrintError(glesv2_path);
diff --git a/ui/gl/test/run_all_unittests.cc b/ui/gl/test/run_all_unittests.cc
index cf75a93..5219c05 100644
--- a/ui/gl/test/run_all_unittests.cc
+++ b/ui/gl/test/run_all_unittests.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_suite.h"
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index e449422..45793d1 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
diff --git a/ui/keyboard/keyboard_util_unittest.cc b/ui/keyboard/keyboard_util_unittest.cc
index bcbc714..a4f4eb8 100644
--- a/ui/keyboard/keyboard_util_unittest.cc
+++ b/ui/keyboard/keyboard_util_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/keyboard/keyboard_util.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_test_util.h"
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index 5415b33..b5d9e13 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -12,7 +12,6 @@
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/observer_list.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index e1af863..33d7e8a 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -5,7 +5,6 @@
 #include "ui/native_theme/common_theme.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
index dc7b44a..4aa44c7 100644
--- a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
+++ b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
@@ -5,7 +5,6 @@
 #include "ui/ozone/platform/cast/client_native_pixmap_factory_cast.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/client_native_pixmap.h"
 #include "ui/gfx/client_native_pixmap_factory.h"
diff --git a/ui/ozone/platform/cast/gl_ozone_egl_cast.cc b/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
index 4066ed41..33d0651f 100644
--- a/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
+++ b/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
@@ -11,7 +11,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "chromecast/base/chromecast_switches.h"
 #include "chromecast/public/cast_egl_platform.h"
diff --git a/ui/ozone/platform/cast/gl_surface_cast.cc b/ui/ozone/platform/cast/gl_surface_cast.cc
index 3864d93..7097dfb 100644
--- a/ui/ozone/platform/cast/gl_surface_cast.cc
+++ b/ui/ozone/platform/cast/gl_surface_cast.cc
@@ -5,7 +5,6 @@
 #include "ui/ozone/platform/cast/gl_surface_cast.h"
 
 #include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "chromecast/base/cast_features.h"
 #include "chromecast/base/chromecast_switches.h"
diff --git a/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc b/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
index f8dd781..8e363e6 100644
--- a/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
+++ b/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/linux/client_native_pixmap_factory_dmabuf.h"
 #include "ui/gfx/native_pixmap_handle.h"
 
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index 91147f0..df006916 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -14,7 +14,6 @@
 #include <utility>
 
 #include "base/containers/flat_map.h"
-#include "base/memory/ptr_util.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/util/edid_parser.h"
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc
index 07d013b..ce85361 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -7,7 +7,6 @@
 #include <xf86drmMode.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/gamma_ramp_rgb_entry.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index d07f576..a1cd565 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/memory/ptr_util.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/gamma_ramp_rgb_entry.h"
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index 768400c..6e187761 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -9,7 +9,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index b71bc83..fe6c4b3 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -5,7 +5,6 @@
 #include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h"
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h"
 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
 #include "ui/ozone/platform/drm/gpu/gbm_buffer.h"
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc
index 51d1855..6deff44 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index ca8a520..4fdef17 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "third_party/khronos/EGL/egl.h"
 #include "ui/gfx/buffer_format_util.h"
diff --git a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 7a3be654..f0670677 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/presentation_feedback.h"
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 7cfd083..aa68355c 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -10,7 +10,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 4455933..e8e47773 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/files/platform_file.h"
-#include "base/memory/ptr_util.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/ui/ozone/platform/drm/host/drm_display_host.cc b/ui/ozone/platform/drm/host/drm_display_host.cc
index 5b36b7f..d486445a 100644
--- a/ui/ozone/platform/drm/host/drm_display_host.cc
+++ b/ui/ozone/platform/drm/host/drm_display_host.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
diff --git a/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
index 7a236a5..31967c9 100644
--- a/ui/ozone/platform/drm/host/drm_display_host_manager.cc
+++ b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -12,7 +12,6 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
diff --git a/ui/ozone/platform/drm/host/drm_overlay_manager.cc b/ui/ozone/platform/drm/host/drm_overlay_manager.cc
index d99d288..4e8aae39 100644
--- a/ui/ozone/platform/drm/host/drm_overlay_manager.cc
+++ b/ui/ozone/platform/drm/host/drm_overlay_manager.cc
@@ -9,7 +9,6 @@
 #include <algorithm>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 963f77e..a6e1286 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -14,7 +14,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc
index 4bd9dc1..7bfe646 100644
--- a/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -8,7 +8,6 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 166def2..e6935b79 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/display/manager/fake_display_delegate.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 843d7c99..f0774bf 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -4,7 +4,6 @@
 
 #include "ui/ozone/platform/wayland/ozone_platform_wayland.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/base/ui_features.h"
 #include "ui/display/manager/fake_display_delegate.h"
diff --git a/ui/ozone/platform/wayland/wayland_touch.cc b/ui/ozone/platform/wayland/wayland_touch.cc
index b8dc5437..9052eaf0 100644
--- a/ui/ozone/platform/wayland/wayland_touch.cc
+++ b/ui/ozone/platform/wayland/wayland_touch.cc
@@ -8,7 +8,6 @@
 #include <wayland-client.h>
 
 #include "base/files/scoped_file.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/ui_features.h"
 #include "ui/events/event.h"
 #include "ui/ozone/platform/wayland/wayland_connection.h"
diff --git a/ui/ozone/platform/wayland/wayland_window.cc b/ui/ozone/platform/wayland/wayland_window.cc
index e5b7cd4..6ebe4075 100644
--- a/ui/ozone/platform/wayland/wayland_window.cc
+++ b/ui/ozone/platform/wayland/wayland_window.cc
@@ -7,7 +7,6 @@
 #include <wayland-client.h>
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/events/event.h"
 #include "ui/events/ozone/events_ozone.h"
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 4f0e938d6..9dd37001 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/x/x11_util.h"
diff --git a/ui/ozone/platform/x11/x11_surface_factory.cc b/ui/ozone/platform/x11/x11_surface_factory.cc
index 95ec3306..b0207c1 100644
--- a/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -4,7 +4,6 @@
 
 #include "ui/ozone/platform/x11/x11_surface_factory.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/gfx/x/x11_types.h"
 #include "ui/gl/gl_surface_egl.h"
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc
index 84b2a9e..a5b80a03 100644
--- a/ui/snapshot/snapshot_aura.cc
+++ b/ui/snapshot/snapshot_aura.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/memory/ptr_util.h"
 #include "base/task_runner_util.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/ui/touch_selection/touch_handle_unittest.cc b/ui/touch_selection/touch_handle_unittest.cc
index c723009..991f44b 100644
--- a/ui/touch_selection/touch_handle_unittest.cc
+++ b/ui/touch_selection/touch_handle_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/touch_selection/touch_handle.h"
 
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/motion_event_test_utils.h"
 #include "ui/gfx/geometry/rect_f.h"
diff --git a/ui/touch_selection/touch_selection_controller_unittest.cc b/ui/touch_selection/touch_selection_controller_unittest.cc
index d0bf65b..1848499 100644
--- a/ui/touch_selection/touch_selection_controller_unittest.cc
+++ b/ui/touch_selection/touch_selection_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/motion_event_test_utils.h"
diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.cc b/ui/views/accessibility/native_view_accessibility_auralinux.cc
index 0be9b7cf..1d155c6f 100644
--- a/ui/views/accessibility/native_view_accessibility_auralinux.cc
+++ b/ui/views/accessibility/native_view_accessibility_auralinux.cc
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/stl_util.h"
 #include "ui/accessibility/ax_action_data.h"
diff --git a/ui/views/accessibility/native_view_accessibility_base.cc b/ui/views/accessibility/native_view_accessibility_base.cc
index 02e2a37..e895c9d 100644
--- a/ui/views/accessibility/native_view_accessibility_base.cc
+++ b/ui/views/accessibility/native_view_accessibility_base.cc
@@ -8,7 +8,6 @@
 #include "ui/views/accessibility/native_view_accessibility_base.h"
 
 #include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/events/event_utils.h"
diff --git a/ui/views/accessibility/native_view_accessibility_mac.mm b/ui/views/accessibility/native_view_accessibility_mac.mm
index c6374ce..be5b197 100644
--- a/ui/views/accessibility/native_view_accessibility_mac.mm
+++ b/ui/views/accessibility/native_view_accessibility_mac.mm
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/ui/views/accessibility/native_view_accessibility_unittest.cc b/ui/views/accessibility/native_view_accessibility_unittest.cc
index d146b337..c490403 100644
--- a/ui/views/accessibility/native_view_accessibility_unittest.cc
+++ b/ui/views/accessibility/native_view_accessibility_unittest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/gfx/geometry/rect_conversions.h"
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index def94a1..7491a60f 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -10,7 +10,6 @@
 #include <set>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/windows_version.h"
diff --git a/ui/views/accessible_pane_view.cc b/ui/views/accessible_pane_view.cc
index a22b696..87cb386a 100644
--- a/ui/views/accessible_pane_view.cc
+++ b/ui/views/accessible_pane_view.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/accessible_pane_view.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/views/focus/focus_search.h"
diff --git a/ui/views/animation/ink_drop_highlight_unittest.cc b/ui/views/animation/ink_drop_highlight_unittest.cc
index f804b934..22f4385 100644
--- a/ui/views/animation/ink_drop_highlight_unittest.cc
+++ b/ui/views/animation/ink_drop_highlight_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 37439db9..8a60f37 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/animation/ink_drop_host_view.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/event.h"
 #include "ui/events/scoped_target_handler.h"
 #include "ui/gfx/color_palette.h"
diff --git a/ui/views/animation/ink_drop_impl.cc b/ui/views/animation/ink_drop_impl.cc
index cf6247ec..96328205c 100644
--- a/ui/views/animation/ink_drop_impl.cc
+++ b/ui/views/animation/ink_drop_impl.cc
@@ -5,7 +5,6 @@
 #include "ui/views/animation/ink_drop_impl.h"
 
 #include "base/auto_reset.h"
-#include "base/memory/ptr_util.h"
 #include "base/timer/timer.h"
 #include "ui/compositor/layer.h"
 #include "ui/views/animation/ink_drop_highlight.h"
diff --git a/ui/views/animation/ink_drop_impl_unittest.cc b/ui/views/animation/ink_drop_impl_unittest.cc
index 02ad6f7..e485be3 100644
--- a/ui/views/animation/ink_drop_impl_unittest.cc
+++ b/ui/views/animation/ink_drop_impl_unittest.cc
@@ -7,7 +7,6 @@
 #include "ui/views/animation/ink_drop_impl.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/test/gtest_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/views/animation/test/ink_drop_impl_test_api.cc b/ui/views/animation/test/ink_drop_impl_test_api.cc
index c780502f..3654224 100644
--- a/ui/views/animation/test/ink_drop_impl_test_api.cc
+++ b/ui/views/animation/test/ink_drop_impl_test_api.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/animation/test/ink_drop_impl_test_api.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_ripple.h"
 #include "ui/views/animation/test/ink_drop_highlight_test_api.h"
diff --git a/ui/views/animation/test/test_ink_drop_host.cc b/ui/views/animation/test/test_ink_drop_host.cc
index 021070c..69caa02 100644
--- a/ui/views/animation/test/test_ink_drop_host.cc
+++ b/ui/views/animation/test/test_ink_drop_host.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/animation/test/test_ink_drop_host.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_impl.h"
diff --git a/ui/views/background.cc b/ui/views/background.cc
index 93bd98f..3b728d7 100644
--- a/ui/views/background.cc
+++ b/ui/views/background.cc
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/scoped_observer.h"
 #include "build/build_config.h"
 #include "ui/gfx/canvas.h"
diff --git a/ui/views/bubble/bubble_dialog_delegate.cc b/ui/views/bubble/bubble_dialog_delegate.cc
index 07dfbf71..5856ea9 100644
--- a/ui/views/bubble/bubble_dialog_delegate.cc
+++ b/ui/views/bubble/bubble_dialog_delegate.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/bubble/bubble_dialog_delegate.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/views/bubble/tooltip_icon.cc b/ui/views/bubble/tooltip_icon.cc
index de30b6dc..b25fd52 100644
--- a/ui/views/bubble/tooltip_icon.cc
+++ b/ui/views/bubble/tooltip_icon.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/bubble/tooltip_icon.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/timer/timer.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index 713ca00..64ea16b8 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -12,7 +12,6 @@
 #import "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #import "base/mac/sdk_forward_declarations.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/viz/common/features.h"
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 7cf9868..d56f4cb 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -10,7 +10,6 @@
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/gfx/animation/throb_animation.h"
 #include "ui/gfx/canvas.h"
diff --git a/ui/views/controls/button/toggle_button_unittest.cc b/ui/views/controls/button/toggle_button_unittest.cc
index ac61914..2315f79 100644
--- a/ui/views/controls/button/toggle_button_unittest.cc
+++ b/ui/views/controls/button/toggle_button_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/views/controls/button/toggle_button.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_utils.h"
diff --git a/ui/views/controls/image_view_unittest.cc b/ui/views/controls/image_view_unittest.cc
index 417d342d..28cbb214 100644
--- a/ui/views/controls/image_view_unittest.cc
+++ b/ui/views/controls/image_view_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/views/controls/image_view.h"
 
 #include "base/i18n/rtl.h"
-#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index 9085592..b5baab3c 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -14,7 +14,6 @@
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 95679ef4..ec25ede2 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 4c71392..1e6f6cc1 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -10,7 +10,6 @@
 #include "base/i18n/case_conversion.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
diff --git a/ui/views/controls/menu/menu_runner_unittest.cc b/ui/views/controls/menu/menu_runner_unittest.cc
index caad764..79875e4 100644
--- a/ui/views/controls/menu/menu_runner_unittest.cc
+++ b/ui/views/controls/menu/menu_runner_unittest.cc
@@ -9,7 +9,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/events/test/event_generator.h"
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc
index c2dce06..2e2e6b2 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -5,7 +5,6 @@
 #include "ui/views/controls/menu/menu_scroll_view_container.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "cc/paint/paint_flags.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc
index a9d8f72b..3f38a248 100644
--- a/ui/views/controls/menu/native_menu_win.cc
+++ b/ui/views/controls/menu/native_menu_win.cc
@@ -5,7 +5,6 @@
 #include "ui/views/controls/menu/native_menu_win.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc
index 16ec528c8..6b818c25 100644
--- a/ui/views/controls/scroll_view_unittest.cc
+++ b/ui/views/controls/scroll_view_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/views/controls/scroll_view.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 638037a..acf7e59 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index 9f57716..7b06af51 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index da06855..4b8d78b 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/i18n/rtl.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "components/vector_icons/vector_icons.h"
diff --git a/ui/views/controls/tree/tree_view_unittest.cc b/ui/views/controls/tree/tree_view_unittest.cc
index 02d3ef1..fa4c7bf 100644
--- a/ui/views/controls/tree/tree_view_unittest.cc
+++ b/ui/views/controls/tree/tree_view_unittest.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/models/tree_node_model.h"
diff --git a/ui/views/controls/views_text_services_context_menu_mac.mm b/ui/views/controls/views_text_services_context_menu_mac.mm
index 0b977f4..37bb9a8f 100644
--- a/ui/views/controls/views_text_services_context_menu_mac.mm
+++ b/ui/views/controls/views_text_services_context_menu_mac.mm
@@ -7,7 +7,6 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/cocoa/text_services_context_menu.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc
index 741321e..b679af9 100644
--- a/ui/views/controls/webview/webview_unittest.cc
+++ b/ui/views/controls/webview/webview_unittest.cc
@@ -14,6 +14,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
@@ -191,6 +192,10 @@
   }
 
  private:
+  // TODO(lukasza): https://crbug.com/832100: Move the factory into
+  // TestingProfile, so individual tests don't need to worry about it.
+  content::ScopedMockRenderProcessHostFactory process_factory_;
+
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   std::unique_ptr<content::TestBrowserContext> browser_context_;
   content::TestContentBrowserClient test_browser_client_;
diff --git a/ui/views/examples/box_layout_example.cc b/ui/views/examples/box_layout_example.cc
index 989b17ff..2c4fba15 100644
--- a/ui/views/examples/box_layout_example.cc
+++ b/ui/views/examples/box_layout_example.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc
index e6b46660..b903e47 100644
--- a/ui/views/examples/examples_window.cc
+++ b/ui/views/examples/examples_window.cc
@@ -10,7 +10,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/views/examples/examples_window_with_content.cc b/ui/views/examples/examples_window_with_content.cc
index bf87c71..1133e88 100644
--- a/ui/views/examples/examples_window_with_content.cc
+++ b/ui/views/examples/examples_window_with_content.cc
@@ -8,7 +8,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "content/public/browser/browser_context.h"
 #include "ui/views/examples/webview_example.h"
 
diff --git a/ui/views/examples/text_example.cc b/ui/views/examples/text_example.cc
index 8b95cf23..17439cc 100644
--- a/ui/views/examples/text_example.cc
+++ b/ui/views/examples/text_example.cc
@@ -5,7 +5,6 @@
 #include "ui/views/examples/text_example.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
diff --git a/ui/views/examples/tree_view_example.cc b/ui/views/examples/tree_view_example.cc
index c6621eb3..6626f709a 100644
--- a/ui/views/examples/tree_view_example.cc
+++ b/ui/views/examples/tree_view_example.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/examples/tree_view_example.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/menu/menu_model_adapter.h"
diff --git a/ui/views/focus/external_focus_tracker.cc b/ui/views/focus/external_focus_tracker.cc
index 280f09f..b843dc2 100644
--- a/ui/views/focus/external_focus_tracker.cc
+++ b/ui/views/focus/external_focus_tracker.cc
@@ -5,7 +5,6 @@
 #include "ui/views/focus/external_focus_tracker.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/views/view.h"
 #include "ui/views/view_tracker.h"
 
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index c3c5e4c..fb3b901 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -10,7 +10,6 @@
 #include "base/auto_reset.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/text_input_client.h"
diff --git a/ui/views/focus/focus_manager_factory.cc b/ui/views/focus/focus_manager_factory.cc
index 85c5e49..5ebe513 100644
--- a/ui/views/focus/focus_manager_factory.cc
+++ b/ui/views/focus/focus_manager_factory.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/focus/focus_manager_factory.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/views/focus/focus_manager.h"
 #include "ui/views/focus/focus_manager_delegate.h"
 
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc
index ff55f0a..809b6d8 100644
--- a/ui/views/focus/focus_manager_unittest.cc
+++ b/ui/views/focus/focus_manager_unittest.cc
@@ -11,7 +11,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/icu_test_util.h"
 #include "ui/base/accelerators/accelerator.h"
diff --git a/ui/views/focus/focus_traversal_unittest.cc b/ui/views/focus/focus_traversal_unittest.cc
index 5085a70..2e45e0a 100644
--- a/ui/views/focus/focus_traversal_unittest.cc
+++ b/ui/views/focus/focus_traversal_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/views/layout/layout_provider.cc b/ui/views/layout/layout_provider.cc
index d00abb9f..1902f4f 100644
--- a/ui/views/layout/layout_provider.cc
+++ b/ui/views/layout/layout_provider.cc
@@ -5,7 +5,6 @@
 #include "ui/views/layout/layout_provider.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/font_list.h"
 #include "ui/views/style/typography.h"
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc
index bac5ac7..c417e73 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/mus/desktop_window_tree_host_mus.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/aura/client/aura_constants.h"
diff --git a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
index 34a105de7..50851a87 100644
--- a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/debug/stack_trace.h"
 #include "base/run_loop.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/transient_window_client.h"
diff --git a/ui/views/mus/pointer_watcher_event_router_unittest.cc b/ui/views/mus/pointer_watcher_event_router_unittest.cc
index bdccaff..7634fff7 100644
--- a/ui/views/mus/pointer_watcher_event_router_unittest.cc
+++ b/ui/views/mus/pointer_watcher_event_router_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc
index 5bbb94a..3b2cfcd 100644
--- a/ui/views/mus/views_mus_test_suite.cc
+++ b/ui/views/mus/views_mus_test_suite.cc
@@ -10,7 +10,6 @@
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/ui/views/painter.cc b/ui/views/painter.cc
index 85ee094..d93eacd 100644
--- a/ui/views/painter.cc
+++ b/ui/views/painter.cc
@@ -5,7 +5,6 @@
 #include "ui/views/painter.h"
 
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_delegate.h"
 #include "ui/compositor/layer_owner.h"
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc
index 6717102..99793bc8 100644
--- a/ui/views/style/platform_style.cc
+++ b/ui/views/style/platform_style.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/style/platform_style.h"
 
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm
index 4be5bae..36cdfff6 100644
--- a/ui/views/style/platform_style_mac.mm
+++ b/ui/views/style/platform_style_mac.mm
@@ -4,7 +4,6 @@
 
 #include "ui/views/style/platform_style.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "ui/base/ui_features.h"
 #include "ui/gfx/color_utils.h"
diff --git a/ui/views/test/combobox_test_api.cc b/ui/views/test/combobox_test_api.cc
index 877f2eb..b443d94 100644
--- a/ui/views/test/combobox_test_api.cc
+++ b/ui/views/test/combobox_test_api.cc
@@ -7,7 +7,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/menu/menu_runner.h"
diff --git a/ui/views/test/native_widget_factory_aura_mus.cc b/ui/views/test/native_widget_factory_aura_mus.cc
index 6745c0c..e99ad33 100644
--- a/ui/views/test/native_widget_factory_aura_mus.cc
+++ b/ui/views/test/native_widget_factory_aura_mus.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/test/native_widget_factory.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/views/mus/desktop_window_tree_host_mus.h"
 #include "ui/views/mus/mus_client.h"
diff --git a/ui/views/test/platform_test_helper_cocoa.mm b/ui/views/test/platform_test_helper_cocoa.mm
index a934f58..5354cd4 100644
--- a/ui/views/test/platform_test_helper_cocoa.mm
+++ b/ui/views/test/platform_test_helper_cocoa.mm
@@ -9,7 +9,6 @@
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #import "ui/views/cocoa/bridged_native_widget.h"
 #include "ui/views/widget/native_widget_mac.h"
 #include "ui/views/widget/widget.h"
diff --git a/ui/views/test/test_views_delegate.h b/ui/views/test/test_views_delegate.h
index f9c5719..b3596e0 100644
--- a/ui/views/test/test_views_delegate.h
+++ b/ui/views/test/test_views_delegate.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/views/layout/layout_provider.h"
 #include "ui/views/views_delegate.h"
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 398a23a6..f544882 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -12,7 +12,6 @@
 #include "base/containers/adapters.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/ui/views/view_tracker_unittest.cc b/ui/views/view_tracker_unittest.cc
index de14208d..ab06814f 100644
--- a/ui/views/view_tracker_unittest.cc
+++ b/ui/views/view_tracker_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/view_tracker.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/view.h"
 
diff --git a/ui/views/views_delegate.cc b/ui/views/views_delegate.cc
index 964f139..a64b2cb2 100644
--- a/ui/views/views_delegate.cc
+++ b/ui/views/views_delegate.cc
@@ -5,7 +5,6 @@
 #include "ui/views/views_delegate.h"
 
 #include "base/command_line.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "ui/views/views_touch_selection_controller_factory.h"
 #include "ui/views/widget/native_widget_private.h"
diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
index 5158b0d..3a7edcd 100644
--- a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/win/win_util.h"
 #include "ui/aura/client/drag_drop_client.h"
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 8135e9d..bb391ec 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
index 94d8a57..7350780 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
diff --git a/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc b/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
index 1e17f0f..e0a11a0 100644
--- a/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
+++ b/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 48518a5..76f19a2 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/views/widget/native_widget_aura_interactive_uitest.cc b/ui/views/widget/native_widget_aura_interactive_uitest.cc
index 28bfeac..b4de50c 100644
--- a/ui/views/widget/native_widget_aura_interactive_uitest.cc
+++ b/ui/views/widget/native_widget_aura_interactive_uitest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/widget/native_widget_aura.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/window.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/test/native_widget_factory.h"
diff --git a/ui/views/win/pen_event_processor.cc b/ui/views/win/pen_event_processor.cc
index 17f5170502..5de8173 100644
--- a/ui/views/win/pen_event_processor.cc
+++ b/ui/views/win/pen_event_processor.cc
@@ -4,7 +4,6 @@
 
 #include "pen_event_processor.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "ui/events/event_utils.h"
 
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
index f2d94480..5e069a548 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -169,7 +169,7 @@
       }
     </style>
 
-    <div id="root" on-contextmenu="onContextMenu_">
+    <div id="root" on-contextmenu="onContextMenu_" on-tap="focusInput_">
       <div id="pinInputDiv" class="row">
         <paper-input id="pinInput" type="password" no-label-float
             value="[[value]]"
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
index 2ebcaaf4..8ffadaa 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
@@ -197,6 +197,17 @@
   },
 
   /**
+   * Transfers focus to the input. Called when a non button element on the
+   * PIN button area is clicked to prevent focus from leaving the input.
+   */
+  focusInput_: function() {
+    // Focus the input and place the selected region to its exact previous
+    // location, as this function will not be called by something that will also
+    // modify the input value.
+    this.focus(this.selectionStart_, this.selectionEnd_);
+  },
+
+  /**
    * Called when a keypad number has been tapped.
    * @param {Event} event The event object.
    * @private
@@ -372,7 +383,7 @@
    * @private
    */
   hasInput_: function(value) {
-    return value.length > 0;
+    return value.length > 0 && this.selectionStart_ > 0;
   },
 
   /**
diff --git a/ui/wm/core/focus_controller_unittest.cc b/ui/wm/core/focus_controller_unittest.cc
index 22974fa..684cdea 100644
--- a/ui/wm/core/focus_controller_unittest.cc
+++ b/ui/wm/core/focus_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include <map>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/focus_change_observer.h"
diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
index d8781f7..af1a9b13 100644
--- a/ui/wm/core/window_animations.cc
+++ b/ui/wm/core/window_animations.cc
@@ -14,7 +14,6 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
diff --git a/ui/wm/core/window_util.cc b/ui/wm/core/window_util.cc
index d8cbfdc..7b00a00b 100644
--- a/ui/wm/core/window_util.cc
+++ b/ui/wm/core/window_util.cc
@@ -4,7 +4,6 @@
 
 #include "ui/wm/core/window_util.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/wm/core/wm_state.cc b/ui/wm/core/wm_state.cc
index a68006d..89410d8 100644
--- a/ui/wm/core/wm_state.cc
+++ b/ui/wm/core/wm_state.cc
@@ -4,7 +4,6 @@
 
 #include "ui/wm/core/wm_state.h"
 
-#include "base/memory/ptr_util.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/wm/core/capture_controller.h"
 #include "ui/wm/core/transient_window_controller.h"