diff --git a/DEPS b/DEPS
index 2e49524..13151fa 100644
--- a/DEPS
+++ b/DEPS
@@ -199,11 +199,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '0a0ad5be0e404299c37c499e4a26dafc52f020fb',
+  'skia_revision': '94e72b90b8e83adac8d1186d3e5daeeda834adee',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e60468ddb6a9b78c3eef0e40c1f17c73c8b0d2c0',
+  'v8_revision': '5bc36e7aec3d7acdb0cb6bca02c0788d5993abbc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -211,11 +211,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '85a9ec10b18fdb9cabb8177d95892e46d7abcc87',
+  'angle_revision': 'e3096d0729df059f1d251405d16eef9e71ba2516',
   # 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': 'a483f3814f0dd7d5e1a4ec18cc555b6a37d2f9dd',
+  'swiftshader_revision': '4d22b2c30f55e7edf6c2340d165e85fd386bd489',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -270,7 +270,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': 'e549290ec8ba7aaab20555967f08faed18d7f469',
+  'catapult_revision': '4920147e9085d6a42b3b304c8b6cfea67e418555',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -278,7 +278,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '9c44c93044d66b74c15cc27c9697518cf5df4458',
+  'devtools_frontend_revision': '6650d6204da2596aa67fa261ad5b6602b0983dd1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -322,7 +322,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '28ff109d78bbe4c1fc00694f48c2030f415ccbc2',
+  'quiche_revision': '3366808a277e0224a083af64a84274df198a9c89',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -490,7 +490,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/autofill/captured_sites',
-        'version': '0pgUX3VESdjGKemtmjistv4nlStl7b-qTsNn71BLgc4C',
+        'version': '-vI5CMccdvrghkWJqjvLu9QWqnAvidTWtzK46qs_rdcC',
       }
     ],
     'condition': 'checkout_chromium_autofill_test_dependencies',
@@ -905,7 +905,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cb07c525c00132fc8cb52cdff78e1078c280a4a1',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0f790421b29596227054e934c0add868e385d0d9',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1270,7 +1270,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '7551137d36dd06b5622959c02e06fd45d5d05459',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '0c8af4a753e6df81ea97768468b9ae6154cd70d0',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1348,7 +1348,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'Y_rckHsnBv6dqNUbG4QoVkl3njqEx7ewCNGmqOE_h1MC'
+              'version': 'k_Yz9epzSVRBLbc_rxW4zlFu27-GJMndNt6QAsbq4gkC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1506,7 +1506,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '66460536ee975a3e98931b7b40a661a63fd9cd57',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'b853d722501bcd445f802d59face4ff7892daea7',
+    Var('webrtc_git') + '/src.git' + '@' + '989e6e7d22e281dde977c349355a8f1d76a8dff3',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1578,7 +1578,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6715a4f2a9e433989529cfaaf890c738099a64a5',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@958a5f337769019d6bd36fdc849bf20071105468',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index b557127..b9666f53 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -332,17 +332,19 @@
   '^base/callback.h',  # Intentional.
   '^base/cancelable_callback.h',  # Intentional.
   '^chrome/browser/apps/guest_view/web_view_browsertest.cc',
+  "^chrome/browser/ash/accessibility/",
   '^chrome/browser/captive_portal/captive_portal_browsertest.cc',
   '^chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos.cc', # pylint: disable=line-too-long
   '^chrome/browser/history/android/android_history_provider_service_unittest.cc', # pylint: disable=line-too-long
   '^chrome/browser/media_galleries/',
+  "^chrome/browser/metrics/",
   '^chrome/browser/net/websocket_browsertest.cc',
-  '^chrome/browser/notifications/',
   '^chrome/browser/ntp_tiles/ntp_tiles_browsertest.cc',
   '^chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc', # pylint: disable=line-too-long
   '^chrome/browser/payments/payment_manifest_parser_browsertest.cc',
-  '^chrome/browser/plugins/',
   '^chrome/browser/portal/portal_browsertest.cc',
+  "^chrome/browser/prefetch/no_state_prefetch/",
+  '^chrome/browser/previews/',
   '^chrome/browser/profiling_host/profiling_process_host.cc',
   '^chrome/browser/recovery/recovery_install_global_error.cc',
   '^chrome/browser/resources/chromeos/accessibility/',
@@ -351,12 +353,22 @@
   '^chrome/browser/signin/',
   '^chrome/browser/site_isolation/site_per_process_text_input_browsertest.cc',
   '^chrome/browser/sync_file_system/',
-  '^chrome/browser/web_applications/',
+  "^components/browsing_data/content/",
+  "^components/enterprise/browser/controller/chrome_browser_cloud_management_controller\\.cc", # pylint: disable=line-too-long
+  "^components/feature_engagement/internal/",
+  "^docs/callback\\.md",  # Intentional
+  "^docs/webui_explainer\\.md",
+  "^docs/process/lsc/large_scale_changes\\.md",  # Intentional
+  "^docs/security/mojo\\.md",
+  "^docs/threading_and_tasks\\.md",
+  "^docs/ui/learn/bestpractices/layout\\.md",
   '^extensions/browser/',
   '^extensions/renderer/',
   '^media/blink/webmediaplayer_impl.cc',
   '^media/blink/webmediaplayer_impl.h',
   '^ppapi/proxy/',
+  '^third_party/blink/PRESUBMIT_test.py', # Intentional.
+  '^third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py' # Intentional pylint: disable=line-too-long
   '^tools/clang/base_bind_rewriters/',  # Intentional.
   '^tools/gdb/gdb_chrome.py',  # Intentional.
 ))
diff --git a/android_webview/browser/gfx/vulkan_gl_interop.cc b/android_webview/browser/gfx/vulkan_gl_interop.cc
index 8e765aab..234dfdb 100644
--- a/android_webview/browser/gfx/vulkan_gl_interop.cc
+++ b/android_webview/browser/gfx/vulkan_gl_interop.cc
@@ -322,8 +322,8 @@
   // Draw the SkImage.
   SkPaint paint;
   paint.setBlendMode(SkBlendMode::kSrcOver);
-  pending_draw->draw_context->getCanvas()->drawImage(pending_draw->ahb_skimage,
-                                                     0, 0, &paint);
+  pending_draw->draw_context->getCanvas()->drawImage(
+      pending_draw->ahb_skimage, 0, 0, SkSamplingOptions(), &paint);
   pending_draw->draw_context->flush();
 
   // Transfer |pending_draw| to |pending_draw_| for handling in
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 64a441070..1f7ec93 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -64,6 +64,7 @@
 #include "ui/base/ui_base_paths.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/gl/gl_switches.h"
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
 #include "components/spellcheck/common/spellcheck_features.h"
@@ -142,7 +143,6 @@
   // isn't much point in having the crash dumps there.
   cl->AppendSwitch(switches::kDisableOoprDebugCrashDump);
 
-#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
   if (cl->GetSwitchValueASCII(switches::kProcessType).empty()) {
     // Browser process (no type specified).
 
@@ -155,6 +155,9 @@
     ui::GestureConfiguration::GetInstance()
         ->set_fling_touchscreen_tap_suppression_enabled(false);
 
+    if (AwDrawFnImpl::IsUsingVulkan())
+      cl->AppendSwitch(switches::kWebViewDrawFunctorUsesVulkan);
+
 #if defined(USE_V8_CONTEXT_SNAPSHOT)
     gin::V8Initializer::V8SnapshotFileType file_type =
         gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext;
@@ -168,11 +171,7 @@
     base::android::RegisterApkAssetWithFileDescriptorStore(
         content::kV8Snapshot64DataDescriptor,
         gin::V8Initializer::GetSnapshotFilePath(false, file_type));
-
-    if (AwDrawFnImpl::IsUsingVulkan())
-      cl->AppendSwitch(switches::kWebViewDrawFunctorUsesVulkan);
   }
-#endif  // V8_USE_EXTERNAL_STARTUP_DATA
 
   if (cl->HasSwitch(switches::kWebViewSandboxedRenderer)) {
     content::RenderProcessHost::SetMaxRendererProcessCount(1u);
@@ -202,6 +201,10 @@
       // When draw functor uses vulkan, assume that it is safe to enable viz
       // which depends on shared images.
       features.EnableIfNotSet(::features::kEnableSharedImageForWebview);
+    } else {
+      // Not use ANGLE's Vulkan backend, if the draw functor is not using
+      // Vulkan.
+      features.DisableIfNotSet(::features::kDefaultANGLEVulkan);
     }
 
     // WebView uses kWebViewVulkan to control vulkan. Pre-emptively disable
diff --git a/ash/app_list/views/ghost_image_view.cc b/ash/app_list/views/ghost_image_view.cc
index 521f264..e7ff639 100644
--- a/ash/app_list/views/ghost_image_view.cc
+++ b/ash/app_list/views/ghost_image_view.cc
@@ -247,12 +247,13 @@
     SkIPoint thick_inner_blur_offset;
     preview.extractAlpha(&thick_inner_blur, &paint, &thick_inner_blur_offset);
 
+    SkSamplingOptions sampling;
     // Mask out the inner blur.
     paint.setMaskFilter(nullptr);
     paint.setBlendMode(SkBlendMode::kDstOut);
     canvas = std::make_unique<SkCanvas>(thick_inner_blur);
-    canvas->drawBitmap(preview, -thick_inner_blur_offset.fX,
-                       -thick_inner_blur_offset.fY, &paint);
+    canvas->drawImage(preview.asImage(), -thick_inner_blur_offset.fX,
+                      -thick_inner_blur_offset.fY, sampling, &paint);
     canvas->drawRect(
         SkRect{0, 0, -thick_inner_blur_offset.fX, thick_inner_blur.height()},
         paint);
@@ -264,14 +265,14 @@
     paint.setBlendMode(SkBlendMode::kPlus);
     canvas = std::make_unique<SkCanvas>(preview);
     canvas->drawColor(0, SkBlendMode::kClear);
-    canvas->drawBitmap(thick_inner_blur, thick_inner_blur_offset.fX,
-                       thick_inner_blur_offset.fY, &paint);
-    canvas->drawBitmap(thick_outer_blur, outer_blur_offset.fX,
-                       outer_blur_offset.fY, &paint);
+    canvas->drawImage(thick_inner_blur.asImage(), thick_inner_blur_offset.fX,
+                      thick_inner_blur_offset.fY, sampling, &paint);
+    canvas->drawImage(thick_outer_blur.asImage(), outer_blur_offset.fX,
+                      outer_blur_offset.fY, sampling, &paint);
 
     // Draw the bright outline.
-    canvas->drawBitmap(bright_outline, bright_outline_offset.fX,
-                       bright_outline_offset.fY, &paint);
+    canvas->drawImage(bright_outline.asImage(), bright_outline_offset.fX,
+                      bright_outline_offset.fY, sampling, &paint);
 
     // Cleanup bitmaps.
     canvas.reset();
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index e0ca385..838d4538 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -428,7 +428,7 @@
   recolored.allocN32Pixels(bitmap.width(), bitmap.height());
   recolored.eraseARGB(0, 0, 0, 0);
   SkCanvas canvas(recolored);
-  canvas.drawBitmap(bitmap, 0, 0);
+  canvas.drawImage(bitmap.asImage(), 0, 0);
   color_utils::HSL cursor_hsl;
   color_utils::SkColorToHSL(cursor_color_, &cursor_hsl);
   for (int y = 0; y < bitmap.height(); ++y) {
diff --git a/base/memory/checked_ptr.md b/base/memory/checked_ptr.md
index bce46ef5..6e96762 100644
--- a/base/memory/checked_ptr.md
+++ b/base/memory/checked_ptr.md
@@ -284,6 +284,23 @@
 - Avoid accessing `S` from the destructor of `Bar`
   (and in general, avoid doing significant work from destructors).
 
+#### Non-PA allocation address space reuse
+
+An address goes from the "outside GigaCage" state to "inside GigaCage" while a `CheckedPtr` is pointing at it.
+
+```cpp
+  CheckedPtr<void> checked_ptr = mmap([...]);
+  munmap(checked_ptr); // must be safe to keep checked_ptr alive since it's not going to be dereferenced
+  void* ptr = allocator.root()->Alloc(16, ""); // PA creates a new superpage, which is by coincidence around the address checked_ptr points to
+  checked_ptr = nullptr;
+```
+
+When this happens, it is like we skipped an `AddRef()` and `Release()` may decrement a non-existent ref count field. There is not enough address space to avoid the reuse on 32-bit platforms. In theory, we could store whether `CheckedPtr` pointed to a non-PA allocation during initialization and, therefore, should act like a no-op pointer, but we don't have a single spare bit in 32-bit pointers.
+
+#### Past-the-end pointers with non-PA allocations
+
+If we increment a `CheckedPtr` pointing at a non-PA allocation until it points past the end of the allocation, that pointer may happen to be pointing at the beginning of a PA superpage. Advancing the pointer through `operator+=()` assumes that the pointer stays within an allocation. So when this happens, it is as if we skipped an `AddRef()`, and `Release()` may decrement a non-existent ref count field.
+
 #### Other
 
 TODO(bartekn): Document runtime errors encountered by BackupRefPtr
diff --git a/base/test/test_timeouts.cc b/base/test/test_timeouts.cc
index 6972123..507c00d 100644
--- a/base/test/test_timeouts.cc
+++ b/base/test/test_timeouts.cc
@@ -71,6 +71,9 @@
   // A number of tests on ChromeOS run very close to the base limit, so ChromeOS
   // gets 3x.
   constexpr int kTimeoutMultiplier = 3;
+#elif !defined(NDEBUG) && defined(OS_MAC)
+  // A lot of browser_tests on Mac debug time out.
+  constexpr int kTimeoutMultiplier = 2;
 #else
   constexpr int kTimeoutMultiplier = 1;
 #endif
diff --git a/build/lacros/lacros_resource_sizes.py b/build/lacros/lacros_resource_sizes.py
index e0edb42..bf791c6 100755
--- a/build/lacros/lacros_resource_sizes.py
+++ b/build/lacros/lacros_resource_sizes.py
@@ -90,8 +90,8 @@
 
 
 # List of disjoint build artifact groups for size tracking. This list should be
-# synched with lacros-amd64-generic-rel builder contents (specified in
-# //infra/config/subprojects/chromium/ci.star) and
+# synched with lacros-amd64-generic-binary-size-rel builder contents (specified
+# in # //infra/config/subprojects/chromium/ci.star) and
 # chromeos-amd64-generic-lacros-internal builder (specified in src-internal).
 _TRACKED_GROUPS = [
     _Group(paths=['chrome'],
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc
index 0dcf681..20d95903 100644
--- a/cc/metrics/compositor_frame_reporter.cc
+++ b/cc/metrics/compositor_frame_reporter.cc
@@ -337,36 +337,6 @@
   return args.frame_time + (args.interval * 1.5);
 }
 
-#define REPORT_VIZ_TRACE_EVENT(start_time, end_time, index, trace_func) \
-  if (start_time <= end_time) {                                         \
-    const char* substage_name =                                         \
-        GetVizBreakdownName(static_cast<VizBreakdown>(index));          \
-    trace_func(start_time, end_time, substage_name);                    \
-  }
-
-#define REPORT_VIZ_BREAKDOWN_TRACES(trace_func)                                \
-  size_t start_to_buffer_available =                                           \
-      static_cast<size_t>(VizBreakdown::kSwapStartToBufferAvailable);          \
-  bool has_ready_timings = !!viz_breakdown_list_[start_to_buffer_available];   \
-  for (size_t i = 0; i < start_to_buffer_available; i++) {                     \
-    if (!viz_breakdown_list_[i]) {                                             \
-      break;                                                                   \
-    }                                                                          \
-    if (i == static_cast<size_t>(VizBreakdown::kSwapStartToSwapEnd) &&         \
-        has_ready_timings) {                                                   \
-      size_t latch_to_swap_end =                                               \
-          static_cast<size_t>(VizBreakdown::kLatchToSwapEnd);                  \
-      for (size_t j = start_to_buffer_available; j <= latch_to_swap_end;       \
-           j++) {                                                              \
-        REPORT_VIZ_TRACE_EVENT(viz_breakdown_list_[j]->first,                  \
-                               viz_breakdown_list_[j]->second, j, trace_func); \
-      }                                                                        \
-    } else {                                                                   \
-      REPORT_VIZ_TRACE_EVENT(viz_breakdown_list_[i]->first,                    \
-                             viz_breakdown_list_[i]->second, i, trace_func);   \
-    }                                                                          \
-  }
-
 bool IsScrollActive(const CompositorFrameReporter::ActiveTrackers& trackers) {
   return trackers.test(
              static_cast<size_t>(FrameSequenceTrackerType::kWheelScroll)) ||
@@ -378,6 +348,123 @@
 
 }  // namespace
 
+// CompositorFrameReporter::ProcessedVizBreakdown::Iterator ====================
+
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::Iterator(
+    const ProcessedVizBreakdown* owner,
+    bool skip_swap_start_to_swap_end)
+    : owner_(owner), skip_swap_start_to_swap_end_(skip_swap_start_to_swap_end) {
+  DCHECK(owner_);
+}
+
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::~Iterator() = default;
+
+bool CompositorFrameReporter::ProcessedVizBreakdown::Iterator::IsValid() const {
+  return index_ < base::size(owner_->list_) && owner_->list_[index_];
+}
+
+void CompositorFrameReporter::ProcessedVizBreakdown::Iterator::Advance() {
+  DCHECK(IsValid());
+  index_++;
+  if (static_cast<VizBreakdown>(index_) == VizBreakdown::kSwapStartToSwapEnd &&
+      skip_swap_start_to_swap_end_) {
+    index_++;
+  }
+}
+
+VizBreakdown
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetBreakdown() const {
+  DCHECK(IsValid());
+  return static_cast<VizBreakdown>(index_);
+}
+
+base::TimeTicks
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetStartTime() const {
+  DCHECK(IsValid());
+  return owner_->list_[index_]->first;
+}
+
+base::TimeTicks
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetEndTime() const {
+  DCHECK(IsValid());
+  return owner_->list_[index_]->second;
+}
+
+base::TimeDelta
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetDuration() const {
+  DCHECK(IsValid());
+  return owner_->list_[index_]->second - owner_->list_[index_]->first;
+}
+
+// CompositorFrameReporter::ProcessedVizBreakdown ==============================
+
+CompositorFrameReporter::ProcessedVizBreakdown::ProcessedVizBreakdown(
+    base::TimeTicks viz_start_time,
+    const viz::FrameTimingDetails& viz_breakdown) {
+  if (viz_start_time.is_null())
+    return;
+
+  // Check if `viz_breakdown` is set. Testing indicates that sometimes the
+  // received_compositor_frame_timestamp can be earlier than the given
+  // `viz_start_time`. Avoid reporting negative times.
+  if (viz_breakdown.received_compositor_frame_timestamp.is_null() ||
+      viz_breakdown.received_compositor_frame_timestamp < viz_start_time) {
+    return;
+  }
+  list_[static_cast<int>(VizBreakdown::kSubmitToReceiveCompositorFrame)] =
+      std::make_pair(viz_start_time,
+                     viz_breakdown.received_compositor_frame_timestamp);
+
+  if (viz_breakdown.draw_start_timestamp.is_null())
+    return;
+  list_[static_cast<int>(VizBreakdown::kReceivedCompositorFrameToStartDraw)] =
+      std::make_pair(viz_breakdown.received_compositor_frame_timestamp,
+                     viz_breakdown.draw_start_timestamp);
+
+  if (viz_breakdown.swap_timings.is_null())
+    return;
+  list_[static_cast<int>(VizBreakdown::kStartDrawToSwapStart)] =
+      std::make_pair(viz_breakdown.draw_start_timestamp,
+                     viz_breakdown.swap_timings.swap_start);
+
+  list_[static_cast<int>(VizBreakdown::kSwapStartToSwapEnd)] =
+      std::make_pair(viz_breakdown.swap_timings.swap_start,
+                     viz_breakdown.swap_timings.swap_end);
+
+  list_[static_cast<int>(VizBreakdown::kSwapEndToPresentationCompositorFrame)] =
+      std::make_pair(viz_breakdown.swap_timings.swap_end,
+                     viz_breakdown.presentation_feedback.timestamp);
+  swap_start_ = viz_breakdown.swap_timings.swap_start;
+
+  if (viz_breakdown.presentation_feedback.ready_timestamp.is_null())
+    return;
+  buffer_ready_available_ = true;
+  list_[static_cast<int>(VizBreakdown::kSwapStartToBufferAvailable)] =
+      std::make_pair(viz_breakdown.swap_timings.swap_start,
+                     viz_breakdown.presentation_feedback.available_timestamp);
+  list_[static_cast<int>(VizBreakdown::kBufferAvailableToBufferReady)] =
+      std::make_pair(viz_breakdown.presentation_feedback.available_timestamp,
+                     viz_breakdown.presentation_feedback.ready_timestamp);
+  list_[static_cast<int>(VizBreakdown::kBufferReadyToLatch)] =
+      std::make_pair(viz_breakdown.presentation_feedback.ready_timestamp,
+                     viz_breakdown.presentation_feedback.latch_timestamp);
+  list_[static_cast<int>(VizBreakdown::kLatchToSwapEnd)] =
+      std::make_pair(viz_breakdown.presentation_feedback.latch_timestamp,
+                     viz_breakdown.swap_timings.swap_end);
+}
+
+CompositorFrameReporter::ProcessedVizBreakdown::~ProcessedVizBreakdown() =
+    default;
+
+CompositorFrameReporter::ProcessedVizBreakdown::Iterator
+CompositorFrameReporter::ProcessedVizBreakdown::CreateIterator(
+    bool skip_swap_start_to_swap_end_if_breakdown_available) const {
+  return Iterator(this, skip_swap_start_to_swap_end_if_breakdown_available &&
+                            buffer_ready_available_);
+}
+
+// CompositorFrameReporter =====================================================
+
 CompositorFrameReporter::CompositorFrameReporter(
     const ActiveTrackers& active_trackers,
     const viz::BeginFrameArgs& args,
@@ -528,7 +615,8 @@
     TerminateFrame(FrameTerminationStatus::kUnknown, Now());
 
   PopulateBlinkBreakdownList();
-  PopulateVizBreakdownList();
+  processed_viz_breakdown_ =
+      std::make_unique<ProcessedVizBreakdown>(viz_start_time_, viz_breakdown_);
 
   DCHECK_EQ(current_stage_.start_time, base::TimeTicks());
   switch (frame_termination_status_) {
@@ -624,7 +712,8 @@
     UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type", report_type);
     if (latency_ukm_reporter_) {
       latency_ukm_reporter_->ReportCompositorLatencyUkm(
-          report_type, stage_history_, active_trackers_, viz_breakdown_);
+          report_type, stage_history_, active_trackers_,
+          *processed_viz_breakdown_);
     }
     bool any_active_interaction = false;
     for (size_t fst_type = 0; fst_type < active_trackers_.size(); ++fst_type) {
@@ -721,20 +810,13 @@
 
 void CompositorFrameReporter::ReportCompositorLatencyVizBreakdowns(
     FrameSequenceTrackerType frame_sequence_tracker_type) const {
-  for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
-    if (!viz_breakdown_list_[i]) {
-#if DCHECK_IS_ON()
-      // Remaining breakdowns should be unset.
-      for (; i < base::size(viz_breakdown_list_); i++)
-        DCHECK(!viz_breakdown_list_[i]);
-#endif
-      break;
-    }
-    const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
-    const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
-    ReportCompositorLatencyHistogram(frame_sequence_tracker_type,
-                                     kVizBreakdownInitialIndex + i,
-                                     end_time - start_time);
+  DCHECK(processed_viz_breakdown_);
+  for (auto it = processed_viz_breakdown_->CreateIterator(false); it.IsValid();
+       it.Advance()) {
+    ReportCompositorLatencyHistogram(
+        frame_sequence_tracker_type,
+        kVizBreakdownInitialIndex + static_cast<size_t>(it.GetBreakdown()),
+        it.GetDuration());
   }
 }
 
@@ -888,7 +970,7 @@
 
   if (latency_ukm_reporter_) {
     latency_ukm_reporter_->ReportEventLatencyUkm(
-        events_metrics_, stage_history_, viz_breakdown_);
+        events_metrics_, stage_history_, *processed_viz_breakdown_);
   }
 }
 
@@ -905,20 +987,13 @@
 void CompositorFrameReporter::ReportEventLatencyVizBreakdowns(
     int histogram_base_index,
     const std::string& histogram_base_name) const {
-  for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
-    if (!viz_breakdown_list_[i]) {
-#if DCHECK_IS_ON()
-      // Remaining breakdowns should be unset.
-      for (; i < base::size(viz_breakdown_list_); i++)
-        DCHECK(!viz_breakdown_list_[i]);
-#endif
-      break;
-    }
-    const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
-    const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
-    ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
-                                kVizBreakdownInitialIndex + i,
-                                end_time - start_time);
+  DCHECK(processed_viz_breakdown_);
+  for (auto it = processed_viz_breakdown_->CreateIterator(false); it.IsValid();
+       it.Advance()) {
+    ReportEventLatencyHistogram(
+        histogram_base_index, histogram_base_name,
+        kVizBreakdownInitialIndex + static_cast<size_t>(it.GetBreakdown()),
+        it.GetDuration());
   }
 }
 
@@ -1000,14 +1075,19 @@
                         trace_track, stage.start_time);
       if (stage.stage_type ==
           StageType::kSubmitCompositorFrameToPresentationCompositorFrame) {
-        REPORT_VIZ_BREAKDOWN_TRACES([&](base::TimeTicks start_time,
-                                        base::TimeTicks end_time,
-                                        const char* substage_name) {
+        DCHECK(processed_viz_breakdown_);
+        for (auto it = processed_viz_breakdown_->CreateIterator(true);
+             it.IsValid(); it.Advance()) {
+          base::TimeTicks start_time = it.GetStartTime();
+          base::TimeTicks end_time = it.GetEndTime();
+          if (start_time >= end_time)
+            continue;
+          const char* breakdown_name = GetVizBreakdownName(it.GetBreakdown());
           TRACE_EVENT_BEGIN("cc,benchmark",
-                            perfetto::StaticString{substage_name}, trace_track,
+                            perfetto::StaticString{breakdown_name}, trace_track,
                             start_time);
           TRACE_EVENT_END("cc,benchmark", trace_track, end_time);
-        });
+        }
       }
       TRACE_EVENT_END("cc,benchmark", trace_track, stage.end_time);
     }
@@ -1110,14 +1190,19 @@
 
       if (stage_it->stage_type ==
           StageType::kSubmitCompositorFrameToPresentationCompositorFrame) {
-        REPORT_VIZ_BREAKDOWN_TRACES([&](base::TimeTicks start_time,
-                                        base::TimeTicks end_time,
-                                        const char* substage_name) {
+        DCHECK(processed_viz_breakdown_);
+        for (auto it = processed_viz_breakdown_->CreateIterator(true);
+             it.IsValid(); it.Advance()) {
+          base::TimeTicks start_time = it.GetStartTime();
+          base::TimeTicks end_time = it.GetEndTime();
+          if (start_time >= end_time)
+            continue;
+          const char* breakdown_name = GetVizBreakdownName(it.GetBreakdown());
           TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
-              "cc,input", substage_name, trace_id, start_time);
+              "cc,input", breakdown_name, trace_id, start_time);
           TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
-              "cc,input", substage_name, trace_id, end_time);
-        });
+              "cc,input", breakdown_name, trace_id, end_time);
+        }
       }
 
       TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
@@ -1158,62 +1243,6 @@
       begin_main_frame_start_ - blink_start_time_;
 }
 
-void CompositorFrameReporter::PopulateVizBreakdownList() {
-  if (viz_start_time_.is_null())
-    return;
-
-  // Check if viz_breakdown is set. Testing indicates that sometimes the
-  // received_compositor_frame_timestamp can be earlier than the given
-  // |start_time|. Avoid reporting negative times.
-  if (viz_breakdown_.received_compositor_frame_timestamp.is_null() ||
-      viz_breakdown_.received_compositor_frame_timestamp < viz_start_time_) {
-    return;
-  }
-  viz_breakdown_list_[static_cast<int>(
-      VizBreakdown::kSubmitToReceiveCompositorFrame)] =
-      std::make_pair(viz_start_time_,
-                     viz_breakdown_.received_compositor_frame_timestamp);
-
-  if (viz_breakdown_.draw_start_timestamp.is_null())
-    return;
-  viz_breakdown_list_[static_cast<int>(
-      VizBreakdown::kReceivedCompositorFrameToStartDraw)] =
-      std::make_pair(viz_breakdown_.received_compositor_frame_timestamp,
-                     viz_breakdown_.draw_start_timestamp);
-
-  if (viz_breakdown_.swap_timings.is_null())
-    return;
-  viz_breakdown_list_[static_cast<int>(VizBreakdown::kStartDrawToSwapStart)] =
-      std::make_pair(viz_breakdown_.draw_start_timestamp,
-                     viz_breakdown_.swap_timings.swap_start);
-
-  viz_breakdown_list_[static_cast<int>(VizBreakdown::kSwapStartToSwapEnd)] =
-      std::make_pair(viz_breakdown_.swap_timings.swap_start,
-                     viz_breakdown_.swap_timings.swap_end);
-
-  viz_breakdown_list_[static_cast<int>(
-      VizBreakdown::kSwapEndToPresentationCompositorFrame)] =
-      std::make_pair(viz_breakdown_.swap_timings.swap_end,
-                     viz_breakdown_.presentation_feedback.timestamp);
-
-  if (viz_breakdown_.presentation_feedback.ready_timestamp.is_null())
-    return;
-  viz_breakdown_list_[static_cast<int>(
-      VizBreakdown::kSwapStartToBufferAvailable)] =
-      std::make_pair(viz_breakdown_.swap_timings.swap_start,
-                     viz_breakdown_.presentation_feedback.available_timestamp);
-  viz_breakdown_list_[static_cast<int>(
-      VizBreakdown::kBufferAvailableToBufferReady)] =
-      std::make_pair(viz_breakdown_.presentation_feedback.available_timestamp,
-                     viz_breakdown_.presentation_feedback.ready_timestamp);
-  viz_breakdown_list_[static_cast<int>(VizBreakdown::kBufferReadyToLatch)] =
-      std::make_pair(viz_breakdown_.presentation_feedback.ready_timestamp,
-                     viz_breakdown_.presentation_feedback.latch_timestamp);
-  viz_breakdown_list_[static_cast<int>(VizBreakdown::kLatchToSwapEnd)] =
-      std::make_pair(viz_breakdown_.presentation_feedback.latch_timestamp,
-                     viz_breakdown_.swap_timings.swap_end);
-}
-
 base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const {
   base::TimeDelta sum;
   for (const StageData& stage : stage_history_)
diff --git a/cc/metrics/compositor_frame_reporter.h b/cc/metrics/compositor_frame_reporter.h
index 6f356b5..02eb68d 100644
--- a/cc/metrics/compositor_frame_reporter.h
+++ b/cc/metrics/compositor_frame_reporter.h
@@ -140,6 +140,53 @@
     kSmoothBoth
   };
 
+  // Holds a processed list of Viz breakdowns with an `Iterator` class to easily
+  // iterate over them.
+  class CC_EXPORT ProcessedVizBreakdown {
+   public:
+    class Iterator {
+     public:
+      Iterator(const ProcessedVizBreakdown* owner,
+               bool skip_swap_start_to_swap_end);
+      ~Iterator();
+
+      bool IsValid() const;
+      void Advance();
+      VizBreakdown GetBreakdown() const;
+      base::TimeTicks GetStartTime() const;
+      base::TimeTicks GetEndTime() const;
+      base::TimeDelta GetDuration() const;
+
+     private:
+      const ProcessedVizBreakdown* owner_;
+      const bool skip_swap_start_to_swap_end_;
+
+      size_t index_ = 0;
+    };
+
+    ProcessedVizBreakdown(base::TimeTicks viz_start_time,
+                          const viz::FrameTimingDetails& viz_breakdown);
+    ~ProcessedVizBreakdown();
+
+    ProcessedVizBreakdown(const ProcessedVizBreakdown&) = delete;
+    ProcessedVizBreakdown& operator=(const ProcessedVizBreakdown&) = delete;
+
+    // Returns a new iterator for the Viz breakdowns. If buffer ready breakdowns
+    // are available, `skip_swap_start_to_swap_end_if_breakdown_available` can
+    // be used to skip `kSwapStartToSwapEnd` breakdown.
+    Iterator CreateIterator(
+        bool skip_swap_start_to_swap_end_if_breakdown_available) const;
+
+    base::TimeTicks swap_start() const { return swap_start_; }
+
+   private:
+    base::Optional<std::pair<base::TimeTicks, base::TimeTicks>>
+        list_[static_cast<int>(VizBreakdown::kBreakdownCount)];
+
+    bool buffer_ready_available_ = false;
+    base::TimeTicks swap_start_;
+  };
+
   using ActiveTrackers =
       std::bitset<static_cast<size_t>(FrameSequenceTrackerType::kMaxType)>;
 
@@ -272,7 +319,6 @@
   }
 
   void PopulateBlinkBreakdownList();
-  void PopulateVizBreakdownList();
 
   // This method is only used for DCheck
   base::TimeDelta SumOfStageHistory() const;
@@ -293,8 +339,7 @@
 
   viz::FrameTimingDetails viz_breakdown_;
   base::TimeTicks viz_start_time_;
-  base::Optional<std::pair<base::TimeTicks, base::TimeTicks>>
-      viz_breakdown_list_[static_cast<int>(VizBreakdown::kBreakdownCount)];
+  std::unique_ptr<ProcessedVizBreakdown> processed_viz_breakdown_;
 
   // Stage data is recorded here. On destruction these stages will be reported
   // to UMA if the termination status is |kPresentedFrame|. Reported data will
diff --git a/cc/metrics/latency_ukm_reporter.cc b/cc/metrics/latency_ukm_reporter.cc
index 02c884e..b44a622 100644
--- a/cc/metrics/latency_ukm_reporter.cc
+++ b/cc/metrics/latency_ukm_reporter.cc
@@ -89,22 +89,24 @@
     CompositorFrameReporter::FrameReportType report_type,
     const std::vector<CompositorFrameReporter::StageData>& stage_history,
     const CompositorFrameReporter::ActiveTrackers& active_trackers,
-    const viz::FrameTimingDetails& viz_breakdown) {
+    const CompositorFrameReporter::ProcessedVizBreakdown&
+        processed_viz_breakdown) {
   if (ukm_manager_ &&
       compositor_latency_sampling_controller_->ShouldRecordNextEvent()) {
-    ukm_manager_->RecordCompositorLatencyUKM(report_type, stage_history,
-                                             active_trackers, viz_breakdown);
+    ukm_manager_->RecordCompositorLatencyUKM(
+        report_type, stage_history, active_trackers, processed_viz_breakdown);
   }
 }
 
 void LatencyUkmReporter::ReportEventLatencyUkm(
     const EventMetrics::List& events_metrics,
     const std::vector<CompositorFrameReporter::StageData>& stage_history,
-    const viz::FrameTimingDetails& viz_breakdown) {
+    const CompositorFrameReporter::ProcessedVizBreakdown&
+        processed_viz_breakdown) {
   if (ukm_manager_ &&
       event_latency_sampling_controller_->ShouldRecordNextEvent()) {
     ukm_manager_->RecordEventLatencyUKM(events_metrics, stage_history,
-                                        viz_breakdown);
+                                        processed_viz_breakdown);
   }
 }
 
diff --git a/cc/metrics/latency_ukm_reporter.h b/cc/metrics/latency_ukm_reporter.h
index 3d2f96f..463c58f 100644
--- a/cc/metrics/latency_ukm_reporter.h
+++ b/cc/metrics/latency_ukm_reporter.h
@@ -11,7 +11,6 @@
 #include "cc/cc_export.h"
 #include "cc/metrics/compositor_frame_reporter.h"
 #include "cc/metrics/event_metrics.h"
-#include "components/viz/common/frame_timing_details.h"
 
 namespace cc {
 class UkmManager;
@@ -30,12 +29,14 @@
       CompositorFrameReporter::FrameReportType report_type,
       const std::vector<CompositorFrameReporter::StageData>& stage_history,
       const CompositorFrameReporter::ActiveTrackers& active_trackers,
-      const viz::FrameTimingDetails& viz_breakdown);
+      const CompositorFrameReporter::ProcessedVizBreakdown&
+          processed_viz_breakdown);
 
   void ReportEventLatencyUkm(
       const EventMetrics::List& events_metrics,
       const std::vector<CompositorFrameReporter::StageData>& stage_history,
-      const viz::FrameTimingDetails& viz_breakdown);
+      const CompositorFrameReporter::ProcessedVizBreakdown&
+          processed_viz_breakdown);
 
   void set_ukm_manager(UkmManager* manager) { ukm_manager_ = manager; }
 
diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc
index 974706d..f63f5e3 100644
--- a/cc/resources/ui_resource_bitmap.cc
+++ b/cc/resources/ui_resource_bitmap.cc
@@ -11,6 +11,7 @@
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkMallocPixelRef.h"
 #include "third_party/skia/include/core/SkPixelRef.h"
@@ -55,7 +56,7 @@
   SkBitmap bitmap;
   bitmap.setInfo(info_, pixel_ref_.get()->rowBytes());
   bitmap.setPixelRef(pixel_ref_, 0, 0);
-  canvas->drawBitmap(bitmap, 0, 0, paint);
+  canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), paint);
   canvas->flush();
 }
 
diff --git a/cc/tiles/gpu_image_decode_cache_perftest.cc b/cc/tiles/gpu_image_decode_cache_perftest.cc
index 20725f8..a2c6d68 100644
--- a/cc/tiles/gpu_image_decode_cache_perftest.cc
+++ b/cc/tiles/gpu_image_decode_cache_perftest.cc
@@ -154,11 +154,11 @@
     DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
 
     if (GetParam() == TestMode::kGpu) {
-      SkPaint paint;
-      paint.setFilterQuality(kMedium_SkFilterQuality);
-      surface->getCanvas()->drawImageRect(decoded_image.image().get(),
-                                          SkRect::MakeWH(1024, 2048),
-                                          SkRect::MakeWH(614, 1229), &paint);
+      SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kLinear);
+      surface->getCanvas()->drawImageRect(
+          decoded_image.image().get(), SkRect::MakeWH(1024, 2048),
+          SkRect::MakeWH(614, 1229), sampling, nullptr,
+          SkCanvas::kStrict_SrcRectConstraint);
       surface->flushAndSubmit();
     }
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 2a170895..dad934a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -4409,7 +4409,7 @@
     // fully filled by drawBitmap(), so we ensure they start empty. (See
     // crbug.com/642011 for an example.)
     scaled_canvas->clear(SK_ColorTRANSPARENT);
-    scaled_canvas->drawBitmap(source_bitmap, 0, 0);
+    scaled_canvas->drawImage(source_bitmap.asImage(), 0, 0);
 
     if (layer_tree_frame_sink_->context_provider()) {
       SkPixmap pixmap;
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc
index 2c40a51..6b49e4a 100644
--- a/cc/trees/ukm_manager.cc
+++ b/cc/trees/ukm_manager.cc
@@ -177,7 +177,8 @@
     CompositorFrameReporter::FrameReportType report_type,
     const std::vector<CompositorFrameReporter::StageData>& stage_history,
     const CompositorFrameReporter::ActiveTrackers& active_trackers,
-    const viz::FrameTimingDetails& viz_breakdown) const {
+    const CompositorFrameReporter::ProcessedVizBreakdown&
+        processed_viz_breakdown) const {
   using StageType = CompositorFrameReporter::StageType;
 
   ukm::builders::Graphics_Smoothness_Latency builder(source_id_);
@@ -186,7 +187,7 @@
     builder.SetMissedFrame(true);
   }
 
-  // Record each stage
+  // Record each stage.
   for (const CompositorFrameReporter::StageData& stage : stage_history) {
     switch (stage.stage_type) {
 #define CASE_FOR_STAGE(name)                                                 \
@@ -199,52 +200,41 @@
       CASE_FOR_STAGE(EndCommitToActivation);
       CASE_FOR_STAGE(Activation);
       CASE_FOR_STAGE(EndActivateToSubmitCompositorFrame);
+      CASE_FOR_STAGE(SubmitCompositorFrameToPresentationCompositorFrame);
       CASE_FOR_STAGE(TotalLatency);
 #undef CASE_FOR_STAGE
-      // Break out kSubmitCompositorFrameToPresentationCompositorFrame to report
-      // the viz breakdown.
-      case StageType::kSubmitCompositorFrameToPresentationCompositorFrame:
-        builder.SetSubmitCompositorFrameToPresentationCompositorFrame(
-            (stage.end_time - stage.start_time).InMicroseconds());
-        if (viz_breakdown.received_compositor_frame_timestamp.is_null())
-          break;
-        builder
-            .SetSubmitCompositorFrameToPresentationCompositorFrame_SubmitToReceiveCompositorFrame(
-                (viz_breakdown.received_compositor_frame_timestamp -
-                 stage.start_time)
-                    .InMicroseconds());
-        if (viz_breakdown.draw_start_timestamp.is_null())
-          break;
-        builder
-            .SetSubmitCompositorFrameToPresentationCompositorFrame_ReceivedCompositorFrameToStartDraw(
-                (viz_breakdown.draw_start_timestamp -
-                 viz_breakdown.received_compositor_frame_timestamp)
-                    .InMicroseconds());
-        if (viz_breakdown.swap_timings.is_null())
-          break;
-        builder
-            .SetSubmitCompositorFrameToPresentationCompositorFrame_StartDrawToSwapStart(
-                (viz_breakdown.swap_timings.swap_start -
-                 viz_breakdown.draw_start_timestamp)
-                    .InMicroseconds());
-        builder
-            .SetSubmitCompositorFrameToPresentationCompositorFrame_SwapStartToSwapEnd(
-                (viz_breakdown.swap_timings.swap_end -
-                 viz_breakdown.swap_timings.swap_start)
-                    .InMicroseconds());
-        builder
-            .SetSubmitCompositorFrameToPresentationCompositorFrame_SwapEndToPresentationCompositorFrame(
-                (viz_breakdown.presentation_feedback.timestamp -
-                 viz_breakdown.swap_timings.swap_end)
-                    .InMicroseconds());
-        break;
       default:
         NOTREACHED();
         break;
     }
   }
 
-  // Record the active trackers
+  // Record Viz breakdowns.
+  for (auto it = processed_viz_breakdown.CreateIterator(false); it.IsValid();
+       it.Advance()) {
+    switch (it.GetBreakdown()) {
+#define CASE_FOR_VIZ_BREAKDOWN(name)                                      \
+  case CompositorFrameReporter::VizBreakdown::k##name:                    \
+    builder.SetSubmitCompositorFrameToPresentationCompositorFrame_##name( \
+        it.GetDuration().InMicroseconds());                               \
+    break;
+      CASE_FOR_VIZ_BREAKDOWN(SubmitToReceiveCompositorFrame);
+      CASE_FOR_VIZ_BREAKDOWN(ReceivedCompositorFrameToStartDraw);
+      CASE_FOR_VIZ_BREAKDOWN(StartDrawToSwapStart);
+      CASE_FOR_VIZ_BREAKDOWN(SwapStartToSwapEnd);
+      CASE_FOR_VIZ_BREAKDOWN(SwapEndToPresentationCompositorFrame);
+      CASE_FOR_VIZ_BREAKDOWN(SwapStartToBufferAvailable);
+      CASE_FOR_VIZ_BREAKDOWN(BufferAvailableToBufferReady);
+      CASE_FOR_VIZ_BREAKDOWN(BufferReadyToLatch);
+      CASE_FOR_VIZ_BREAKDOWN(LatchToSwapEnd);
+#undef CASE_FOR_VIZ_BREAKDOWN
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  // Record the active trackers.
   for (size_t type = 0; type < active_trackers.size(); ++type) {
     if (!active_trackers.test(type))
       continue;
@@ -278,7 +268,8 @@
 void UkmManager::RecordEventLatencyUKM(
     const EventMetrics::List& events_metrics,
     const std::vector<CompositorFrameReporter::StageData>& stage_history,
-    const viz::FrameTimingDetails& viz_breakdown) const {
+    const CompositorFrameReporter::ProcessedVizBreakdown&
+        processed_viz_breakdown) const {
   using StageType = CompositorFrameReporter::StageType;
 
   for (const auto& event_metrics : events_metrics) {
@@ -294,9 +285,9 @@
       builder.SetScrollInputType(
           static_cast<int64_t>(*event_metrics->scroll_type()));
 
-      if (!viz_breakdown.swap_timings.is_null()) {
+      if (!processed_viz_breakdown.swap_start().is_null()) {
         builder.SetTotalLatencyToSwapBegin(
-            (viz_breakdown.swap_timings.swap_start - generated_timestamp)
+            (processed_viz_breakdown.swap_start() - generated_timestamp)
                 .InMicroseconds());
       }
     }
@@ -463,6 +454,31 @@
       }
     }
 
+    // Record Viz breakdowns.
+    for (auto it = processed_viz_breakdown.CreateIterator(false); it.IsValid();
+         it.Advance()) {
+      switch (it.GetBreakdown()) {
+#define CASE_FOR_VIZ_BREAKDOWN(name)                                      \
+  case CompositorFrameReporter::VizBreakdown::k##name:                    \
+    builder.SetSubmitCompositorFrameToPresentationCompositorFrame_##name( \
+        it.GetDuration().InMicroseconds());                               \
+    break;
+        CASE_FOR_VIZ_BREAKDOWN(SubmitToReceiveCompositorFrame);
+        CASE_FOR_VIZ_BREAKDOWN(ReceivedCompositorFrameToStartDraw);
+        CASE_FOR_VIZ_BREAKDOWN(StartDrawToSwapStart);
+        CASE_FOR_VIZ_BREAKDOWN(SwapStartToSwapEnd);
+        CASE_FOR_VIZ_BREAKDOWN(SwapEndToPresentationCompositorFrame);
+        CASE_FOR_VIZ_BREAKDOWN(SwapStartToBufferAvailable);
+        CASE_FOR_VIZ_BREAKDOWN(BufferAvailableToBufferReady);
+        CASE_FOR_VIZ_BREAKDOWN(BufferReadyToLatch);
+        CASE_FOR_VIZ_BREAKDOWN(LatchToSwapEnd);
+#undef CASE_FOR_VIZ_BREAKDOWN
+        default:
+          NOTREACHED();
+          break;
+      }
+    }
+
     builder.Record(recorder_.get());
   }
 }
diff --git a/cc/trees/ukm_manager.h b/cc/trees/ukm_manager.h
index b51147f..c326fff4 100644
--- a/cc/trees/ukm_manager.h
+++ b/cc/trees/ukm_manager.h
@@ -12,7 +12,6 @@
 #include "cc/metrics/compositor_frame_reporter.h"
 #include "cc/metrics/event_metrics.h"
 #include "cc/metrics/frame_sequence_metrics.h"
-#include "components/viz/common/frame_timing_details.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/gurl.h"
 
@@ -57,12 +56,14 @@
       CompositorFrameReporter::FrameReportType report_type,
       const std::vector<CompositorFrameReporter::StageData>& stage_history,
       const CompositorFrameReporter::ActiveTrackers& active_trackers,
-      const viz::FrameTimingDetails& viz_breakdown) const;
+      const CompositorFrameReporter::ProcessedVizBreakdown&
+          processed_viz_breakdown) const;
 
   void RecordEventLatencyUKM(
       const EventMetrics::List& events_metrics,
       const std::vector<CompositorFrameReporter::StageData>& stage_history,
-      const viz::FrameTimingDetails& viz_breakdown) const;
+      const CompositorFrameReporter::ProcessedVizBreakdown&
+          processed_viz_breakdown) const;
 
   ukm::UkmRecorder* recorder_for_testing() { return recorder_.get(); }
 
diff --git a/cc/trees/ukm_manager_unittest.cc b/cc/trees/ukm_manager_unittest.cc
index da55cfda..862cee2 100644
--- a/cc/trees/ukm_manager_unittest.cc
+++ b/cc/trees/ukm_manager_unittest.cc
@@ -72,6 +72,16 @@
     "SubmitCompositorFrameToPresentationCompositorFrame.StartDrawToSwapStart";
 const char kVizBreakdownSwapStartToSwapEnd[] =
     "SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd";
+const char kVizBreakdownSwapStartToBufferAvailable[] =
+    "SubmitCompositorFrameToPresentationCompositorFrame."
+    "SwapStartToBufferAvailable";
+const char kVizBreakdownBufferAvailableToBufferReady[] =
+    "SubmitCompositorFrameToPresentationCompositorFrame."
+    "BufferAvailableToBufferReady";
+const char kVizBreakdownBufferReadyToLatch[] =
+    "SubmitCompositorFrameToPresentationCompositorFrame.BufferReadyToLatch";
+const char kVizBreakdownLatchToSwapEnd[] =
+    "SubmitCompositorFrameToPresentationCompositorFrame.LatchToSwapEnd";
 const char kVizBreakdownSwapEndToPresentationCompositorFrame[] =
     "SubmitCompositorFrameToPresentationCompositorFrame."
     "SwapEndToPresentationCompositorFrame";
@@ -271,7 +281,10 @@
   viz_breakdown.received_compositor_frame_timestamp = AdvanceNowByMs(1);
   viz_breakdown.draw_start_timestamp = AdvanceNowByMs(2);
   viz_breakdown.swap_timings.swap_start = AdvanceNowByMs(3);
-  viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(4);
+  viz_breakdown.presentation_feedback.available_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.presentation_feedback.ready_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.presentation_feedback.latch_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(1);
   viz_breakdown.presentation_feedback.timestamp = AdvanceNowByMs(5);
 
   std::vector<CompositorFrameReporter::StageData> stage_history = {
@@ -328,8 +341,10 @@
   active_trackers.set(
       static_cast<size_t>(FrameSequenceTrackerType::kCompositorAnimation));
 
-  manager_->RecordCompositorLatencyUKM(report_type(), stage_history,
-                                       active_trackers, viz_breakdown);
+  CompositorFrameReporter::ProcessedVizBreakdown processed_viz_breakdown(
+      submit_time, viz_breakdown);
+  manager_->RecordCompositorLatencyUKM(
+      report_type(), stage_history, active_trackers, processed_viz_breakdown);
 
   const auto& entries =
       test_ukm_recorder_->GetEntriesByName(kCompositorLatency);
@@ -386,6 +401,26 @@
                                          viz_breakdown.swap_timings.swap_start)
                                             .InMicroseconds());
   test_ukm_recorder_->ExpectEntryMetric(
+      entry, kVizBreakdownSwapStartToBufferAvailable,
+      (viz_breakdown.presentation_feedback.available_timestamp -
+       viz_breakdown.swap_timings.swap_start)
+          .InMicroseconds());
+  test_ukm_recorder_->ExpectEntryMetric(
+      entry, kVizBreakdownBufferAvailableToBufferReady,
+      (viz_breakdown.presentation_feedback.ready_timestamp -
+       viz_breakdown.presentation_feedback.available_timestamp)
+          .InMicroseconds());
+  test_ukm_recorder_->ExpectEntryMetric(
+      entry, kVizBreakdownBufferReadyToLatch,
+      (viz_breakdown.presentation_feedback.latch_timestamp -
+       viz_breakdown.presentation_feedback.ready_timestamp)
+          .InMicroseconds());
+  test_ukm_recorder_->ExpectEntryMetric(
+      entry, kVizBreakdownLatchToSwapEnd,
+      (viz_breakdown.swap_timings.swap_end -
+       viz_breakdown.presentation_feedback.latch_timestamp)
+          .InMicroseconds());
+  test_ukm_recorder_->ExpectEntryMetric(
       entry, kVizBreakdownSwapEndToPresentationCompositorFrame,
       (viz_breakdown.presentation_feedback.timestamp -
        viz_breakdown.swap_timings.swap_end)
@@ -431,7 +466,10 @@
   viz_breakdown.received_compositor_frame_timestamp = AdvanceNowByMs(1);
   viz_breakdown.draw_start_timestamp = AdvanceNowByMs(2);
   viz_breakdown.swap_timings.swap_start = AdvanceNowByMs(3);
-  viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(4);
+  viz_breakdown.presentation_feedback.available_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.presentation_feedback.ready_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.presentation_feedback.latch_timestamp = AdvanceNowByMs(1);
+  viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(1);
   viz_breakdown.presentation_feedback.timestamp = AdvanceNowByMs(5);
 
   const base::TimeTicks swap_start_time = viz_breakdown.swap_timings.swap_start;
@@ -464,7 +502,10 @@
       },
   };
 
-  manager_->RecordEventLatencyUKM(events_metrics, stage_history, viz_breakdown);
+  CompositorFrameReporter::ProcessedVizBreakdown processed_viz_breakdown(
+      submit_time, viz_breakdown);
+  manager_->RecordEventLatencyUKM(events_metrics, stage_history,
+                                  processed_viz_breakdown);
 
   const auto& entries = test_ukm_recorder_->GetEntriesByName(kEventLatency);
   EXPECT_EQ(3u, entries.size());
@@ -526,6 +567,50 @@
         entry, kSubmitCompositorFrameToPresentationCompositorFrame,
         (present_time - submit_time).InMicroseconds());
     test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownSubmitToReceiveCompositorFrame,
+        (viz_breakdown.received_compositor_frame_timestamp - submit_time)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownReceivedCompositorFrameToStartDraw,
+        (viz_breakdown.draw_start_timestamp -
+         viz_breakdown.received_compositor_frame_timestamp)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownStartDrawToSwapStart,
+        (viz_breakdown.swap_timings.swap_start -
+         viz_breakdown.draw_start_timestamp)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownSwapStartToSwapEnd,
+        (viz_breakdown.swap_timings.swap_end -
+         viz_breakdown.swap_timings.swap_start)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownSwapStartToBufferAvailable,
+        (viz_breakdown.presentation_feedback.available_timestamp -
+         viz_breakdown.swap_timings.swap_start)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownBufferAvailableToBufferReady,
+        (viz_breakdown.presentation_feedback.ready_timestamp -
+         viz_breakdown.presentation_feedback.available_timestamp)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownBufferReadyToLatch,
+        (viz_breakdown.presentation_feedback.latch_timestamp -
+         viz_breakdown.presentation_feedback.ready_timestamp)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownLatchToSwapEnd,
+        (viz_breakdown.swap_timings.swap_end -
+         viz_breakdown.presentation_feedback.latch_timestamp)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
+        entry, kVizBreakdownSwapEndToPresentationCompositorFrame,
+        (viz_breakdown.presentation_feedback.timestamp -
+         viz_breakdown.swap_timings.swap_end)
+            .InMicroseconds());
+    test_ukm_recorder_->ExpectEntryMetric(
         entry, kTotalLatencyToSwapBegin,
         (swap_start_time - event_dispatch_times[i].generated).InMicroseconds());
     test_ukm_recorder_->ExpectEntryMetric(
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 713b3ea..9c37a91 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -323,6 +323,7 @@
     "//chrome/browser/offline_pages/android:java",
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/optimization_guide/android:java",
+    "//chrome/browser/page_annotations/android:java",
     "//chrome/browser/paint_preview/android:java",
     "//chrome/browser/password_check:public_java",
     "//chrome/browser/password_manager/android:java",
@@ -646,6 +647,7 @@
     ":chrome_java",
     "//chrome/android/features/keyboard_accessory:internal_java",
     "//chrome/browser/download/internal/android:java",
+    "//chrome/browser/page_annotations/android:java",
     "//chrome/browser/password_check:internal_java",
     "//chrome/browser/tabmodel/internal:java",
     "//chrome/browser/touch_to_fill/android/internal:java",
@@ -831,6 +833,7 @@
     "//chrome/browser/incognito/interstitial/android:junit",
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/optimization_guide/android:java",
+    "//chrome/browser/page_annotations/test/android:junit",
     "//chrome/browser/payments/android:junit",
     "//chrome/browser/performance_hints/android:java",
     "//chrome/browser/policy/android:java",
@@ -1085,6 +1088,8 @@
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/optimization_guide/android:java",
     "//chrome/browser/optimization_guide/android:javatests",
+    "//chrome/browser/page_annotations/android:java",
+    "//chrome/browser/page_annotations/test/android:javatests",
     "//chrome/browser/paint_preview/android:java",
     "//chrome/browser/paint_preview/android:javatests",
     "//chrome/browser/password_check:public_java",
diff --git a/chrome/android/DEPS b/chrome/android/DEPS
index 0046b982..13c1347 100644
--- a/chrome/android/DEPS
+++ b/chrome/android/DEPS
@@ -15,6 +15,7 @@
   "+chrome/browser/ui/android/layouts",
   "+chrome/browser/notifications",
   "+chrome/browser/password_manager/android",
+  "+chrome/browser/page_annotations/android",
   "+chrome/browser/policy/android",
   "+chrome/browser/preferences/android/java",
   "+chrome/browser/safe_browsing/android",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 692cb623..23acb3db 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -637,12 +637,6 @@
             }
         }
 
-        // Pressing back button on the Start surface homepage is handled by
-        // ChromeTabbedActivity#handleBackPressed().
-        if (mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE && !mShowStackTabSwitcher) {
-            return false;
-        }
-
         if (mPropertyModel != null && mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)
                 && mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER_TWO_PANES) {
             setExploreSurfaceVisibility(false);
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
index 5277f141..52a464a 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -1709,6 +1709,49 @@
     @Test
     @MediumTest
     @Feature({"StartSurface"})
+    @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID)
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/single"})
+    public void testShow_SingleAsHomepage_BackButtonOnCarouselTabSwitcher() {
+        // clang-format on
+        if (!mImmediateReturn) {
+            onView(withId(org.chromium.chrome.tab_ui.R.id.home_button)).perform(click());
+        }
+
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        CriteriaHelper.pollUiThread(
+                () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible());
+        waitForTabModel();
+        TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
+
+        OverviewModeBehaviorWatcher hideWatcher =
+                TabUiTestHelper.createOverviewHideWatcher(mActivityTestRule.getActivity());
+        onView(withId(org.chromium.chrome.start_surface.R.id.search_box_text))
+                .perform(replaceText("about:blank"));
+        onView(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        hideWatcher.waitForBehavior();
+        TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
+
+        TabUiTestHelper.mergeAllNormalTabsToAGroup(cta);
+        onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.home_button));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.home_button)).perform(click());
+        CriteriaHelper.pollUiThread(() -> cta.getLayoutManager().overviewVisible());
+
+        onView(allOf(withParent(withId(
+                             org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)),
+                       withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)))
+                .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
+        onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view), isDisplayed()));
+
+        pressBack();
+        waitForView(withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view), VIEW_GONE);
+        onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"StartSurface"})
     @DisableIf.Build(sdk_is_less_than = P, message = "https://crbug.com/1170553")
     @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1170553")
     @CommandLineFlags.Add({BASE_PARAMS + "/single/omnibox_focused_on_new_tab/true"})
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index fec7847..514b3d1f 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -717,6 +717,14 @@
     @Override
     public boolean onBackPressed() {
         if (!mContainerViewModel.get(IS_VISIBLE)) return false;
+
+        // The carousel tab switcher is only shown on the Start surface. When the Start surface is
+        // showing, we only check if the tab group dialog is showing, and delegates to
+        // mTabGridDialogController to close the dialog. See https://crbug.com/1171799.
+        if (mMode == TabListCoordinator.TabListMode.CAROUSEL) {
+            return mTabGridDialogController != null && mTabGridDialogController.handleBackPressed();
+        }
+
         if (mTabSelectionEditorController != null
                 && mTabSelectionEditorController.handleBackPressed()) {
             return true;
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS
index d922a70..d63ec10 100644
--- a/chrome/android/java/DEPS
+++ b/chrome/android/java/DEPS
@@ -22,6 +22,7 @@
   "+chrome/browser/performance_hints/android/java",
   "+chrome/browser/settings/android/java",
   "+chrome/browser/tabmodel/android/java",
+  "+chrome/browser/page_annotations/android/java",
   "+chrome/browser/video_tutorials/android",
   "+components/autofill/android/java/src/org/chromium/components/autofill",
   "+components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index 650cbf1..bd9a33c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.CachedFieldTrialParameter;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.page_annotations.PageAnnotationsServiceConfig;
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.chrome.browser.tasks.ConditionalTabStripUtils;
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
@@ -91,6 +92,7 @@
                 ConditionalTabStripUtils.CONDITIONAL_TAB_STRIP_INFOBAR_LIMIT,
                 ConditionalTabStripUtils.CONDITIONAL_TAB_STRIP_INFOBAR_PERIOD,
                 ConditionalTabStripUtils.CONDITIONAL_TAB_STRIP_SESSION_TIME_MS,
+                PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL,
                 ReturnToChromeExperimentsUtil.TAB_SWITCHER_ON_RETURN_MS,
                 StartSurfaceConfiguration.OMNIBOX_FOCUSED_ON_NEW_TAB,
                 StartSurfaceConfiguration.START_SURFACE_EXCLUDE_MV_TILES,
@@ -111,7 +113,6 @@
                 TabUiFeatureUtilities.ENABLE_SEARCH_CHIP,
                 ShoppingPersistedTabData.TIME_TO_LIVE_MS,
                 ShoppingPersistedTabData.DISPLAY_TIME_MS,
-                ShoppingPersistedTabData.ENDPOINT,
                 TabUiFeatureUtilities.ENABLE_PRICE_TRACKING,
                 TabUiFeatureUtilities.ENABLE_SEARCH_CHIP_ADAPTIVE,
                 TabUiFeatureUtilities.ZOOMING_MIN_MEMORY,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java
index fd7b865..72648dc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java
@@ -7,6 +7,7 @@
 import android.util.JsonReader;
 import android.util.JsonToken;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
@@ -26,6 +27,27 @@
     private static final String TAG = "WebContextFetcher";
 
     /**
+     * Wrapper object to encapsulate response.
+     */
+    public static class WebContextFetchResponse {
+        /**
+         * The context returned from the page converted from a JSON object
+         */
+        public Map<String, String> context = new HashMap<>();
+
+        /**
+         * A descriptive error message set if web context fetching failed.
+         * Currently if this is set 'context' will necessarily be empty.
+         */
+        @Nullable
+        public String error;
+    }
+
+    // TODO(benwgold): Delete this temporary stub kept to avoid temporarily breaking compilation.
+    public static void fetchContextWithJavascript(String script,
+            Callback<Map<String, String>> callback, RenderFrameHost renderFrameHost) {}
+
+    /**
      * A utility method which allows Java code to extract content from the page using
      * a Javascript string. The script should be a self executing function returning
      * a javascript dictionary object. The return value must be flat (so no nested fields)
@@ -37,16 +59,16 @@
      * @param renderFrameHost The frame to execute the JS on.
      *
      */
-    public static void fetchContextWithJavascript(String script,
-            Callback<Map<String, String>> callback, RenderFrameHost renderFrameHost) {
+    public static void fetchContextWithJavascriptUpdated(String script,
+            Callback<WebContextFetchResponse> callback, RenderFrameHost renderFrameHost) {
         WebContextFetcherJni.get().fetchContextWithJavascript(script, (jsonString) -> {
-            callback.onResult(convertJsonToMap(jsonString));
+            callback.onResult(convertJsonToResponse(jsonString));
         }, renderFrameHost);
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    static Map<String, String> convertJsonToMap(String jsonString) {
-        Map<String, String> fetchedContext = new HashMap<>();
+    static WebContextFetchResponse convertJsonToResponse(String jsonString) {
+        WebContextFetchResponse fetchResponse = new WebContextFetchResponse();
         try {
             JsonReader jsonReader = new JsonReader(new StringReader(jsonString));
             // The JSON should be an object and not an array.
@@ -65,14 +87,14 @@
                     throw new AssertionError("Error reading JSON string value.");
                 }
                 String value = jsonReader.nextString();
-                fetchedContext.put(key, value);
+                fetchResponse.context.put(key, value);
             }
             jsonReader.endObject();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to read web context json");
-            throw new AssertionError("Error parsing JSON string value.");
+        } catch (IOException | AssertionError e) {
+            Log.e(TAG, "Web context json was malformed: %s", e.getMessage());
+            fetchResponse.error = e.getMessage();
         }
-        return fetchedContext;
+        return fetchResponse;
     }
 
     @NativeMethods
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/WebContextFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/WebContextFetcherTest.java
index fe8aff7..bf7099e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/WebContextFetcherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/javascript/WebContextFetcherTest.java
@@ -10,10 +10,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import org.chromium.chrome.browser.javascript.WebContextFetcher.WebContextFetchResponse;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
-import java.util.Map;
-
 /**
  * Unit tests for web context fetching java code.
  */
@@ -24,40 +23,61 @@
      */
     @Test
     @SmallTest
-    public void testConvertJsonToMap_Successful() throws Exception {
-        Map emptyMap = WebContextFetcher.convertJsonToMap("{}");
-        Assert.assertTrue("Empty json dictionary does not return empty map.", emptyMap.isEmpty());
+    public void testConvertJsonToResponse_Successful() {
+        WebContextFetchResponse emptyResponse = WebContextFetcher.convertJsonToResponse("{}");
+        Assert.assertTrue("Empty json dictionary does not return empty map.",
+                emptyResponse.context.isEmpty());
 
-        Map mapWithSingleKey = WebContextFetcher.convertJsonToMap("{\"testing\": \"onetwothree\"}");
+        WebContextFetchResponse response =
+                WebContextFetcher.convertJsonToResponse("{\"testing\": \"onetwothree\"}");
         Assert.assertEquals("Map with single key did not have correct key/val pair.", "onetwothree",
-                mapWithSingleKey.get("testing"));
+                response.context.get("testing"));
         Assert.assertEquals(
-                "Map with single key had more than one key.", 1, mapWithSingleKey.size());
+                "Map with single key had more than one key.", 1, response.context.size());
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     @SmallTest
-    public void testConvertJsonToMap_AssertionErrorMalformed() {
-        Map unused = WebContextFetcher.convertJsonToMap("14324asdfasc132434");
+    public void testConvertJsonToResponse_AssertionErrorMalformed() {
+        WebContextFetchResponse response =
+                WebContextFetcher.convertJsonToResponse("14324asdfasc132434");
+
+        Assert.assertEquals("Response with error key did not have correct value pair.",
+                "Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 19",
+                response.error);
+        Assert.assertTrue("Response with error had filled context.", response.context.isEmpty());
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     @SmallTest
-    public void testConvertJsonToMap_AssertionErrorNestedObject() {
-        Map unused = WebContextFetcher.convertJsonToMap(
+    public void testConvertJsonToResponse_AssertionErrorNestedObject() {
+        WebContextFetchResponse response = WebContextFetcher.convertJsonToResponse(
                 "{\"nestedObject\": {\"nestedKey\": \"nestedVal\"}}");
+
+        Assert.assertEquals("Response with error did not have correct message.",
+                "Error reading JSON string value.", response.error);
+        Assert.assertTrue("Response with error had filled context.", response.context.isEmpty());
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     @SmallTest
-    public void testConvertJsonToMap_AssertionErrorNonStringVal() {
-        Map unused = WebContextFetcher.convertJsonToMap("{\"integer\": 123}");
+    public void testConvertJsonToResponse_AssertionErrorNonStringVal() {
+        WebContextFetchResponse response =
+                WebContextFetcher.convertJsonToResponse("{\"integer\": 123}");
+
+        Assert.assertEquals("Response with error  did not have correct message.",
+                "Error reading JSON string value.", response.error);
+        Assert.assertTrue("Response with error had filled context.", response.context.isEmpty());
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     @SmallTest
-    public void testConvertJsonToMap_AssertionErrorArray() {
-        Map unused = WebContextFetcher.convertJsonToMap(
+    public void testConvertJsonToResponse_AssertionErrorArray() {
+        WebContextFetchResponse response = WebContextFetcher.convertJsonToResponse(
                 "{\"nestedArray\":[\"arrayVal1\", \"arrayVal2\"]}");
+
+        Assert.assertEquals("Response with error key did not have correct message.",
+                "Error reading JSON string value.", response.error);
+        Assert.assertTrue("Response with error had filled context.", response.context.isEmpty());
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
index 6a41f529..f624b46 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
@@ -131,6 +131,11 @@
         }
 
         @Override
+        public boolean isScheduled(Context context, int taskId) {
+            return (mTasks.get(taskId) != null);
+        }
+
+        @Override
         public void checkForOSUpgrade(Context context) {}
 
         @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
index e0267ce..c39ef30 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
@@ -15,6 +15,8 @@
 
 import android.support.test.filters.SmallTest;
 
+import androidx.annotation.IntDef;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -34,12 +36,15 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher;
 import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcherJni;
-import org.chromium.chrome.browser.endpoint_fetcher.EndpointResponse;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge;
 import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge.OptimizationGuideCallback;
 import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridgeJni;
+import org.chromium.chrome.browser.page_annotations.BuyableProductPageAnnotation;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation;
+import org.chromium.chrome.browser.page_annotations.PageAnnotationsService;
+import org.chromium.chrome.browser.page_annotations.PageAnnotationsServiceFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
@@ -50,10 +55,12 @@
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.url.GURL;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.LinkedList;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
-
 /**
  * Test relating to {@link ShoppingPersistedTabData}
  */
@@ -62,6 +69,16 @@
 @CommandLineFlags.
 Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-fieldtrials=Study/Group"})
 public class ShoppingPersistedTabDataTest {
+    @IntDef({MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL,
+            MockPageAnnotationsResponse.BUYABLE_PRODUCT_PRICE_UPDATED,
+            MockPageAnnotationsResponse.BUYABLE_PRODUCT_EMPTY})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface MockPageAnnotationsResponse {
+        int BUYABLE_PRODUCT_INITIAL = 0;
+        int BUYABLE_PRODUCT_PRICE_UPDATED = 1;
+        int BUYABLE_PRODUCT_EMPTY = 2;
+    }
+
     @Rule
     public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
 
@@ -80,8 +97,14 @@
     @Mock
     OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock;
 
-    // Tracks if the endpoint fetcher has been called once or not
-    private boolean mCalledOnce;
+    @Mock
+    Profile mProfileMock;
+
+    @Mock
+    PageAnnotationsServiceFactory mServiceFactoryMock;
+
+    @Mock
+    PageAnnotationsService mPageAnnotationsServiceMock;
 
     private static final long PRICE_MICROS = 123456789012345L;
     private static final long UPDATED_PRICE_MICROS = 287000000L;
@@ -93,26 +116,6 @@
     private static final String GREAT_BRITAIN_CURRENCY_CODE = "GBP";
     private static final String JAPAN_CURRENCY_CODE = "JPY";
 
-    private static final String EMPTY_PRICE = "";
-    private static final String ENDPOINT_RESPONSE_INITIAL =
-            "{\"annotations\":[{\"type\":\"DOCUMENT_INTENT\",\"documentIntent\":"
-            + "{\"intent\":\"UNKNOWN\"}},{\"type\":\"BUYABLE_PRODUCT\",\"buyableProduct\":"
-            + "{\"title\":\"foo title\",\"imageUrl\":\"https://images.com?q=1234\","
-            + "\"currentPrice\":{\"currencyCode\":\"USD\",\"amountMicros\":\"123456789012345\"},"
-            + "\"referenceType\":\"MAIN_PRODUCT\"}}]}";
-
-    private static final String ENDPOINT_RESPONSE_UPDATE =
-            "{\"annotations\":[{\"type\":\"DOCUMENT_INTENT\",\"documentIntent\":"
-            + "{\"intent\":\"UNKNOWN\"}},{\"type\":\"BUYABLE_PRODUCT\",\"buyableProduct\":"
-            + "{\"title\":\"foo title\",\"imageUrl\":\"https://images.com?q=1234\","
-            + "\"currentPrice\":{\"currencyCode\":\"USD\",\"amountMicros\":\"287000000\"},"
-            + "\"referenceType\":\"MAIN_PRODUCT\"}}]}";
-
-    private static final String EMPTY_RESPONSE = "{}";
-
-    private static final String DEFAULT_ENDPOINT = "https://memex-pa.googleapis.com/v1/annotations";
-    private static final String ENDPOINT_OVERRIDE = "my-endpoint.com";
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -122,6 +125,10 @@
         doReturn(1L).when(mOptimizationGuideBridgeJniMock).init();
         mockOptimizationGuideResponse(OptimizationGuideDecision.TRUE);
         PersistedTabDataConfiguration.setUseTestConfig(true);
+
+        Profile.setLastUsedProfileForTesting(mProfileMock);
+        doReturn(mPageAnnotationsServiceMock).when(mServiceFactoryMock).getForLastUsedProfile();
+        ShoppingPersistedTabData.sPageAnnotationsServiceFactory = mServiceFactoryMock;
     }
 
     @UiThreadTest
@@ -160,7 +167,7 @@
         final Semaphore semaphore = new Semaphore(0);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
-                verifyEndpointFetcherCalled(3);
+                verifyGetPageAnnotationsCalled(3);
                 Assert.assertEquals(
                         UPDATED_PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
                 Assert.assertEquals(
@@ -178,7 +185,7 @@
     @SmallTest
     @Test
     public void testShoppingBloomFilterNotShoppingWebsite() {
-        mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL);
         mockOptimizationGuideResponse(OptimizationGuideDecision.FALSE);
         Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO);
         Semaphore semaphore = new Semaphore(0);
@@ -187,7 +194,7 @@
                     tab, (shoppingPersistedTabData) -> { semaphore.release(); });
         });
         acquireSemaphore(semaphore);
-        verifyEndpointFetcherCalled(0);
+        verifyGetPageAnnotationsCalled(0);
     }
 
     @SmallTest
@@ -195,7 +202,7 @@
     public void testShoppingBloomFilterShoppingWebsite() {
         for (@OptimizationGuideDecision int decision :
                 new int[] {OptimizationGuideDecision.TRUE, OptimizationGuideDecision.UNKNOWN}) {
-            mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL);
+            mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL);
             mockOptimizationGuideResponse(decision);
             Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO);
             Semaphore semaphore = new Semaphore(0);
@@ -204,17 +211,17 @@
                         tab, (shoppingPersistedTabData) -> { semaphore.release(); });
             });
             acquireSemaphore(semaphore);
-            verifyEndpointFetcherCalled(1);
+            verifyGetPageAnnotationsCalled(1);
         }
     }
 
     private long shoppingPriceChange(Tab tab) {
         final Semaphore initialSemaphore = new Semaphore(0);
         final Semaphore updateSemaphore = new Semaphore(0);
-        mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
-                verifyEndpointFetcherCalled(1);
+                verifyGetPageAnnotationsCalled(1);
                 Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
                 Assert.assertEquals(
                         UNITED_STATES_CURRENCY_CODE, shoppingPersistedTabData.getCurrencyCode());
@@ -227,10 +234,10 @@
         });
         acquireSemaphore(initialSemaphore);
         long firstUpdateTime = getTimeLastUpdatedOnUiThread(tab);
-        mockEndpointResponse(ENDPOINT_RESPONSE_UPDATE);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_PRICE_UPDATED);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (updatedShoppingPersistedTabData) -> {
-                verifyEndpointFetcherCalled(2);
+                verifyGetPageAnnotationsCalled(2);
                 Assert.assertEquals(
                         UPDATED_PRICE_MICROS, updatedShoppingPersistedTabData.getPriceMicros());
                 Assert.assertEquals(
@@ -243,14 +250,16 @@
         acquireSemaphore(updateSemaphore);
         return getTimeLastUpdatedOnUiThread(tab);
     }
-
+    @UiThreadTest
     @SmallTest
     @Test
     public void testNoRefetch() {
         final Semaphore initialSemaphore = new Semaphore(0);
         final Semaphore updateSemaphore = new Semaphore(0);
         Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO);
-        mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL);
+        // Mock annotations response.
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL);
+
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
                 Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
@@ -264,8 +273,8 @@
             });
         });
         acquireSemaphore(initialSemaphore);
-        verifyEndpointFetcherCalled(1);
-        mockEndpointResponse(ENDPOINT_RESPONSE_UPDATE);
+        verifyGetPageAnnotationsCalled(1);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_PRICE_UPDATED);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
                 Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
@@ -280,7 +289,36 @@
         acquireSemaphore(updateSemaphore);
         // EndpointFetcher should not have been called a second time - because we haven't passed the
         // time to live
-        verifyEndpointFetcherCalled(1);
+        verifyGetPageAnnotationsCalled(1);
+    }
+
+    private void mockPageAnnotationsResponse(@MockPageAnnotationsResponse int expectedResponse) {
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                Callback callback = (Callback) invocation.getArguments()[1];
+                callback.onResult(new LinkedList<PageAnnotation>() {
+                    {
+                        switch (expectedResponse) {
+                            case MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL:
+                                add(new BuyableProductPageAnnotation(
+                                        PRICE_MICROS, UNITED_STATES_CURRENCY_CODE));
+                                break;
+                            case MockPageAnnotationsResponse.BUYABLE_PRODUCT_PRICE_UPDATED:
+                                add(new BuyableProductPageAnnotation(
+                                        UPDATED_PRICE_MICROS, UNITED_STATES_CURRENCY_CODE));
+                                break;
+                            case MockPageAnnotationsResponse.BUYABLE_PRODUCT_EMPTY:
+                            default:
+                                break;
+                        }
+                    }
+                });
+                return null;
+            }
+        })
+                .when(mPageAnnotationsServiceMock)
+                .getAnnotations(any(GURL.class), any(Callback.class));
     }
 
     @UiThreadTest
@@ -593,7 +631,7 @@
     public void testSPTDSavingEnabledUponSuccessfulResponse() {
         final Semaphore semaphore = new Semaphore(0);
         Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO);
-        mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_INITIAL);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
                 Assert.assertTrue(shoppingPersistedTabData.mIsTabSaveEnabledSupplier.get());
@@ -609,7 +647,7 @@
     public void testSPTDNullUponUnsuccessfulResponse() {
         final Semaphore semaphore = new Semaphore(0);
         Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO);
-        mockEndpointResponse(EMPTY_RESPONSE);
+        mockPageAnnotationsResponse(MockPageAnnotationsResponse.BUYABLE_PRODUCT_EMPTY);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
                 Assert.assertNull(shoppingPersistedTabData);
@@ -634,27 +672,17 @@
         Assert.assertEquals(42_000_000L, deserialized.getPriceMicros());
     }
 
-    // TODO(crbug.com/1168345) Create end to end test overriding the endpoint
-    @SmallTest
-    @Test
-    @CommandLineFlags.
-    Add({"force-fieldtrial-params=Study.Group:price_tracking_endpoint/my-endpoint.com"})
-    public void testEndpointOverride() {
-        Assert.assertEquals(ENDPOINT_OVERRIDE, ShoppingPersistedTabData.ENDPOINT.getValue());
-    }
-
-    @SmallTest
-    @Test
-    public void testEndpointNoOverride() {
-        Assert.assertEquals(DEFAULT_ENDPOINT, ShoppingPersistedTabData.ENDPOINT.getValue());
-    }
-
     private void verifyEndpointFetcherCalled(int numTimes) {
         verify(mEndpointFetcherJniMock, times(numTimes))
                 .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
                         anyString(), anyLong(), any(String[].class), any(Callback.class));
     }
 
+    private void verifyGetPageAnnotationsCalled(int numTimes) {
+        verify(mPageAnnotationsServiceMock, times(numTimes))
+                .getAnnotations(any(GURL.class), any(Callback.class));
+    }
+
     private static Tab createTabOnUiThread(int tabId, boolean isIncognito) {
         AtomicReference<Tab> res = new AtomicReference<>();
         TestThreadUtils.runOnUiThreadBlocking(
@@ -671,20 +699,6 @@
         return res.get();
     }
 
-    private void mockEndpointResponse(String response) {
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) {
-                Callback callback = (Callback) invocation.getArguments()[7];
-                callback.onResult(new EndpointResponse(response));
-                return null;
-            }
-        })
-                .when(mEndpointFetcherJniMock)
-                .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
-                        anyString(), anyLong(), any(String[].class), any(Callback.class));
-    }
-
     private static void acquireSemaphore(Semaphore semaphore) {
         try {
             semaphore.acquire();
@@ -708,4 +722,4 @@
                 .canApplyOptimization(
                         anyLong(), any(GURL.class), anyInt(), any(OptimizationGuideCallback.class));
     }
-}
+}
\ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
index 8211812..1b9ead5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
@@ -98,6 +98,11 @@
         }
 
         @Override
+        public boolean isScheduled(Context context, int taskId) {
+            return (mTaskInfos.get(taskId) != null);
+        }
+
+        @Override
         public void checkForOSUpgrade(Context context) {}
 
         @Override
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offline/measurements/OfflineMeasurementsBackgroundTaskUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offline/measurements/OfflineMeasurementsBackgroundTaskUnitTest.java
index 2a8ca71c..ebba969 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offline/measurements/OfflineMeasurementsBackgroundTaskUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offline/measurements/OfflineMeasurementsBackgroundTaskUnitTest.java
@@ -53,6 +53,11 @@
         }
 
         @Override
+        public boolean isScheduled(Context context, int taskId) {
+            return (mTaskInfos.get(taskId) != null);
+        }
+
+        @Override
         public void checkForOSUpgrade(Context context) {}
 
         @Override
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTaskUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTaskUnitTest.java
index 445ea57..985a4a68 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTaskUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTaskUnitTest.java
@@ -87,6 +87,11 @@
         }
 
         @Override
+        public boolean isScheduled(Context context, int taskId) {
+            return (mTaskInfos.get(taskId) != null);
+        }
+
+        @Override
         public void checkForOSUpgrade(Context context) {}
 
         @Override
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java
index 09af57cd..92baa9f 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java
@@ -74,6 +74,11 @@
         }
 
         @Override
+        public boolean isScheduled(Context context, int taskId) {
+            return (mTaskInfos.get(taskId) != null);
+        }
+
+        @Override
         public void checkForOSUpgrade(Context context) {}
 
         @Override
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index f71fa0c..eb638982 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -33,6 +33,7 @@
     "cast_for_education.icon",
     "chevron_right.icon",
     "chrome_labs.icon",
+    "chrome_labs_touch.icon",
     "click_to_call_illustration.icon",
     "click_to_call_illustration_dark.icon",
     "close_all.icon",
diff --git a/chrome/app/vector_icons/chrome_labs_touch.icon b/chrome/app/vector_icons/chrome_labs_touch.icon
new file mode 100644
index 0000000..f99a178
--- /dev/null
+++ b/chrome/app/vector_icons/chrome_labs_touch.icon
@@ -0,0 +1,20 @@
+// Copyright 2021 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, 24,
+MOVE_TO, 20.72f, 17.71f,
+LINE_TO, 15, 9.82f,
+V_LINE_TO, 5.08f,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 7,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 4.73f,
+LINE_TO, 3.14f, 17.9f,
+R_ARC_TO, 2, 2, 0, 0, 0, 1.62f, 3.17f,
+R_H_LINE_TO, 14.5f,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+R_CUBIC_TO, 0, -0.52f, -0.21f, -1, -0.54f, -1.36f,
+CLOSE
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0f0122a..f1389c10 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2086,6 +2086,7 @@
     "//components/leveldb_proto",
     "//components/lookalikes/core",
     "//components/lookalikes/core:features",
+    "//components/memories/browser",
     "//components/metrics:call_stack_profile_collector",
     "//components/metrics:call_stack_profile_params",
     "//components/metrics:component_metrics",
@@ -2748,8 +2749,6 @@
       "android/intent_helper.cc",
       "android/intent_helper.h",
       "android/javascript/web_context_fetcher.cc",
-      "android/javascript/web_context_fetcher_util.cc",
-      "android/javascript/web_context_fetcher_util.h",
       "android/locale/locale_manager.cc",
       "android/locale/locale_manager.h",
       "android/locale/locale_template_url_loader.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 005982e..84cbbe15 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3777,6 +3777,12 @@
      flag_descriptions::kVirtualKeyboardBorderedKeyName,
      flag_descriptions::kVirtualKeyboardBorderedKeyDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kVirtualKeyboardBorderedKey)},
+    {"enable-experimental-accessibility-dictation-extension",
+     flag_descriptions::kExperimentalAccessibilityDictationExtensionName,
+     flag_descriptions::kExperimentalAccessibilityDictationExtensionDescription,
+     kOsAll,
+     SINGLE_VALUE_TYPE(
+         ::switches::kEnableExperimentalAccessibilityDictationExtension)},
     {"enable-experimental-accessibility-switch-access-text",
      flag_descriptions::kExperimentalAccessibilitySwitchAccessTextName,
      flag_descriptions::kExperimentalAccessibilitySwitchAccessTextDescription,
@@ -7028,6 +7034,17 @@
      FEATURE_VALUE_TYPE(media::kVaapiAV1Decoder)},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC)
+    {
+        "ui-debug-tools",
+        flag_descriptions::kUIDebugToolsName,
+        flag_descriptions::kUIDebugToolsDescription,
+        kOsWin | kOsLinux | kOsMac,
+        FEATURE_VALUE_TYPE(features::kUIDebugTools),
+    },
+#endif
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/javascript/web_context_fetcher.cc b/chrome/browser/android/javascript/web_context_fetcher.cc
index e33664b..9ae4e72e 100644
--- a/chrome/browser/android/javascript/web_context_fetcher.cc
+++ b/chrome/browser/android/javascript/web_context_fetcher.cc
@@ -5,11 +5,9 @@
 #include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
-#include "base/json/json_writer.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/android/chrome_jni_headers/WebContextFetcher_jni.h"
-#include "chrome/browser/android/javascript/web_context_fetcher_util.h"
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -33,11 +31,7 @@
     DVLOG(1) << "WebContextFetcher.JavaScriptRunner.ExecutionTime = "
              << javascript_time;
   }
-  std::string json;
-  base::JSONWriter::Write(result, &json);
-  base::android::RunStringCallbackAndroid(
-      scoped_jcallback,
-      WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(json));
+  base::android::RunStringCallbackAndroid(scoped_jcallback, result.GetString());
 }
 
 // IMPORTANT: The output of this fetch should only be handled in memory safe
diff --git a/chrome/browser/android/javascript/web_context_fetcher_util.cc b/chrome/browser/android/javascript/web_context_fetcher_util.cc
deleted file mode 100644
index 5b007e7..0000000
--- a/chrome/browser/android/javascript/web_context_fetcher_util.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/android/javascript/web_context_fetcher_util.h"
-
-// static
-std::string WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(
-    std::string& json) {
-  // If we receive an empty or near empty output return an empty JSON object.
-  if (json.size() <= 2) {
-    return "{}";
-  }
-
-  // Remove trailing and leading double quotation characters.
-  std::string trimmed_json = json.substr(1, json.size() - 2);
-  // Remove escape slash from before quotations.
-  std::string substring_to_search = "\\\"";
-  std::string replace_str = "\"";
-  size_t pos = trimmed_json.find(substring_to_search);
-  // Repeat till end is reached.
-  while (pos != std::string::npos) {
-    // Remove occurrence of the escape character before quotes.
-    trimmed_json.replace(pos, substring_to_search.size(), replace_str);
-    // Get the next occurrence from the current position.
-    pos = trimmed_json.find(substring_to_search, pos + replace_str.size());
-  }
-  return trimmed_json;
-}
diff --git a/chrome/browser/android/javascript/web_context_fetcher_util.h b/chrome/browser/android/javascript/web_context_fetcher_util.h
deleted file mode 100644
index 8f38ced0..0000000
--- a/chrome/browser/android/javascript/web_context_fetcher_util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ANDROID_JAVASCRIPT_WEB_CONTEXT_FETCHER_UTIL_H_
-#define CHROME_BROWSER_ANDROID_JAVASCRIPT_WEB_CONTEXT_FETCHER_UTIL_H_
-
-#include <string>
-#include "base/macros.h"
-
-// Util class for functions related to web context fetching.
-class WebContextFetcherUtil {
- public:
-  // The JS execution function returns the JSON object as a quoted string
-  // literal. Remove the surrounding quotes and the internal escaping, to
-  // convert it into a JSON object that can be parsed. E.g.:
-  // "{\"foo\":\"bar\"}" --> {"foo":"bar"}
-  static std::string ConvertJavascriptOutputToValidJson(std::string& json);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(WebContextFetcherUtil);
-};
-
-#endif  // CHROME_BROWSER_ANDROID_JAVASCRIPT_WEB_CONTEXT_FETCHER_UTIL_H_
diff --git a/chrome/browser/android/javascript/web_context_fetcher_util_unittest.cc b/chrome/browser/android/javascript/web_context_fetcher_util_unittest.cc
deleted file mode 100644
index d39da28..0000000
--- a/chrome/browser/android/javascript/web_context_fetcher_util_unittest.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/android/javascript/web_context_fetcher_util.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/time/time.h"
-#include "chrome/browser/android/history_report/delta_file_service.h"
-#include "chrome/browser/android/history_report/usage_reports_buffer_service.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/test/test_bookmark_client.h"
-#include "components/history/core/browser/history_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "media/base/test_helpers.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-using testing::_;
-
-namespace web_context_fetcher_util {
-
-class WebContextFetcherUtilTest : public testing::Test {
- public:
-  WebContextFetcherUtilTest() {}
-
- protected:
-  DISALLOW_COPY_AND_ASSIGN(WebContextFetcherUtilTest);
-};
-
-// Test that call to get category image with three site icons works.
-TEST_F(WebContextFetcherUtilTest, TestConvertJavascriptOutputToValidJson) {
-  std::string empty_string = "";
-  EXPECT_EQ("{}", WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(
-                      empty_string));
-
-  std::string empty_object = "{}";
-  EXPECT_EQ("{}", WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(
-                      empty_object));
-
-  std::string quoted_empty_object = "\"{}\"";
-  EXPECT_EQ("{}", WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(
-                      quoted_empty_object));
-
-  std::string valid_json_object = "\"{\\\"testing\\\": \\\"123\\\"}\"";
-  EXPECT_EQ("{\"testing\": \"123\"}",
-            WebContextFetcherUtil::ConvertJavascriptOutputToValidJson(
-                valid_json_object));
-}
-
-}  // namespace web_context_fetcher_util
diff --git a/chrome/browser/apps/icon_standardizer.cc b/chrome/browser/apps/icon_standardizer.cc
index 5e9a4a5..de1d52d 100644
--- a/chrome/browser/apps/icon_standardizer.cc
+++ b/chrome/browser/apps/icon_standardizer.cc
@@ -192,8 +192,9 @@
 
     preview.eraseColor(SK_ColorTRANSPARENT);
     SkCanvas canvas1(preview);
-    canvas1.drawBitmap(scaled_preview, -visible_preview_bounds.x() * scale,
-                       -visible_preview_bounds.y() * scale);
+    canvas1.drawImage(scaled_preview.asImage(),
+                      -visible_preview_bounds.x() * scale,
+                      -visible_preview_bounds.y() * scale);
 
     // Use a canvas to perform XOR and DST_OUT operations, which should
     // generate a transparent bitmap for |preview| if the original icon is
@@ -267,8 +268,8 @@
     final_bitmap.eraseColor(SK_ColorTRANSPARENT);
 
     SkCanvas canvas(final_bitmap);
-    canvas.drawBitmap(unscaled_bitmap, (longest_side - width) / 2,
-                      (longest_side - height) / 2);
+    canvas.drawImage(unscaled_bitmap.asImage(), (longest_side - width) / 2,
+                     (longest_side - height) / 2);
 
     final_image.AddRepresentation(gfx::ImageSkiaRep(final_bitmap, rep.scale()));
   }
@@ -316,7 +317,8 @@
         int target_top = (height - scaled_icon_size.height()) / 2;
 
         // Draw the scaled down bitmap and add that to the final image.
-        canvas.drawBitmap(scaled_bitmap, target_left, target_top, &paint_icon);
+        canvas.drawImage(scaled_bitmap.asImage(), target_left, target_top,
+                         SkSamplingOptions(), &paint_icon);
         final_image.AddRepresentation(
             gfx::ImageSkiaRep(final_bitmap, rep.scale()));
       } else {
@@ -368,7 +370,8 @@
 
     if (icon_scale == 1.0f) {
       // Draw the unscaled icon on top of the background.
-      canvas.drawBitmap(unscaled_bitmap, 0, 0, &paint_icon);
+      canvas.drawImage(unscaled_bitmap.asImage(), 0, 0, SkSamplingOptions(),
+                       &paint_icon);
     } else {
       gfx::Size scaled_icon_size =
           gfx::ScaleToRoundedSize(rep.pixel_size(), icon_scale);
@@ -380,7 +383,8 @@
       int target_top = (height - scaled_icon_size.height()) / 2;
 
       // Draw the scaled icon on top of the background.
-      canvas.drawBitmap(scaled_bitmap, target_left, target_top, &paint_icon);
+      canvas.drawImage(scaled_bitmap.asImage(), target_left, target_top,
+                       SkSamplingOptions(), &paint_icon);
     }
 
     final_image.AddRepresentation(gfx::ImageSkiaRep(final_bitmap, rep.scale()));
diff --git a/chrome/browser/apps/icon_standardizer_unittest.cc b/chrome/browser/apps/icon_standardizer_unittest.cc
index af1728c..22443bc 100644
--- a/chrome/browser/apps/icon_standardizer_unittest.cc
+++ b/chrome/browser/apps/icon_standardizer_unittest.cc
@@ -65,7 +65,7 @@
 
   const SkBitmap scaled_bitmap = skia::ImageOperations::Resize(
       square_icon_bitmap, skia::ImageOperations::RESIZE_BEST, 36, 36);
-  canvas.drawBitmap(scaled_bitmap, 14, 14);
+  canvas.drawImage(scaled_bitmap.asImage(), 14, 14);
 
   EXPECT_TRUE(AreBitmapsEqual(*standard_icon.bitmap(), test_standard_bitmap));
 }
@@ -100,7 +100,7 @@
   manually_scaled_bitmap.allocN32Pixels(kIconSize, kIconSize);
   manually_scaled_bitmap.eraseColor(SK_ColorTRANSPARENT);
   SkCanvas canvas2(manually_scaled_bitmap);
-  canvas2.drawBitmap(scaled_bitmap, 3, 3);
+  canvas2.drawImage(scaled_bitmap.asImage(), 3, 3);
 
   EXPECT_TRUE(AreBitmapsEqual(*generated_standard_icon.bitmap(),
                               manually_scaled_bitmap));
diff --git a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
index 20c456c..032dd825 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
@@ -51,6 +51,8 @@
 using extensions::api::braille_display_private::MockBrailleController;
 using testing::WithParamInterface;
 
+namespace ash {
+
 namespace {
 
 // Use a real domain to avoid policy loading problems.
@@ -784,3 +786,5 @@
   EXPECT_TRUE(IsSpokenFeedbackEnabled());
   EXPECT_TRUE(IsBrailleImeActive());
 }
+
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/app_launch_utils.cc b/chrome/browser/ash/app_mode/app_launch_utils.cc
index 0a6e7a6..f854077 100644
--- a/chrome/browser/ash/app_mode/app_launch_utils.cc
+++ b/chrome/browser/ash/app_mode/app_launch_utils.cc
@@ -14,7 +14,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -109,4 +109,4 @@
   test_prefs_to_reset = prefs;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/app_launch_utils.h b/chrome/browser/ash/app_mode/app_launch_utils.h
index 44992eb..c383d9e 100644
--- a/chrome/browser/ash/app_mode/app_launch_utils.h
+++ b/chrome/browser/ash/app_mode/app_launch_utils.h
@@ -10,7 +10,7 @@
 class PrefService;
 class Profile;
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppId;
 
@@ -25,6 +25,12 @@
 // Replace the list of preferences which are reset in tests.
 void SetEphemeralKioskPreferencesListForTesting(std::vector<std::string>*);
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the migration of
+// //chrome/browser/ash is finished.
+namespace chromeos {
+using ::ash::LaunchAppOrDie;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_APP_LAUNCH_UTILS_H_
diff --git a/chrome/browser/ash/app_mode/app_launch_utils_unittest.cc b/chrome/browser/ash/app_mode/app_launch_utils_unittest.cc
index 1dcf854..dd0834a 100644
--- a/chrome/browser/ash/app_mode/app_launch_utils_unittest.cc
+++ b/chrome/browser/ash/app_mode/app_launch_utils_unittest.cc
@@ -18,6 +18,8 @@
 #include "components/user_manager/scoped_user_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace ash {
+
 namespace {
 
 const char kEmptyPrefsFile[] = "{}";
@@ -27,10 +29,10 @@
   explicit ScopedKioskPreferencesListForTesting(
       const std::vector<std::string>& prefs_to_reset)
       : prefs_(prefs_to_reset) {
-    chromeos::SetEphemeralKioskPreferencesListForTesting(&prefs_);
+    SetEphemeralKioskPreferencesListForTesting(&prefs_);
   }
   ~ScopedKioskPreferencesListForTesting() {
-    chromeos::SetEphemeralKioskPreferencesListForTesting(nullptr);
+    SetEphemeralKioskPreferencesListForTesting(nullptr);
   }
 
  private:
@@ -92,7 +94,7 @@
   ScopedKioskPreferencesListForTesting prefs({pref_name});
   pref_service->SetBoolean(pref_name, true);
   pref_service->SetBoolean(pref2_name, true);
-  chromeos::ResetEphemeralKioskPreferences(pref_service.get());
+  ResetEphemeralKioskPreferences(pref_service.get());
   EXPECT_FALSE(pref_service->GetBoolean(pref_name));
   EXPECT_TRUE(pref_service->GetBoolean(pref2_name));
 }
@@ -110,7 +112,9 @@
   pref_service->SetBoolean(pref_a, true);
   pref_service->SetBoolean(pref_b, true);
 
-  chromeos::ResetEphemeralKioskPreferences(pref_service.get());
+  ResetEphemeralKioskPreferences(pref_service.get());
   EXPECT_FALSE(pref_service->GetBoolean(pref_a));
   EXPECT_FALSE(pref_service->GetBoolean(pref_b));
 }
+
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/app_session.cc b/chrome/browser/ash/app_mode/app_session.cc
index 91091e5..e392596 100644
--- a/chrome/browser/ash/app_mode/app_session.cc
+++ b/chrome/browser/ash/app_mode/app_session.cc
@@ -51,7 +51,7 @@
 using extensions::AppWindow;
 using extensions::AppWindowRegistry;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -63,13 +63,13 @@
 }
 
 void RebootDevice() {
-  PowerManagerClient::Get()->RequestRestart(
+  chromeos::PowerManagerClient::Get()->RequestRestart(
       power_manager::REQUEST_RESTART_OTHER, "kiosk app session");
 }
 
 void StartFloatingAccessibilityMenu() {
-  ash::AccessibilityController* accessibility_controller =
-      ash::AccessibilityController::Get();
+  AccessibilityController* accessibility_controller =
+      AccessibilityController::Get();
   if (accessibility_controller)
     accessibility_controller->ShowFloatingMenuIfEnabled();
 }
@@ -358,4 +358,4 @@
       FROM_HERE, base::BindOnce(&DumpPluginProcessOnIOThread, hung_plugins));
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/app_session.h b/chrome/browser/ash/app_mode/app_session.h
index 3844cd8..d23e9741 100644
--- a/chrome/browser/ash/app_mode/app_session.h
+++ b/chrome/browser/ash/app_mode/app_session.h
@@ -23,7 +23,7 @@
 class AppWindow;
 }
 
-namespace chromeos {
+namespace ash {
 
 class KioskSessionPluginHandler;
 
@@ -86,6 +86,12 @@
   DISALLOW_COPY_AND_ASSIGN(AppSession);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the migration of
+// //chrome/browser/chromeos is finished.
+namespace chromeos {
+using ::ash::AppSession;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_APP_SESSION_H_
diff --git a/chrome/browser/ash/app_mode/app_session_unittest.cc b/chrome/browser/ash/app_mode/app_session_unittest.cc
index cb18c86..f545e6f 100644
--- a/chrome/browser/ash/app_mode/app_session_unittest.cc
+++ b/chrome/browser/ash/app_mode/app_session_unittest.cc
@@ -16,10 +16,12 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+using ::chromeos::FakePowerManagerClient;
+
 constexpr char kPepperPluginName1[] = "pepper_plugin_name1";
 constexpr char kPepperPluginName2[] = "pepper_plugin_name2";
 constexpr char kBrowserPluginName[] = "browser_plugin_name";
@@ -147,4 +149,4 @@
   delegate->OnPluginHung(std::set<int>());
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.cc
index 6a33e07..8931202 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.cc
@@ -14,7 +14,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_thread.h"
 
-namespace chromeos {
+namespace ash {
 
 ArcKioskAppData::ArcKioskAppData(const std::string& app_id,
                                  const std::string& package_name,
@@ -77,4 +77,4 @@
   // Do nothing
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.h b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.h
index 1ef156c..64d4679b 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_data.h
@@ -13,7 +13,7 @@
 #include "components/account_id/account_id.h"
 #include "ui/gfx/image/image_skia.h"
 
-namespace chromeos {
+namespace ash {
 
 // Fetches from Android side and caches ARC kiosk app data such as name and
 // icon.
@@ -52,6 +52,12 @@
   DISALLOW_COPY_AND_ASSIGN(ArcKioskAppData);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// migration is finished.
+namespace chromeos {
+using ::ash::ArcKioskAppData;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_ARC_ARC_KIOSK_APP_DATA_H_
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.cc
index 571e6a6..08208729 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.cc
@@ -16,7 +16,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/events/event_constants.h"
 
-namespace chromeos {
+namespace ash {
 
 ArcKioskAppLauncher::ArcKioskAppLauncher(content::BrowserContext* context,
                                          ArcAppListPrefs* prefs,
@@ -97,4 +97,4 @@
   prefs_->RemoveObserver(this);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.h
index 79614961..0938d15d 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_launcher.h
@@ -10,7 +10,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 
-namespace chromeos {
+namespace ash {
 
 // Starts Android app in kiosk mode.
 // Keeps track of start progress and pins app window
@@ -68,6 +68,6 @@
   DISALLOW_COPY_AND_ASSIGN(ArcKioskAppLauncher);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_ARC_ARC_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.cc
index bced224..ccca3ae 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.cc
@@ -27,7 +27,7 @@
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -192,4 +192,5 @@
 
   NotifyKioskAppsChanged();
 }
-}  // namespace chromeos
+
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h
index 598df9d..fca6967 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h
@@ -19,7 +19,7 @@
 
 class PrefRegistrySimple;
 
-namespace chromeos {
+namespace ash {
 
 // Keeps track of Android apps that are to be launched in kiosk mode.
 // For removed apps deletes appropriate cryptohome. The information about
@@ -72,6 +72,12 @@
   DISALLOW_COPY_AND_ASSIGN(ArcKioskAppManager);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::ArcKioskAppManager;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_ARC_ARC_KIOSK_APP_MANAGER_H_
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager_browsertest.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
index f0b3b48..c4ddc1c7 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
@@ -24,7 +24,7 @@
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -285,4 +285,4 @@
   ASSERT_TRUE(app->icon().BackedBySameObjectAs(new_icon));
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.cc
index f895d47..faae607 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.cc
@@ -20,7 +20,7 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -264,4 +264,4 @@
 void ArcKioskAppService::RestartLauncher() {}
 void ArcKioskAppService::LaunchApp() {}
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h
index cf18f47a..8d02913 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h
@@ -24,7 +24,7 @@
 class BrowserContext;
 }  // namespace content
 
-namespace chromeos {
+namespace ash {
 
 class ArcKioskAppManager;
 
@@ -125,6 +125,12 @@
   DISALLOW_COPY_AND_ASSIGN(ArcKioskAppService);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::ArcKioskAppService;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_ARC_ARC_KIOSK_APP_SERVICE_H_
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.cc
index dcbff0d..c76d890b 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
-namespace chromeos {
+namespace ash {
 
 // static
 ArcKioskAppService* ArcKioskAppServiceFactory::GetForBrowserContext(
@@ -40,4 +40,4 @@
   return ArcKioskAppService::Create(profile);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.h b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.h
index c3064ee..4778a9a 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.h
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.h
@@ -9,7 +9,7 @@
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-namespace chromeos {
+namespace ash {
 
 class ArcKioskAppService;
 
@@ -36,6 +36,12 @@
   DISALLOW_COPY_AND_ASSIGN(ArcKioskAppServiceFactory);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::ArcKioskAppServiceFactory;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_ARC_ARC_KIOSK_APP_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
index 2d250a6..0971ab99 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
@@ -26,7 +26,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/test/test_screen.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -259,4 +259,4 @@
   controller.WaitUntilWindowCreated();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/certificate_manager_dialog.cc b/chrome/browser/ash/app_mode/certificate_manager_dialog.cc
index c94cec3..6f01151 100644
--- a/chrome/browser/ash/app_mode/certificate_manager_dialog.cc
+++ b/chrome/browser/ash/app_mode/certificate_manager_dialog.cc
@@ -24,7 +24,7 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace ash {
 
 CertificateManagerDialog::CertificateManagerDialog(
     Profile* profile,
@@ -46,4 +46,4 @@
   size->SetSize(kDefaultWidth, kDefaultHeight);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/certificate_manager_dialog.h b/chrome/browser/ash/app_mode/certificate_manager_dialog.h
index c697607..a736e37 100644
--- a/chrome/browser/ash/app_mode/certificate_manager_dialog.h
+++ b/chrome/browser/ash/app_mode/certificate_manager_dialog.h
@@ -11,7 +11,7 @@
 
 class Profile;
 
-namespace chromeos {
+namespace ash {
 
 // This dialog is used to manage user certificates from the kiosk launch screen.
 class CertificateManagerDialog : public LoginWebDialog {
@@ -29,6 +29,12 @@
   DISALLOW_COPY_AND_ASSIGN(CertificateManagerDialog);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::CertificateManagerDialog;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_CERTIFICATE_MANAGER_DIALOG_H_
diff --git a/chrome/browser/ash/app_mode/fake_cws.cc b/chrome/browser/ash/app_mode/fake_cws.cc
index 413c8a41..069f082 100644
--- a/chrome/browser/ash/app_mode/fake_cws.cc
+++ b/chrome/browser/ash/app_mode/fake_cws.cc
@@ -28,7 +28,7 @@
 using net::test_server::HttpRequest;
 using net::test_server::HttpResponse;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -331,4 +331,4 @@
   return std::unique_ptr<HttpResponse>();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/fake_cws.h b/chrome/browser/ash/app_mode/fake_cws.h
index 91f5baed..8be7880 100644
--- a/chrome/browser/ash/app_mode/fake_cws.h
+++ b/chrome/browser/ash/app_mode/fake_cws.h
@@ -18,7 +18,7 @@
 #include "net/test/embedded_test_server/http_response.h"
 #include "url/gurl.h"
 
-namespace chromeos {
+namespace ash {
 
 // Simple fake CWS update check request handler that returns a fixed update
 // check response. The response is created either from SetUpdateCrx() or
@@ -92,6 +92,12 @@
   DISALLOW_COPY_AND_ASSIGN(FakeCWS);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::FakeCWS;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_FAKE_CWS_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_data.cc b/chrome/browser/ash/app_mode/kiosk_app_data.cc
index f2c42426d..e39bfdb 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_data.cc
@@ -42,7 +42,7 @@
 
 using content::BrowserThread;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -582,4 +582,4 @@
   SetStatus(Status::kLoaded);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_data.h b/chrome/browser/ash/app_mode/kiosk_app_data.h
index 8afc5a4f..e1d59b2 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_data.h
@@ -33,7 +33,7 @@
 }
 }
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppDataDelegate;
 
@@ -161,6 +161,11 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppData);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace chromeos {
+using ::ash::KioskAppData;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_DATA_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_data_base.cc b/chrome/browser/ash/app_mode/kiosk_app_data_base.cc
index b7e4c50..dd483faf 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_data_base.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_data_base.cc
@@ -20,7 +20,7 @@
 
 using content::BrowserThread;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -147,4 +147,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_data_base.h b/chrome/browser/ash/app_mode/kiosk_app_data_base.h
index 7c12f3d..12db924 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_data_base.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_data_base.h
@@ -18,7 +18,7 @@
 class DictionaryValue;
 }
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppDataBase : public KioskAppIconLoader::Delegate {
  public:
@@ -81,6 +81,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppDataBase);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_DATA_BASE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_data_delegate.h b/chrome/browser/ash/app_mode/kiosk_app_data_delegate.h
index 230d79d9..183e2ff1 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_data_delegate.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_data_delegate.h
@@ -11,7 +11,7 @@
 class FilePath;
 }
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppDataDelegate {
  public:
@@ -32,6 +32,6 @@
   virtual ~KioskAppDataDelegate() {}
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_DATA_DELEGATE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_external_loader.cc b/chrome/browser/ash/app_mode/kiosk_app_external_loader.cc
index 519e148d..765d025 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_external_loader.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_external_loader.cc
@@ -11,7 +11,7 @@
 #include "base/values.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 
-namespace chromeos {
+namespace ash {
 
 KioskAppExternalLoader::KioskAppExternalLoader(AppClass app_class)
     : app_class_(app_class) {}
@@ -75,4 +75,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_external_loader.h b/chrome/browser/ash/app_mode/kiosk_app_external_loader.h
index b0c7564..0b2fc15 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_external_loader.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_external_loader.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/extensions/external_loader.h"
 
-namespace chromeos {
+namespace ash {
 
 // An extensions::ExternalLoader that loads apps and extensions for a kiosk
 // session. It is used to either load primary kiosk app, or secondary kiosk
@@ -62,6 +62,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppExternalLoader);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_EXTERNAL_LOADER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_icon_loader.cc b/chrome/browser/ash/app_mode/kiosk_app_icon_loader.cc
index 4cc65183..a08b291 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_icon_loader.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_icon_loader.cc
@@ -18,7 +18,7 @@
 
 using content::BrowserThread;
 
-namespace chromeos {
+namespace ash {
 
 class IconImageRequest : public ImageDecoder::ImageRequest {
  public:
@@ -98,4 +98,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_icon_loader.h b/chrome/browser/ash/app_mode/kiosk_app_icon_loader.h
index 49f47a1f..5be44da 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_icon_loader.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_icon_loader.h
@@ -16,7 +16,7 @@
 class FilePath;
 }
 
-namespace chromeos {
+namespace ash {
 
 // Loads locally stored icon data and decodes it.
 class KioskAppIconLoader {
@@ -52,6 +52,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppIconLoader);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_ICON_LOADER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_launch_error.cc b/chrome/browser/ash/app_mode/kiosk_app_launch_error.cc
index a203593..e12ee4e 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_launch_error.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_launch_error.cc
@@ -12,7 +12,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "ui/base/l10n/l10n_util.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -134,4 +134,4 @@
   dict_update->Remove(kKeyCryptohomeFailure, NULL);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_launch_error.h b/chrome/browser/ash/app_mode/kiosk_app_launch_error.h
index bb88ef9..544885a 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_launch_error.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_launch_error.h
@@ -8,10 +8,11 @@
 #include <string>
 
 #include "base/macros.h"
+// TODO(https://crbug.com/1164001): forward declare AuthFailure when migrated
+// to ash/components/.
+#include "chromeos/login/auth/auth_status_consumer.h"
 
-namespace chromeos {
-
-class AuthFailure;
+namespace ash {
 
 class KioskAppLaunchError {
  public:
@@ -60,6 +61,12 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(KioskAppLaunchError);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::KioskAppLaunchError;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_LAUNCH_ERROR_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_launch_error_unittest.cc b/chrome/browser/ash/app_mode/kiosk_app_launch_error_unittest.cc
index a4a97df9..78d4a372 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_launch_error_unittest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_launch_error_unittest.cc
@@ -14,8 +14,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
-using chromeos::AuthFailure;
-using chromeos::KioskAppLaunchError;
+namespace ash {
+
+using ::chromeos::AuthFailure;
+using ::chromeos::KioskAppLaunchError;
 
 namespace {
 
@@ -28,7 +30,7 @@
 // Get Kiosk dictionary value. It is replaced after each update.
 const base::DictionaryValue* GetKioskDictionary() {
   return g_browser_process->local_state()->GetDictionary(
-      chromeos::KioskAppManager::kKioskDictionaryName);
+      KioskAppManager::kKioskDictionaryName);
 }
 
 }  // namespace
@@ -128,3 +130,5 @@
   KioskAppLaunchError::RecordMetricAndClear();
   EXPECT_FALSE(GetKioskDictionary()->HasKey(kKeyCryptohomeFailure));
 }
+
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/kiosk_app_launcher.cc
index e5c8c29..36fe219 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_launcher.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_launcher.h"
 
-namespace chromeos {
+namespace ash {
 
 KioskAppLauncher::KioskAppLauncher() = default;
 
@@ -15,4 +15,4 @@
   delegate_ = delegate;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_launcher.h b/chrome/browser/ash/app_mode/kiosk_app_launcher.h
index 7b751a7..b5776b3 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_launcher.h
@@ -6,7 +6,8 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
 
-namespace chromeos {
+namespace ash {
+
 // Abstract class responsible for the launch different type of kiosk apps.
 //
 //
@@ -69,6 +70,13 @@
  protected:
   Delegate* delegate_ = nullptr;  // Not owned, owns us.
 };
-}  // namespace chromeos
+
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::KioskAppLauncher;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager.cc b/chrome/browser/ash/app_mode/kiosk_app_manager.cc
index 9a72b43..502f0ec9 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager.cc
@@ -58,10 +58,12 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "third_party/cros_system_api/switches/chrome_switches.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+using ::chromeos::InstallAttributes;
+
 // Domain that is used for kiosk-app account IDs.
 constexpr char kKioskAppAccountDomain[] = "kiosk-apps";
 
@@ -106,14 +108,14 @@
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
-std::unique_ptr<ExternalCache> CreateExternalCache(
-    ExternalCacheDelegate* delegate) {
+std::unique_ptr<chromeos::ExternalCache> CreateExternalCache(
+    chromeos::ExternalCacheDelegate* delegate) {
   if (g_test_overrides)
     return g_test_overrides->CreateExternalCache(delegate, true);
 
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory =
       g_browser_process->shared_url_loader_factory();
-  auto cache = std::make_unique<ExternalCacheImpl>(
+  auto cache = std::make_unique<chromeos::ExternalCacheImpl>(
       GetCrxCacheDir(), shared_url_loader_factory, GetBackgroundTaskRunner(),
       delegate, true /* always_check_updates */,
       false /* wait_for_cache_initialization */);
@@ -645,7 +647,7 @@
     const std::string& app_id,
     const base::FilePath& crx_path,
     const std::string& version,
-    ExternalCache::PutExternalExtensionCallback callback) {
+    chromeos::ExternalCache::PutExternalExtensionCallback callback) {
   external_cache_->PutExternalExtension(app_id, crx_path, version,
                                         std::move(callback));
 }
@@ -862,4 +864,4 @@
   return base::TimeDelta::FromMilliseconds(delay);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager.h b/chrome/browser/ash/app_mode/kiosk_app_manager.h
index f7fbdb6..7dc6a56 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager.h
@@ -18,6 +18,9 @@
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/chromeos/extensions/external_cache.h"
 #include "chrome/browser/chromeos/extensions/external_cache_delegate.h"
+// TODO(https://crbug.com/1164001): use forward declaration when moved to
+// chrome/browser/ash/.
+#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "components/account_id/account_id.h"
@@ -31,20 +34,23 @@
 class CommandLine;
 }
 
+namespace chromeos {
+class KioskAutoLaunchViewsTest;
+class KioskTest;
+}  // namespace chromeos
+
 namespace extensions {
 class Extension;
 }
 
-namespace chromeos {
+namespace ash {
 
-class ExternalCache;
 class KioskAppData;
 class KioskExternalUpdater;
-class OwnerSettingsServiceChromeOS;
 
 // KioskAppManager manages cached app data.
 class KioskAppManager : public KioskAppManagerBase,
-                        public ExternalCacheDelegate {
+                        public chromeos::ExternalCacheDelegate {
  public:
   enum class ConsumerKioskAutoLaunchStatus {
     // Consumer kiosk mode auto-launch feature can be enabled on this machine.
@@ -71,8 +77,8 @@
 
     // Creates the external cache that should be used by the
     // KioskAppManager. It should always return a valid object.
-    virtual std::unique_ptr<ExternalCache> CreateExternalCache(
-        ExternalCacheDelegate* delegate,
+    virtual std::unique_ptr<chromeos::ExternalCache> CreateExternalCache(
+        chromeos::ExternalCacheDelegate* delegate,
         bool always_check_updates) = 0;
 
     // Creates an AppSession object that will mantain a started kiosk app
@@ -221,7 +227,7 @@
       const std::string& app_id,
       const base::FilePath& crx_path,
       const std::string& version,
-      ExternalCache::PutExternalExtensionCallback callback);
+      chromeos::ExternalCache::PutExternalExtensionCallback callback);
 
   // Whether the current platform is compliant with the given required
   // platform version.
@@ -250,9 +256,8 @@
   friend struct base::LazyInstanceTraitsBase<KioskAppManager>;
   friend std::default_delete<KioskAppManager>;
   friend class KioskAppManagerTest;
-  friend class KioskAutoLaunchViewsTest;
-  friend class KioskTest;
-  friend class KioskUpdateTest;
+  friend class chromeos::KioskAutoLaunchViewsTest;
+  friend class chromeos::KioskTest;
 
   enum class AutoLoginState {
     kNone = 0,
@@ -278,16 +283,16 @@
   // Updates the prefs of |external_cache_| from |apps_|.
   void UpdateExternalCachePrefs();
 
-  // ExternalCacheDelegate:
+  // chromeos::ExternalCacheDelegate:
   void OnExtensionLoadedInCache(const extensions::ExtensionId& id) override;
   void OnExtensionDownloadFailed(const extensions::ExtensionId& id) override;
 
-  // Callback for InstallAttributes::LockDevice() during
+  // Callback for chromeos::InstallAttributes::LockDevice() during
   // EnableConsumerModeKiosk() call.
   void OnLockDevice(EnableKioskAutoLaunchCallback callback,
-                    InstallAttributes::LockResult result);
+                    chromeos::InstallAttributes::LockResult result);
 
-  // Callback for InstallAttributes::ReadImmutableAttributes() during
+  // Callback for chromeos::InstallAttributes::ReadImmutableAttributes() during
   // GetConsumerKioskModeStatus() call.
   void OnReadImmutableAttributes(
       GetConsumerKioskAutoLaunchStatusCallback callback);
@@ -325,7 +330,7 @@
   std::string auto_launch_app_id_;
   std::string currently_auto_launched_with_zero_delay_app_;
 
-  std::unique_ptr<ExternalCache> external_cache_;
+  std::unique_ptr<chromeos::ExternalCache> external_cache_;
 
   std::unique_ptr<KioskExternalUpdater> usb_stick_updater_;
 
@@ -344,6 +349,12 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppManager);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::KioskAppManager;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_MANAGER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager_base.cc b/chrome/browser/ash/app_mode/kiosk_app_manager_base.cc
index 79a8109..886ec3b 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager_base.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager_base.cc
@@ -18,7 +18,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/settings/cros_settings_names.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 // Sub directory under DIR_USER_DATA to store cached icon files.
@@ -113,4 +113,4 @@
       account_ids_to_remove);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager_base.h b/chrome/browser/ash/app_mode/kiosk_app_manager_base.h
index 7090f05..6900243 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager_base.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager_base.h
@@ -24,7 +24,7 @@
 class FilePath;
 }
 
-namespace chromeos {
+namespace ash {
 
 class AppSession;
 class KioskAppDataBase;
@@ -101,6 +101,12 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppManagerBase);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::KioskAppManagerBase;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_MANAGER_BASE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_app_manager_browsertest.cc
index 417aec1..f64837f 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager_browsertest.cc
@@ -49,10 +49,12 @@
 
 using content::BrowserThread;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+using ::chromeos::InstallAttributes;
+
 // An app to test local fs data persistence across app update. V1 app writes
 // data into local fs. V2 app reads and verifies the data.
 // Webstore data json is in
@@ -1059,4 +1061,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_manager_observer.h b/chrome/browser/ash/app_mode/kiosk_app_manager_observer.h
index 4bed2fb..99a168a4 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_manager_observer.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_manager_observer.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppManagerObserver {
  public:
@@ -41,6 +41,12 @@
   virtual ~KioskAppManagerObserver() {}
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::KioskAppManagerObserver;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_types.cc b/chrome/browser/ash/app_mode/kiosk_app_types.cc
index e6e4ff6..327dff4 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_types.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_types.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 
-namespace chromeos {
+namespace ash {
 
 KioskAppId::KioskAppId() = default;
 KioskAppId::~KioskAppId() = default;
@@ -30,4 +30,4 @@
   return KioskAppId(KioskAppType::WEB_APP, account_id);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_types.h b/chrome/browser/ash/app_mode/kiosk_app_types.h
index 9f7492c8..93a22ec 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_types.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_types.h
@@ -10,7 +10,7 @@
 #include "base/optional.h"
 #include "components/account_id/account_id.h"
 
-namespace chromeos {
+namespace ash {
 
 // Type of different kiosk apps to be launched.
 enum class KioskAppType { ARC_APP, CHROME_APP, WEB_APP };
@@ -40,6 +40,13 @@
   KioskAppId(KioskAppType type, const AccountId& account_id);
 };
 
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::KioskAppId;
+using ::ash::KioskAppType;
 }  // namespace chromeos
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_TYPES_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.cc b/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.cc
index 2c400ff4..27f7aea 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.cc
@@ -10,7 +10,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 
-namespace chromeos {
+namespace ash {
 
 KioskAppUpdateInstallGate::KioskAppUpdateInstallGate(Profile* profile)
     : profile_(profile),
@@ -39,4 +39,4 @@
   return DELAY;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.h b/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.h
index 31d5297a..7228abef 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_install_gate.h
@@ -15,7 +15,7 @@
 
 class Profile;
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppUpdateInstallGate : public extensions::InstallGate {
  public:
@@ -33,6 +33,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskAppUpdateInstallGate);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_UPDATE_INSTALL_GATE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service.cc b/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
index d1330e5..16f4b4c 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
@@ -20,7 +20,7 @@
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/common/extension.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -175,4 +175,4 @@
       g_browser_process->platform_part()->automatic_reboot_manager());
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service.h b/chrome/browser/ash/app_mode/kiosk_app_update_service.h
index 7412222..5c27470 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service.h
@@ -12,6 +12,9 @@
 #include "base/memory/singleton.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_observer.h"
+// TODO(https://crbug.com/1164001): forward declare when moved to
+// chrome/browser/ash/.
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
 #include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -23,11 +26,7 @@
 class Extension;
 }
 
-namespace chromeos {
-
-namespace system {
-class AutomaticRebootManager;
-}
+namespace ash {
 
 // This class enforces automatic restart on app and Chrome updates in app mode.
 class KioskAppUpdateService : public KeyedService,
@@ -97,6 +96,6 @@
       content::BrowserContext* profile) const override;
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_UPDATE_SERVICE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
index b87696f..0118114f 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
@@ -42,7 +42,7 @@
 #include "extensions/test/extension_test_message_listener.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -223,4 +223,4 @@
   EXPECT_TRUE(listener.WaitUntilSatisfied());
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
index 048f6dd1..2aab70d1 100644
--- a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
@@ -38,7 +38,7 @@
 constexpr em::DeviceLocalAccountInfoProto_AccountType kKioskAccountType =
     em::DeviceLocalAccountInfoProto_AccountType_ACCOUNT_TYPE_KIOSK_APP;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -87,7 +87,7 @@
                                     cryptohome_id.account_id());
     command_line->AppendSwitchASCII(
         switches::kLoginProfile,
-        CryptohomeClient::GetStubSanitizedUsername(cryptohome_id));
+        chromeos::CryptohomeClient::GetStubSanitizedUsername(cryptohome_id));
 
     fake_cws_->Init(embedded_test_server());
     fake_cws_->SetUpdateCrx(kTestKioskApp, std::string(kTestKioskApp) + ".crx",
@@ -184,4 +184,4 @@
   KioskSessionInitializedWaiter().Wait();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
index 3e76d241..124cd2a 100644
--- a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
+++ b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
@@ -23,10 +23,12 @@
 #include "components/user_manager/user_manager.h"
 #include "third_party/cros_system_api/dbus/cryptohome/dbus-constants.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+using ::chromeos::CryptohomeClient;
+
 void ScheduleDelayedCryptohomeRemoval(const AccountId& account_id) {
   PrefService* const local_state = g_browser_process->local_state();
   {
@@ -136,7 +138,7 @@
 }
 
 void KioskCryptohomeRemover::RemoveObsoleteCryptohomes() {
-  chromeos::CryptohomeClient* client = chromeos::CryptohomeClient::Get();
+  auto* client = CryptohomeClient::Get();
   client->WaitForServiceToBeAvailable(
       base::BindOnce(&PerformDelayedCryptohomeRemovals));
 }
@@ -177,4 +179,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h
index 182e3433..6f3c4a7 100644
--- a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h
+++ b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h
@@ -12,7 +12,7 @@
 class AccountId;
 class PrefRegistrySimple;
 
-namespace chromeos {
+namespace ash {
 
 // Helper functions to remove cryptohomes of no longer existing kiosk apps.
 class KioskCryptohomeRemover {
@@ -31,6 +31,12 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(KioskCryptohomeRemover);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// migration is finished.
+namespace chromeos {
+using ::ash::KioskCryptohomeRemover;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_CRYPTOHOME_REMOVER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_external_update_validator.cc b/chrome/browser/ash/app_mode/kiosk_external_update_validator.cc
index 1c19f92..57d4e98 100644
--- a/chrome/browser/ash/app_mode/kiosk_external_update_validator.cc
+++ b/chrome/browser/ash/app_mode/kiosk_external_update_validator.cc
@@ -11,7 +11,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_constants.h"
 
-namespace chromeos {
+namespace ash {
 
 KioskExternalUpdateValidator::KioskExternalUpdateValidator(
     const scoped_refptr<base::SequencedTaskRunner>& backend_task_runner,
@@ -77,4 +77,4 @@
           minimum_browser_version, temp_dir));
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_external_update_validator.h b/chrome/browser/ash/app_mode/kiosk_external_update_validator.h
index 7bd81d7..e31eefc 100644
--- a/chrome/browser/ash/app_mode/kiosk_external_update_validator.h
+++ b/chrome/browser/ash/app_mode/kiosk_external_update_validator.h
@@ -18,7 +18,7 @@
 class Extension;
 }
 
-namespace chromeos {
+namespace ash {
 
 // Delegate class for KioskExternalUpdateValidator, derived class must support
 // WeakPtr.
@@ -75,6 +75,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskExternalUpdateValidator);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_EXTERNAL_UPDATE_VALIDATOR_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_external_updater.cc b/chrome/browser/ash/app_mode/kiosk_external_updater.cc
index b1ed98a..e4567ea614 100644
--- a/chrome/browser/ash/app_mode/kiosk_external_updater.cc
+++ b/chrome/browser/ash/app_mode/kiosk_external_updater.cc
@@ -23,10 +23,14 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+namespace disks = ::chromeos::disks;
+using ::chromeos::MountError;
+using ::chromeos::MountType;
+
 constexpr base::FilePath::CharType kExternalUpdateManifest[] =
     "external_update.json";
 constexpr char kExternalCrx[] = "external_crx";
@@ -111,8 +115,8 @@
     const disks::DiskMountManager::MountPointInfo& mount_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (mount_info.mount_type != MOUNT_TYPE_DEVICE ||
-      error_code != MOUNT_ERROR_NONE) {
+  if (mount_info.mount_type != MountType::MOUNT_TYPE_DEVICE ||
+      error_code != MountError::MOUNT_ERROR_NONE) {
     return;
   }
 
@@ -486,4 +490,4 @@
   return message;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_external_updater.h b/chrome/browser/ash/app_mode/kiosk_external_updater.h
index 7027a0f..61f6591 100644
--- a/chrome/browser/ash/app_mode/kiosk_external_updater.h
+++ b/chrome/browser/ash/app_mode/kiosk_external_updater.h
@@ -15,15 +15,16 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "chrome/browser/ash/app_mode/kiosk_external_update_validator.h"
+// TODO(https://crbug.com/1164001): use forward declaration when moved to
+// chrome/browser/ash/.
+#include "chrome/browser/chromeos/ui/kiosk_external_update_notification.h"
 #include "chromeos/disks/disk_mount_manager.h"
 
-namespace chromeos {
-
-class KioskExternalUpdateNotification;
+namespace ash {
 
 // Observes the disk mount/unmount events, scans the usb stick for external
 // kiosk app updates, validates the external crx, and updates the cache.
-class KioskExternalUpdater : public disks::DiskMountManager::Observer,
+class KioskExternalUpdater : public chromeos::disks::DiskMountManager::Observer,
                              public KioskExternalUpdateValidatorDelegate {
  public:
   enum class ErrorCode {
@@ -56,11 +57,11 @@
     base::string16 error;
   };
 
-  // disks::DiskMountManager::Observer overrides.
-  void OnMountEvent(
-      disks::DiskMountManager::MountEvent event,
-      MountError error_code,
-      const disks::DiskMountManager::MountPointInfo& mount_info) override;
+  // chromeos::disks::DiskMountManager::Observer overrides.
+  void OnMountEvent(chromeos::disks::DiskMountManager::MountEvent event,
+                    chromeos::MountError error_code,
+                    const chromeos::disks::DiskMountManager::MountPointInfo&
+                        mount_info) override;
 
   // KioskExternalUpdateValidatorDelegate overrides:
   void OnExternalUpdateUnpackSuccess(const std::string& app_id,
@@ -146,6 +147,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskExternalUpdater);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_EXTERNAL_UPDATER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.cc b/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.cc
index b6d8cd9..5e2ad75 100644
--- a/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.cc
+++ b/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.cc
@@ -17,7 +17,7 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -129,4 +129,4 @@
   show_notification_upon_next_user_activity_ = true;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.h b/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.h
index c60f38a..48d1b24 100644
--- a/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.h
+++ b/chrome/browser/ash/app_mode/kiosk_mode_idle_app_name_notification.h
@@ -10,15 +10,17 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/timer/timer.h"
+// TODO(https://crbug.com/1164001): move to forward declaration when migrated to
+// chrome/browser/ash/.
+#include "chrome/browser/chromeos/ui/idle_app_name_notification_view.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/base/user_activity/user_activity_observer.h"
 
-namespace chromeos {
+namespace ash {
 
-class IdleAppNameNotificationView;
-
-class KioskModeIdleAppNameNotification : public ui::UserActivityObserver,
-                                         public PowerManagerClient::Observer {
+class KioskModeIdleAppNameNotification
+    : public ui::UserActivityObserver,
+      public chromeos::PowerManagerClient::Observer {
  public:
   static void Initialize();
 
@@ -57,6 +59,12 @@
   DISALLOW_COPY_AND_ASSIGN(KioskModeIdleAppNameNotification);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the migration of
+// //chrome/browser/chromeos is finished.
+namespace chromeos {
+using ::ash::KioskModeIdleAppNameNotification;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_MODE_IDLE_APP_NAME_NOTIFICATION_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
index 57bcd2b..14bf002a 100644
--- a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
@@ -31,12 +31,13 @@
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 
-using content::BrowserThread;
-
-namespace chromeos {
+namespace ash {
 
 namespace {
 
+using ::chromeos::CryptohomeClient;
+using ::content::BrowserThread;
+
 KioskAppLaunchError::Error LoginFailureToKioskAppLaunchError(
     const AuthFailure& error) {
   switch (error.reason()) {
@@ -242,4 +243,4 @@
   ReportLaunchResult(KioskAppLaunchError::Error::kNone);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_profile_loader.h b/chrome/browser/ash/app_mode/kiosk_profile_loader.h
index 7bd8ed9..9085c483 100644
--- a/chrome/browser/ash/app_mode/kiosk_profile_loader.h
+++ b/chrome/browser/ash/app_mode/kiosk_profile_loader.h
@@ -14,11 +14,13 @@
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chromeos/login/auth/login_performer.h"
+// TODO(https://crbug.com/1164001): remove when migrated to ash/components/.
+#include "chromeos/login/auth/user_context.h"
 #include "components/account_id/account_id.h"
 
 class Profile;
 
-namespace chromeos {
+namespace ash {
 
 enum class KioskAppType;
 
@@ -76,6 +78,12 @@
   DISALLOW_COPY_AND_ASSIGN(KioskProfileLoader);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::KioskProfileLoader;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_PROFILE_LOADER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.cc b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.cc
index b6c6a777..b5451cd 100644
--- a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.cc
+++ b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.cc
@@ -13,7 +13,7 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/app_mode/kiosk_session_plugin_handler_delegate.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -118,4 +118,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.h b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.h
index 7fbb281..bd75b09f 100644
--- a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.h
+++ b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler.h
@@ -20,7 +20,7 @@
 class WebContents;
 }
 
-namespace chromeos {
+namespace ash {
 
 class KioskSessionPluginHandlerDelegate;
 
@@ -72,6 +72,6 @@
   DISALLOW_COPY_AND_ASSIGN(KioskSessionPluginHandler);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_SESSION_PLUGIN_HANDLER_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_delegate.h b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_delegate.h
index 6e73595..aa91306 100644
--- a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_delegate.h
+++ b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_delegate.h
@@ -9,7 +9,7 @@
 
 #include "base/files/file_path.h"
 
-namespace chromeos {
+namespace ash {
 
 class KioskSessionPluginHandlerDelegate {
  public:
@@ -26,6 +26,6 @@
   virtual ~KioskSessionPluginHandlerDelegate() {}
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_SESSION_PLUGIN_HANDLER_DELEGATE_H_
diff --git a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_unittest.cc b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_unittest.cc
index 42c73a42..d091bd3 100644
--- a/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_unittest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_session_plugin_handler_unittest.cc
@@ -14,7 +14,7 @@
 using content::WebContents;
 using content::WebContentsObserver;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -149,4 +149,4 @@
   EXPECT_EQ(observer->GetHungPluginsForTesting().size(), 1U);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.cc b/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.cc
index a1656df..49f49dd 100644
--- a/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.cc
+++ b/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.cc
@@ -10,7 +10,7 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 // List of pages, which along with their subpages are considered whitelisted in
@@ -113,4 +113,4 @@
                                                               : CANCEL;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.h b/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.h
index 10f6d1e..e14d73a 100644
--- a/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.h
+++ b/chrome/browser/ash/app_mode/kiosk_settings_navigation_throttle.h
@@ -9,7 +9,7 @@
 
 #include "content/public/browser/navigation_throttle.h"
 
-namespace chromeos {
+namespace ash {
 
 // Throttle that is applied on WebContents which are opening settings pages
 // opened in kiosk mode. It restricts the navigationgs inside of these
@@ -40,6 +40,11 @@
   ThrottleCheckResult WillStartOrRedirectRequest();
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace chromeos {
+using ::ash::KioskSettingsNavigationThrottle;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_KIOSK_SETTINGS_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/ash/app_mode/pref_names.cc b/chrome/browser/ash/app_mode/pref_names.cc
index 4111637b..391f780 100644
--- a/chrome/browser/ash/app_mode/pref_names.cc
+++ b/chrome/browser/ash/app_mode/pref_names.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ash/app_mode/pref_names.h"
 
-namespace chromeos {
+namespace ash {
 namespace prefs {
 
 // Dictionary of kiosk cryptohomes scheduled to removed upon next startup.
@@ -24,4 +24,4 @@
 const char kArcKioskUsersToRemove[] = "arc-kiosk-users-to-remove";
 
 }  // namespace prefs
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/pref_names.h b/chrome/browser/ash/app_mode/pref_names.h
index d795d715..b7d631cb 100644
--- a/chrome/browser/ash/app_mode/pref_names.h
+++ b/chrome/browser/ash/app_mode/pref_names.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_APP_MODE_PREF_NAMES_H_
 #define CHROME_BROWSER_ASH_APP_MODE_PREF_NAMES_H_
 
-namespace chromeos {
+namespace ash {
 namespace prefs {
 
 // ---------------------------------------------------------------------------
@@ -16,5 +16,5 @@
 extern const char kArcKioskUsersToRemove[];
 
 }  // namespace prefs
-}  // namespace chromeos
+}  // namespace ash
 #endif  // CHROME_BROWSER_ASH_APP_MODE_PREF_NAMES_H_
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher.cc b/chrome/browser/ash/app_mode/startup_app_launcher.cc
index 8a3721e..ebafe69 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/startup_app_launcher.cc
@@ -41,7 +41,7 @@
 
 using extensions::Extension;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -557,4 +557,4 @@
   KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
 }
 
-}   // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher.h b/chrome/browser/ash/app_mode/startup_app_launcher.h
index 482162c..f8a9d1537 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher.h
+++ b/chrome/browser/ash/app_mode/startup_app_launcher.h
@@ -25,7 +25,7 @@
 class AppWindowRegistry;
 }
 
-namespace chromeos {
+namespace ash {
 
 class StartupAppLauncherUpdateChecker;
 
@@ -124,6 +124,12 @@
   DISALLOW_COPY_AND_ASSIGN(StartupAppLauncher);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// migration is finished.
+namespace chromeos {
+using ::ash::StartupAppLauncher;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_STARTUP_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
index c4467fc..d72a3c2 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
@@ -57,7 +57,7 @@
 using ::testing::AssertionResult;
 using ::testing::AssertionSuccess;
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -386,11 +386,11 @@
   }
 
   // KioskAppManager::Overrides:
-  std::unique_ptr<ExternalCache> CreateExternalCache(
-      ExternalCacheDelegate* delegate,
+  std::unique_ptr<chromeos::ExternalCache> CreateExternalCache(
+      chromeos::ExternalCacheDelegate* delegate,
       bool always_check_updates) override {
-    auto cache =
-        std::make_unique<TestExternalCache>(delegate, always_check_updates);
+    auto cache = std::make_unique<chromeos::TestExternalCache>(
+        delegate, always_check_updates);
     external_cache_ = cache.get();
     return cache;
   }
@@ -575,7 +575,7 @@
   std::unique_ptr<AppLaunchTracker> app_launch_tracker_;
   std::unique_ptr<TestKioskLoaderVisitor> external_apps_loader_handler_;
 
-  TestExternalCache* external_cache_ = nullptr;
+  chromeos::TestExternalCache* external_cache_ = nullptr;
 
   bool kiosk_app_session_initialized_ = false;
   session_manager::SessionManager session_manager_;
@@ -1282,4 +1282,4 @@
   EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtraSecondaryAppId));
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.cc b/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.cc
index 727978b..9bbed9d91 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.cc
+++ b/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.cc
@@ -15,7 +15,7 @@
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_system.h"
 
-namespace chromeos {
+namespace ash {
 
 StartupAppLauncherUpdateChecker::StartupAppLauncherUpdateChecker(
     Profile* profile)
@@ -74,4 +74,4 @@
   std::move(callback_).Run(update_found_);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.h b/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.h
index 383581ee3..bc214f7 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.h
+++ b/chrome/browser/ash/app_mode/startup_app_launcher_update_checker.h
@@ -13,7 +13,7 @@
 
 class Profile;
 
-namespace chromeos {
+namespace ash {
 
 // Used by StartupAppLauncher to check for available extension updates for
 // extensions other than the primary kiosk app - in particular for the secondary
@@ -56,6 +56,6 @@
   DISALLOW_COPY_AND_ASSIGN(StartupAppLauncherUpdateChecker);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_STARTUP_APP_LAUNCHER_UPDATE_CHECKER_H_
diff --git a/chrome/browser/ash/app_mode/test_kiosk_extension_builder.cc b/chrome/browser/ash/app_mode/test_kiosk_extension_builder.cc
index 4f6c1d3..01dc2151 100644
--- a/chrome/browser/ash/app_mode/test_kiosk_extension_builder.cc
+++ b/chrome/browser/ash/app_mode/test_kiosk_extension_builder.cc
@@ -17,7 +17,7 @@
 using extensions::ListBuilder;
 using extensions::ExtensionBuilder;
 
-namespace chromeos {
+namespace ash {
 
 TestKioskExtensionBuilder::TestKioskExtensionBuilder(
     extensions::Manifest::Type type,
@@ -90,4 +90,4 @@
       .Build();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/test_kiosk_extension_builder.h b/chrome/browser/ash/app_mode/test_kiosk_extension_builder.h
index a0e3d668..3fd2549 100644
--- a/chrome/browser/ash/app_mode/test_kiosk_extension_builder.h
+++ b/chrome/browser/ash/app_mode/test_kiosk_extension_builder.h
@@ -16,7 +16,7 @@
 class Extension;
 }
 
-namespace chromeos {
+namespace ash {
 
 // Wrapper around extensions::ExtensionBuilder for creating extension::Extension
 // instances for usage in kiosk app tests.
@@ -51,6 +51,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestKioskExtensionBuilder);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_TEST_KIOSK_EXTENSION_BUILDER_H_
diff --git a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc
index ab7d691..c70c1d0 100644
--- a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc
@@ -4,11 +4,11 @@
 
 #include <chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h>
 
-namespace chromeos {
+namespace ash {
 
 MockWebKioskAppLauncher::MockWebKioskAppLauncher()
     : WebKioskAppLauncher(nullptr, nullptr, EmptyAccountId()) {}
 
 MockWebKioskAppLauncher::~MockWebKioskAppLauncher() = default;
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h
index 618e36fd..77242dc 100644
--- a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h
@@ -9,7 +9,7 @@
 #include "components/account_id/account_id.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-namespace chromeos {
+namespace ash {
 
 class MockWebKioskAppLauncher : public WebKioskAppLauncher {
  public:
@@ -22,6 +22,12 @@
   MOCK_METHOD0(RestartLauncher, void());
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// migration is finished.
+namespace chromeos {
+using ::ash::MockWebKioskAppLauncher;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_MOCK_WEB_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
index 982adf1..6c0f297 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
@@ -20,7 +20,7 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "skia/ext/image_operations.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 constexpr int kIconSize = 128;  // size of the icon in px.
@@ -311,4 +311,4 @@
   // Do nothing
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
index 37a8fa2..78e8889 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
@@ -16,7 +16,7 @@
 
 struct WebApplicationInfo;
 
-namespace chromeos {
+namespace ash {
 
 class KioskAppDataDelegate;
 
@@ -81,6 +81,12 @@
   DISALLOW_COPY_AND_ASSIGN(WebKioskAppData);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace chromeos {
+using ::ash::WebKioskAppData;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_DATA_H_
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
index 62b2f183..c35d28d 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
@@ -18,7 +18,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -215,4 +215,4 @@
   EXPECT_EQ(app_data.name(), kAppTitle);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
index 1e34fe9..0af6319 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
@@ -24,7 +24,7 @@
 #include "ui/base/page_transition_types.h"
 #include "url/origin.h"
 
-namespace chromeos {
+namespace ash {
 
 WebKioskAppLauncher::WebKioskAppLauncher(
     Profile* profile,
@@ -145,4 +145,4 @@
   url_loader_ = std::move(url_loader);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
index 9a1852d..58177db 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
@@ -29,7 +29,7 @@
 class WebAppDataRetriever;
 }  // namespace web_app
 
-namespace chromeos {
+namespace ash {
 
 class WebKioskAppData;
 
@@ -85,6 +85,13 @@
   base::WeakPtrFactory<WebKioskAppLauncher> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(WebKioskAppLauncher);
 };
-}  // namespace chromeos
+
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// migration is finished.
+namespace chromeos {
+using ::ash::WebKioskAppLauncher;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
index 258686a..1aa18572 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
@@ -28,7 +28,7 @@
 using ::base::test::RunClosure;
 using ::testing::Return;
 
-namespace chromeos {
+namespace ash {
 
 class MockAppLauncherDelegate : public WebKioskAppLauncher::Delegate {
  public:
@@ -353,4 +353,4 @@
   CloseAppWindow();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
index 8ec2c07c..9743b6e 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
@@ -16,7 +16,7 @@
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/prefs/pref_registry_simple.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 // This class is owned by ChromeBrowserMainPartsChromeos.
@@ -167,4 +167,4 @@
   NotifyKioskAppsChanged();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
index bed900b..647b697fe 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
@@ -17,7 +17,7 @@
 class PrefRegistrySimple;
 struct WebApplicationInfo;
 
-namespace chromeos {
+namespace ash {
 
 // Does the management of web kiosk apps.
 class WebKioskAppManager : public KioskAppManagerBase {
@@ -68,6 +68,12 @@
   DISALLOW_COPY_AND_ASSIGN(WebKioskAppManager);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::WebKioskAppManager;
+}
 
 #endif  // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_WEB_KIOSK_APP_MANAGER_H_
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 5760877..a07f9892 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -42,6 +42,8 @@
         <!-- OOBE Components -->
         <structure name="IDR_OOBE_COMPONENTS_I18N_BEHAVIOR_HTML" file="resources/chromeos/login/components/oobe_i18n_behavior/oobe_i18n_behavior.html" type="chrome_html" />
         <structure name="IDR_OOBE_COMPONENTS_I18N_BEHAVIOR_JS" file="resources/chromeos/login/components/oobe_i18n_behavior/oobe_i18n_behavior.js" type="chrome_html" />
+        <structure name="IDR_OOBE_COMPONENTS_DIALOG_HOST_BEHAVIOR_HTML" file="resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.html" type="chrome_html" />
+        <structure name="IDR_OOBE_COMPONENTS_DIALOG_HOST_BEHAVIOR_JS" file="resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.js" type="chrome_html" />
         <structure name="IDR_OOBE_COMPONENTS_FOCUS_BEHAVIOR_HTML" file="resources/chromeos/login/components/oobe_focus_behavior/oobe_focus_behavior.html" type="chrome_html" />
         <structure name="IDR_OOBE_COMPONENTS_FOCUS_BEHAVIOR_JS" file="resources/chromeos/login/components/oobe_focus_behavior/oobe_focus_behavior.js" type="chrome_html" />
         <structure name="IDR_OOBE_COMPONENTS_SCROLLABLE_BEHAVIOR_HTML" file="resources/chromeos/login/components/oobe_scrollable_behavior/oobe_scrollable_behavior.html" type="chrome_html" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 788dab4..52b05c7 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4127,7 +4127,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   MaybeAddThrottle(
-      chromeos::KioskSettingsNavigationThrottle::MaybeCreateThrottleFor(handle),
+      ash::KioskSettingsNavigationThrottle::MaybeCreateThrottleFor(handle),
       &throttles);
 #endif
 
diff --git a/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc
index b0a8b2e..02576a2 100644
--- a/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc
+++ b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc
@@ -34,7 +34,7 @@
   friend base::DefaultSingletonTraits<ArcKioskBridgeFactory>;
 
   ArcKioskBridgeFactory() {
-    DependsOn(chromeos::ArcKioskAppServiceFactory::GetInstance());
+    DependsOn(ash::ArcKioskAppServiceFactory::GetInstance());
   }
   ~ArcKioskBridgeFactory() override = default;
 
@@ -67,8 +67,7 @@
 
 ArcKioskBridge::ArcKioskBridge(content::BrowserContext* context,
                                ArcBridgeService* bridge_service)
-    : ArcKioskBridge(bridge_service,
-                     chromeos::ArcKioskAppService::Get(context)) {}
+    : ArcKioskBridge(bridge_service, ash::ArcKioskAppService::Get(context)) {}
 
 ArcKioskBridge::ArcKioskBridge(ArcBridgeService* bridge_service,
                                Delegate* delegate)
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index a3d8a30..8408200 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -9,6 +9,12 @@
 
 #include "base/macros.h"
 #include "base/task/cancelable_task_tracker.h"
+// TODO(https://crbug.com/1164001): forward declare when moved to
+// chrome/browser/ash/.
+#include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
+// TODO(https://crbug.com/1164001): forward declare when moved to
+// chrome/browser/ash/.
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/chrome_browser_main_linux.h"
 #include "chrome/browser/chromeos/external_metrics.h"
 #include "chrome/browser/memory/memory_kills_monitor.h"
@@ -47,7 +53,6 @@
 
 namespace chromeos {
 
-class ArcKioskAppManager;
 class BulkPrintersCalculatorFactory;
 class CrosUsbDetector;
 class DemoModeResourcesRemover;
@@ -66,7 +71,6 @@
 class SessionTerminationManager;
 class ShutdownPolicyForwarder;
 class SystemTokenCertDBInitializer;
-class WebKioskAppManager;
 class WilcoDtcSupportdManager;
 
 namespace default_app_order {
diff --git a/chrome/browser/chromeos/login/auth/chrome_login_performer.h b/chrome/browser/chromeos/login/auth/chrome_login_performer.h
index 6e094ddf..53d1903 100644
--- a/chrome/browser/chromeos/login/auth/chrome_login_performer.h
+++ b/chrome/browser/chromeos/login/auth/chrome_login_performer.h
@@ -79,4 +79,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::ChromeLoginPerformer;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_CHROME_LOGIN_PERFORMER_H_
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
index 85a9be95..ec7f06a9 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
@@ -50,4 +50,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::DemoAppLauncher;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_APP_LAUNCHER_H_
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index f39050e7..a086cc54 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -30,6 +30,7 @@
 #include "base/version.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chrome_notification_types.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index 1c58f49..fb390985 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -22,6 +22,8 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
+// TODO(https://crbug.com/1164001): move KioskAppId to forward declaration
+// when moved to chrome/browser/ash/.
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/chromeos/login/saml/password_sync_token_checkers_collection.h"
 #include "chrome/browser/chromeos/login/screens/encryption_migration_mode.h"
@@ -51,7 +53,6 @@
 class CrosSettings;
 class LoginDisplay;
 class OAuth2TokenInitializer;
-class KioskAppId;
 
 namespace login {
 class NetworkStateHelper;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index a671dd11..bb741c2 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -38,7 +38,6 @@
 
 class Authenticator;
 class ExtendedAuthenticator;
-class AuthFailure;
 class ViewsScreenLocker;
 
 // ScreenLocker displays the lock UI and takes care of authenticating the user
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h
index ef1bfcd..fdeead3 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.h
+++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -641,6 +641,9 @@
 
 // TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
 // source migration is finished.
-using chromeos::UserSessionManager;
+namespace ash {
+using ::chromeos::UserSessionManager;
+using ::chromeos::UserSessionManagerDelegate;
+}  // namespace ash
 
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_USER_SESSION_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/test/kiosk_test_helpers.h b/chrome/browser/chromeos/login/test/kiosk_test_helpers.h
index bd61041c..f60a45f 100644
--- a/chrome/browser/chromeos/login/test/kiosk_test_helpers.h
+++ b/chrome/browser/chromeos/login/test/kiosk_test_helpers.h
@@ -73,4 +73,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using chromeos::KioskSessionInitializedWaiter;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_KIOSK_TEST_HELPERS_H_
diff --git a/chrome/browser/chromeos/login/ui/login_display_host.h b/chrome/browser/chromeos/login/ui/login_display_host.h
index b7c75b7..0dd175b 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host.h
@@ -13,6 +13,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list_types.h"
 #include "base/optional.h"
+// TODO(https://crbug.com/1164001): move KioskAppId to forward declaration
+// when moved to chrome/browser/ash/.
+#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/chromeos/customization/customization_document.h"
 #include "chrome/browser/chromeos/login/auth/auth_prewarmer.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
@@ -43,7 +46,6 @@
 class OobeUI;
 class WebUILoginView;
 class WizardController;
-class KioskAppId;
 
 // An interface that defines an out-of-box-experience (OOBE) or login screen
 // host. It contains code specific to the login UI implementation.
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
index d3e402a0..ac159ec 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -30,6 +30,7 @@
 #include "base/trace_event/trace_event.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
diff --git a/chrome/browser/chromeos/login/ui/login_web_dialog.h b/chrome/browser/chromeos/login/ui/login_web_dialog.h
index 55124ee2..31f3113 100644
--- a/chrome/browser/chromeos/login/ui/login_web_dialog.h
+++ b/chrome/browser/chromeos/login/ui/login_web_dialog.h
@@ -96,4 +96,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::LoginWebDialog;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_LOGIN_WEB_DIALOG_H_
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index c24c3f2..6420b7e6 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 9784317..e3a97fe0 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -18,6 +18,9 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
+// TODO(https://crbug.com/1164001): move KioskAppType to forward declaration
+// when moved to chrome/browser/ash/.
+#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
@@ -67,7 +70,6 @@
 class DemoSetupController;
 class ErrorScreen;
 struct Geoposition;
-enum class KioskAppType;
 class LoginDisplayHost;
 class SimpleGeolocationProvider;
 class TimeZoneProvider;
diff --git a/chrome/browser/chromeos/net/delay_network_call.h b/chrome/browser/chromeos/net/delay_network_call.h
index c26739a9..0e60bf6 100644
--- a/chrome/browser/chromeos/net/delay_network_call.h
+++ b/chrome/browser/chromeos/net/delay_network_call.h
@@ -25,4 +25,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using chromeos::DelayNetworkCall;
+using chromeos::kDefaultNetworkRetryDelayMS;
+}  // namespace ash
+
 #endif  // CHROME_BROWSER_CHROMEOS_NET_DELAY_NETWORK_CALL_H_
diff --git a/chrome/browser/chromeos/ownership/fake_owner_settings_service.h b/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
index 552e399..d161718a 100644
--- a/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
+++ b/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
@@ -52,4 +52,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::FakeOwnerSettingsService;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_OWNERSHIP_FAKE_OWNER_SETTINGS_SERVICE_H_
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
index e818ace..5dc0881 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
@@ -200,4 +200,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::OwnerSettingsServiceChromeOS;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_CHROMEOS_H_
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
index 2854bdb8..52b39bda 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
@@ -67,4 +67,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::OwnerSettingsServiceChromeOSFactory;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_CHROMEOS_FACTORY_H_
diff --git a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc
index 62871a1..baec5cf9 100644
--- a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc
+++ b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc
@@ -116,17 +116,17 @@
     return false;
 
   if (user_manager->IsLoggedInAsKioskApp()) {
-    chromeos::KioskAppManager* manager = chromeos::KioskAppManager::Get();
+    ash::KioskAppManager* manager = ash::KioskAppManager::Get();
     if (manager->GetAutoLaunchApp().empty())
       return false;
-    chromeos::KioskAppManager::App app;
+    ash::KioskAppManager::App app;
     CHECK(manager->GetApp(manager->GetAutoLaunchApp(), &app));
     return app.was_auto_launched_with_zero_delay;
   } else if (user_manager->IsLoggedInAsArcKioskApp()) {
     return chromeos::ArcKioskAppManager::Get()
         ->current_app_was_auto_launched_with_zero_delay();
   } else if (user_manager->IsLoggedInAsWebKioskApp()) {
-    return chromeos::WebKioskAppManager::Get()
+    return ash::WebKioskAppManager::Get()
         ->current_app_was_auto_launched_with_zero_delay();
   }
   NOTREACHED();
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
index e1c5ea8..9078c9be 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -2302,8 +2302,7 @@
     return false;
 
   const std::string required_platform_version_string =
-      chromeos::KioskAppManager::Get()
-          ->GetAutoLaunchAppRequiredPlatformVersion();
+      ash::KioskAppManager::Get()->GetAutoLaunchAppRequiredPlatformVersion();
   em::OsUpdateStatus* os_update_status = status->mutable_os_update_status();
 
   const update_engine::StatusResult update_engine_status =
@@ -2400,9 +2399,8 @@
       running_kiosk_app->set_extension_version(app_version);
     }
 
-    chromeos::KioskAppManager::App app_info;
-    if (chromeos::KioskAppManager::Get()->GetApp(account->kiosk_app_id,
-                                                 &app_info)) {
+    ash::KioskAppManager::App app_info;
+    if (ash::KioskAppManager::Get()->GetApp(account->kiosk_app_id, &app_info)) {
       running_kiosk_app->set_required_platform_version(
           app_info.required_platform_version);
     }
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index bd04b93..9757d28 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -829,7 +829,7 @@
 
     // Set up a fake local state for KioskAppManager and KioskCryptohomeRemover.
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
-    chromeos::KioskAppManager::RegisterPrefs(local_state_.registry());
+    ash::KioskAppManager::RegisterPrefs(local_state_.registry());
     chromeos::KioskCryptohomeRemover::RegisterPrefs(local_state_.registry());
 
     // Use FakeUpdateEngineClient.
@@ -853,7 +853,7 @@
     chromeos::PowerManagerClient::Shutdown();
     chromeos::CryptohomeClient::Shutdown();
     chromeos::CrasAudioHandler::Shutdown();
-    chromeos::KioskAppManager::Shutdown();
+    ash::KioskAppManager::Shutdown();
     TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
 
     // Finish pending tasks.
@@ -1012,7 +1012,7 @@
   void MockAutoLaunchKioskAppWithRequiredPlatformVersion(
       const DeviceLocalAccount& auto_launch_app_account,
       const std::string& required_platform_version) {
-    chromeos::KioskAppManager* manager = chromeos::KioskAppManager::Get();
+    ash::KioskAppManager* manager = ash::KioskAppManager::Get();
     manager->AddAppForTest(
         auto_launch_app_account.kiosk_app_id,
         AccountId::FromUserEmail(auto_launch_app_account.user_id),
@@ -1055,7 +1055,7 @@
 
   void MockAutoLaunchWebKioskApp(
       const DeviceLocalAccount& auto_launch_app_account) {
-    web_kiosk_app_manager_.reset(new chromeos::WebKioskAppManager());
+    web_kiosk_app_manager_ = std::make_unique<ash::WebKioskAppManager>();
     web_kiosk_app_manager_->AddAppForTesting(
         AccountId::FromUserEmail(auto_launch_app_account.user_id),
         GURL(auto_launch_app_account.web_kiosk_app_info.url()));
@@ -1096,7 +1096,7 @@
   // Only set after MockAutoLaunchArcKioskApp was called.
   std::unique_ptr<chromeos::ArcKioskAppManager> arc_kiosk_app_manager_;
   // Only set after MockAutoLaunchWebKioskApp was called.
-  std::unique_ptr<chromeos::WebKioskAppManager> web_kiosk_app_manager_;
+  std::unique_ptr<ash::WebKioskAppManager> web_kiosk_app_manager_;
   chromeos::MockUserManager* const user_manager_;
   user_manager::ScopedUserManager user_manager_enabler_;
   em::DeviceStatusReportRequest device_status_;
diff --git a/chrome/browser/chromeos/policy/status_collector/status_collector.cc b/chrome/browser/chromeos/policy/status_collector/status_collector.cc
index 7efe46d8..03773bd0 100644
--- a/chrome/browser/chromeos/policy/status_collector/status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/status_collector.cc
@@ -119,17 +119,17 @@
     return nullptr;
   }
 
-  chromeos::KioskAppManager::App current_app;
+  ash::KioskAppManager::App current_app;
   bool regular_app_auto_launched_with_zero_delay =
-      chromeos::KioskAppManager::Get()->GetApp(account->kiosk_app_id,
-                                               &current_app) &&
+      ash::KioskAppManager::Get()->GetApp(account->kiosk_app_id,
+                                          &current_app) &&
       current_app.was_auto_launched_with_zero_delay;
   bool arc_app_auto_launched_with_zero_delay =
       chromeos::ArcKioskAppManager::Get()
           ->current_app_was_auto_launched_with_zero_delay();
 
   bool web_app_auto_launched_with_zero_delay =
-      chromeos::WebKioskAppManager::Get()
+      ash::WebKioskAppManager::Get()
           ->current_app_was_auto_launched_with_zero_delay();
 
   return regular_app_auto_launched_with_zero_delay ||
diff --git a/chrome/browser/chromeos/scanning/scan_service.cc b/chrome/browser/chromeos/scanning/scan_service.cc
index aa3627b..c496342 100644
--- a/chrome/browser/chromeos/scanning/scan_service.cc
+++ b/chrome/browser/chromeos/scanning/scan_service.cc
@@ -125,7 +125,7 @@
     LOG(ERROR) << "Unable to access PDF page canvas.";
     return false;
   }
-  page_canvas->drawBitmap(img_bitmap, /*left=*/0, /*top=*/0);
+  page_canvas->drawImage(img_bitmap.asImage(), /*left=*/0, /*top=*/0);
   pdf_doc->endPage();
   return true;
 }
diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h
index b58ece5..da17cd7d 100644
--- a/chrome/browser/chromeos/settings/cros_settings.h
+++ b/chrome/browser/chromeos/settings/cros_settings.h
@@ -167,4 +167,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::CrosSettings;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_SETTINGS_CROS_SETTINGS_H_
diff --git a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
index bd9e6b8..e162bb7 100644
--- a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
+++ b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
@@ -100,4 +100,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::ScopedCrosSettingsTestHelper;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_SETTINGS_SCOPED_CROS_SETTINGS_TEST_HELPER_H_
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.h b/chrome/browser/chromeos/system/automatic_reboot_manager.h
index 1a5fa47..34448e6 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.h
@@ -190,4 +190,11 @@
 }  // namespace system
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+namespace system {
+using ::chromeos::system::AutomaticRebootManager;
+}
+}  // namespace ash
+
 #endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_H_
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
index 0a750bc..6ad9774 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
@@ -29,4 +29,11 @@
 }  // namespace system
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+namespace system {
+using ::chromeos::system::AutomaticRebootManagerObserver;
+}
+}  // namespace ash
+
 #endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/chromeos/ui/idle_app_name_notification_view.h b/chrome/browser/chromeos/ui/idle_app_name_notification_view.h
index 494d2f9..ee677093 100644
--- a/chrome/browser/chromeos/ui/idle_app_name_notification_view.h
+++ b/chrome/browser/chromeos/ui/idle_app_name_notification_view.h
@@ -53,4 +53,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
+namespace ash {
+using ::chromeos::IdleAppNameNotificationView;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_UI_IDLE_APP_NAME_NOTIFICATION_VIEW_H_
diff --git a/chrome/browser/chromeos/ui/kiosk_external_update_notification.h b/chrome/browser/chromeos/ui/kiosk_external_update_notification.h
index e8e3acb3..fdbda44 100644
--- a/chrome/browser/chromeos/ui/kiosk_external_update_notification.h
+++ b/chrome/browser/chromeos/ui/kiosk_external_update_notification.h
@@ -32,4 +32,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when migrated to
+// chrome/browser/ash/.
+namespace ash {
+using ::chromeos::KioskExternalUpdateNotification;
+}
+
 #endif  // CHROME_BROWSER_CHROMEOS_UI_KIOSK_EXTERNAL_UPDATE_NOTIFICATION_H_
diff --git a/chrome/browser/devtools/devtools_eye_dropper.cc b/chrome/browser/devtools/devtools_eye_dropper.cc
index 6aa52f0..e72796e 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.cc
+++ b/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -226,7 +226,9 @@
                                      last_cursor_y_ - pixel_count / 2,
                                      pixel_count, pixel_count);
   SkRect dst_rect = SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter);
-  canvas.drawBitmapRect(frame_, src_rect, dst_rect, NULL);
+  canvas.drawImageRect(frame_.asImage(), src_rect, dst_rect,
+                       SkSamplingOptions(), nullptr,
+                       SkCanvas::kStrict_SrcRectConstraint);
 
   // Paint grid.
   paint.setStrokeWidth(1);
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index ec3593e..b847cd3 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -118,12 +118,12 @@
   SkBitmap container_bitmap;
   container_bitmap.allocN32Pixels(container_size.width(),
                                   container_size.height());
-  SkPaint paint;
-  paint.setFilterQuality(kHigh_SkFilterQuality);
+  SkSamplingOptions sampling({1.0f / 3, 1.0f / 3});
   SkCanvas container_image(container_bitmap);
   container_image.drawColor(kImageBackgroundColor);
-  container_image.drawBitmapRect(
-      original_bitmap, source_rect, SkRect::MakeSize(container_size), &paint);
+  container_image.drawImageRect(original_bitmap.asImage(), source_rect,
+                                SkRect::MakeSize(container_size), sampling,
+                                nullptr, SkCanvas::kStrict_SrcRectConstraint);
 
   return container_bitmap;
 }
diff --git a/chrome/browser/enterprise/connectors/connectors_prefs.cc b/chrome/browser/enterprise/connectors/connectors_prefs.cc
index e14aa40a..eaed2905 100644
--- a/chrome/browser/enterprise/connectors/connectors_prefs.cc
+++ b/chrome/browser/enterprise/connectors/connectors_prefs.cc
@@ -8,6 +8,9 @@
 
 namespace enterprise_connectors {
 
+const char kSendDownloadToCloudPref[] =
+    "enterprise_connectors.send_download_to_cloud";
+
 const char kOnFileAttachedPref[] = "enterprise_connectors.on_file_attached";
 
 const char kOnFileDownloadedPref[] = "enterprise_connectors.on_file_downloaded";
@@ -32,6 +35,7 @@
     "enterprise_connectors.file_system.box.refresh_token";
 
 void RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterListPref(kSendDownloadToCloudPref);
   registry->RegisterListPref(kOnFileAttachedPref);
   registry->RegisterListPref(kOnFileDownloadedPref);
   registry->RegisterListPref(kOnBulkDataEntryPref);
diff --git a/chrome/browser/enterprise/connectors/connectors_prefs.h b/chrome/browser/enterprise/connectors/connectors_prefs.h
index e2b8ede..ef5afb5 100644
--- a/chrome/browser/enterprise/connectors/connectors_prefs.h
+++ b/chrome/browser/enterprise/connectors/connectors_prefs.h
@@ -9,6 +9,9 @@
 
 namespace enterprise_connectors {
 
+// Pref that maps to the "SendDownloadToCloudEnterpriseConnector" policy.
+extern const char kSendDownloadToCloudPref[];
+
 // Pref that maps to the "OnFileAttachedEnterpriseConnector" policy.
 extern const char kOnFileAttachedPref[];
 
diff --git a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.cc b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.cc
index f57dd48..996d6ab 100644
--- a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.cc
+++ b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.cc
@@ -16,6 +16,15 @@
 EnterpriseConnectorsPolicyHandler::EnterpriseConnectorsPolicyHandler(
     const char* policy_name,
     const char* pref_path,
+    policy::Schema schema)
+    : EnterpriseConnectorsPolicyHandler(policy_name,
+                                        pref_path,
+                                        nullptr,
+                                        schema) {}
+
+EnterpriseConnectorsPolicyHandler::EnterpriseConnectorsPolicyHandler(
+    const char* policy_name,
+    const char* pref_path,
     const char* pref_scope_path,
     policy::Schema schema)
     : SchemaValidatingPolicyHandler(
@@ -48,7 +57,7 @@
 void EnterpriseConnectorsPolicyHandler::ApplyPolicySettings(
     const policy::PolicyMap& policies,
     PrefValueMap* prefs) {
-  if (!pref_path_ || !pref_scope_path_)
+  if (!pref_path_)
     return;
 
   const policy::PolicyMap::Entry* policy = policies.Get(policy_name());
@@ -58,7 +67,9 @@
   const base::Value* value = policy->value();
   if (value) {
     prefs->SetValue(pref_path_, value->Clone());
-    prefs->SetInteger(pref_scope_path_, policy->scope);
+
+    if (pref_scope_path_)
+      prefs->SetInteger(pref_scope_path_, policy->scope);
   }
 }
 
diff --git a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.h b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.h
index 267b2a9..24a7dab6 100644
--- a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.h
+++ b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.h
@@ -16,6 +16,9 @@
  public:
   EnterpriseConnectorsPolicyHandler(const char* policy_name,
                                     const char* pref_path,
+                                    policy::Schema schema);
+  EnterpriseConnectorsPolicyHandler(const char* policy_name,
+                                    const char* pref_path,
                                     const char* pref_scope_path,
                                     policy::Schema schema);
   EnterpriseConnectorsPolicyHandler(EnterpriseConnectorsPolicyHandler&) =
@@ -34,7 +37,7 @@
   const char* pref_path_;
 
   // Key used to store the policy::PolicyScope of the policy. This is looked up
-  // later so the Connector can adjust its behaviour.
+  // later so the Connector can adjust its behaviour.  May be null.
   const char* pref_scope_path_;
 };
 
diff --git a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler_unittest.cc b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler_unittest.cc
index 06930802..bb2877a 100644
--- a/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler_unittest.cc
+++ b/chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler_unittest.cc
@@ -75,11 +75,13 @@
 
 class EnterpriseConnectorsPolicyHandlerTest
     : public testing::TestWithParam<
-          std::tuple<const char*, policy::PolicySource>> {
+          std::tuple<const char*, const char*, policy::PolicySource>> {
  public:
-  const char* policy() const { return std::get<0>(GetParam()); }
+  const char* policy_scope() const { return std::get<0>(GetParam()); }
 
-  policy::PolicySource source() const { return std::get<1>(GetParam()); }
+  const char* policy() const { return std::get<1>(GetParam()); }
+
+  policy::PolicySource source() const { return std::get<2>(GetParam()); }
 
   bool expect_valid_policy() const {
     if (policy() == kEmptyPolicy)
@@ -108,7 +110,7 @@
   }
 
   auto handler = std::make_unique<EnterpriseConnectorsPolicyHandler>(
-      kPolicyName, kTestPref, kTestScopePref, validation_schema);
+      kPolicyName, kTestPref, policy_scope(), validation_schema);
   policy::PolicyErrorMap errors;
   ASSERT_EQ(expect_valid_policy(),
             handler->CheckPolicySettings(policy_map, &errors));
@@ -124,15 +126,18 @@
 
   bool policy_is_set = policy() != kEmptyPolicy;
   ASSERT_EQ(policy_is_set, prefs.GetValue(kTestPref, &value_set_in_pref));
-  EXPECT_EQ(policy_is_set, prefs.GetInteger(kTestScopePref, &pref_scope));
+  if (policy_scope())
+    EXPECT_EQ(policy_is_set, prefs.GetInteger(policy_scope(), &pref_scope));
 
   auto* value_set_in_map = policy_map.GetValue(kPolicyName);
   if (value_set_in_map) {
     ASSERT_TRUE(value_set_in_map->Equals(value_set_in_pref));
-    ASSERT_EQ(policy::POLICY_SCOPE_MACHINE, pref_scope);
+    if (policy_scope())
+      ASSERT_EQ(policy::POLICY_SCOPE_MACHINE, pref_scope);
   } else {
     ASSERT_FALSE(policy_is_set);
-    ASSERT_EQ(-1, pref_scope);
+    if (policy_scope())
+      ASSERT_EQ(-1, pref_scope);
   }
 }
 
@@ -140,6 +145,7 @@
     EnterpriseConnectorsPolicyHandlerTest,
     EnterpriseConnectorsPolicyHandlerTest,
     testing::Combine(
+        testing::Values(kTestScopePref, nullptr),
         testing::Values(kValidPolicy, kInvalidPolicy, kEmptyPolicy),
         testing::Values(policy::PolicySource::POLICY_SOURCE_CLOUD,
                         policy::PolicySource::POLICY_SOURCE_PRIORITY_CLOUD,
diff --git a/chrome/browser/enterprise/connectors/fake_content_analysis_delegate.h b/chrome/browser/enterprise/connectors/fake_content_analysis_delegate.h
index fdd4f35f..58f31b5 100644
--- a/chrome/browser/enterprise/connectors/fake_content_analysis_delegate.h
+++ b/chrome/browser/enterprise/connectors/fake_content_analysis_delegate.h
@@ -49,7 +49,7 @@
 
   // Use with ContentAnalysisDelegate::SetFactoryForTesting() to create
   // fake instances of this class.  Note that all but the last three arguments
-  // will need to be bound at base::Bind() time.
+  // will need to be bound at base::BindRepeating() time.
   static std::unique_ptr<ContentAnalysisDelegate> Create(
       base::RepeatingClosure delete_closure,
       StatusCallback status_callback,
diff --git a/chrome/browser/extensions/active_tab_unittest.cc b/chrome/browser/extensions/active_tab_unittest.cc
index 8b42d8d..accba2b 100644
--- a/chrome/browser/extensions/active_tab_unittest.cc
+++ b/chrome/browser/extensions/active_tab_unittest.cc
@@ -152,7 +152,7 @@
 
   void TearDown() override {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-    chromeos::KioskAppManager::Shutdown();
+    ash::KioskAppManager::Shutdown();
 #endif
     ChromeRenderViewHostTestHarness::TearDown();
   }
diff --git a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
index 345970f..c7a48dc 100644
--- a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
@@ -64,9 +64,7 @@
     manager()->SetAppWasAutoLaunchedWithZeroDelay(kTestingAppId);
   }
 
-  chromeos::KioskAppManager* manager() const {
-    return chromeos::KioskAppManager::Get();
-  }
+  ash::KioskAppManager* manager() const { return ash::KioskAppManager::Get(); }
 
   chromeos::FakeChromeUserManager* fake_user_manager_;
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
diff --git a/chrome/browser/extensions/api/file_system/consent_provider.cc b/chrome/browser/extensions/api/file_system/consent_provider.cc
index 502e3f5..76bcf2f 100644
--- a/chrome/browser/extensions/api/file_system/consent_provider.cc
+++ b/chrome/browser/extensions/api/file_system/consent_provider.cc
@@ -240,8 +240,8 @@
 }
 
 bool ConsentProviderDelegate::IsAutoLaunched(const Extension& extension) {
-  chromeos::KioskAppManager::App app_info;
-  return chromeos::KioskAppManager::Get()->GetApp(extension.id(), &app_info) &&
+  ash::KioskAppManager::App app_info;
+  return ash::KioskAppManager::Get()->GetApp(extension.id(), &app_info) &&
          app_info.was_auto_launched_with_zero_delay;
 }
 
diff --git a/chrome/browser/extensions/autoplay_browsertest.cc b/chrome/browser/extensions/autoplay_browsertest.cc
index e0f097c5..84a04d8 100644
--- a/chrome/browser/extensions/autoplay_browsertest.cc
+++ b/chrome/browser/extensions/autoplay_browsertest.cc
@@ -40,7 +40,8 @@
 #else
 #define MAYBE_AutoplayAllowedInIframe AutoplayAllowedInIframe
 #endif  // defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
-IN_PROC_BROWSER_TEST_F(AutoplayExtensionBrowserTest, AutoplayAllowedInIframe) {
+IN_PROC_BROWSER_TEST_F(AutoplayExtensionBrowserTest,
+                       MAYBE_AutoplayAllowedInIframe) {
   ASSERT_TRUE(StartEmbeddedTestServer());
 
   const extensions::Extension* extension =
diff --git a/chrome/browser/extensions/chrome_kiosk_delegate_chromeos.cc b/chrome/browser/extensions/chrome_kiosk_delegate_chromeos.cc
index 3818e33..814695c 100644
--- a/chrome/browser/extensions/chrome_kiosk_delegate_chromeos.cc
+++ b/chrome/browser/extensions/chrome_kiosk_delegate_chromeos.cc
@@ -13,8 +13,8 @@
 ChromeKioskDelegate::~ChromeKioskDelegate() {}
 
 bool ChromeKioskDelegate::IsAutoLaunchedKioskApp(const ExtensionId& id) const {
-  chromeos::KioskAppManager::App app_info;
-  return chromeos::KioskAppManager::Get()->GetApp(id, &app_info) &&
+  ash::KioskAppManager::App app_info;
+  return ash::KioskAppManager::Get()->GetApp(id, &app_info) &&
          app_info.was_auto_launched_with_zero_delay;
 }
 
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index 780f5d7..5066878 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -410,10 +410,10 @@
   }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  // The KioskAppManager, if initialized, needs to be cleaned up.
+  // The ash::KioskAppManager, if initialized, needs to be cleaned up.
   // TODO(devlin): This should probably go somewhere more central, like
   // chromeos::ScopedCrosSettingsTestHelper.
-  chromeos::KioskAppManager::Shutdown();
+  ash::KioskAppManager::Shutdown();
 #endif
 
   ExtensionServiceTestBase::TearDown();
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index bea21a0..df51f89 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -176,8 +176,8 @@
       extension_service_->shared_module_service());
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chrome::IsRunningInForcedAppMode()) {
-    kiosk_app_update_install_gate_.reset(
-        new chromeos::KioskAppUpdateInstallGate(profile_));
+    kiosk_app_update_install_gate_ =
+        std::make_unique<ash::KioskAppUpdateInstallGate>(profile_);
     extension_service_->RegisterInstallGate(
         ExtensionPrefs::DELAY_REASON_WAIT_FOR_OS_UPDATE,
         kiosk_app_update_install_gate_.get());
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 833c30c..8128e52 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -681,8 +681,8 @@
 
       auto kiosk_app_provider = std::make_unique<ExternalProviderImpl>(
           service,
-          base::MakeRefCounted<chromeos::KioskAppExternalLoader>(
-              chromeos::KioskAppExternalLoader::AppClass::kPrimary),
+          base::MakeRefCounted<ash::KioskAppExternalLoader>(
+              ash::KioskAppExternalLoader::AppClass::kPrimary),
           profile, location, Manifest::INVALID_LOCATION, Extension::NO_FLAGS);
       kiosk_app_provider->set_auto_acknowledge(true);
       kiosk_app_provider->set_install_immediately(true);
@@ -693,8 +693,8 @@
       auto secondary_kiosk_app_provider =
           std::make_unique<ExternalProviderImpl>(
               service,
-              base::MakeRefCounted<chromeos::KioskAppExternalLoader>(
-                  chromeos::KioskAppExternalLoader::AppClass::kSecondary),
+              base::MakeRefCounted<ash::KioskAppExternalLoader>(
+                  ash::KioskAppExternalLoader::AppClass::kSecondary),
               profile, Manifest::EXTERNAL_PREF,
               Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS);
       secondary_kiosk_app_provider->set_auto_acknowledge(true);
diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
index 31ba806..2512b81 100644
--- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
@@ -102,7 +102,7 @@
     // finish cleanly).
     // So ensure we let pending extension installations finish.
     WaitForPendingStandaloneExtensionsInstalled();
-    chromeos::KioskAppManager::Shutdown();
+    ash::KioskAppManager::Shutdown();
     ExtensionServiceTestBase::TearDown();
   }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index d938783..8da2245 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1587,6 +1587,11 @@
     "expiry_milestone": 87
   },
   {
+    "name": "enable-experimental-accessibility-dictation-extension",
+    "owners": [ "akihiroota" ],
+    "expiry_milestone": 92
+  },
+  {
     "name": "enable-experimental-accessibility-labels",
     "owners": [ "dmazzoni", "mschillaci" ],
     "expiry_milestone": 99
@@ -4861,6 +4866,11 @@
     "expiry_milestone": 89
   },
   {
+    "name": "ui-debug-tools",
+    "owners": [ "//ui/views/OWNERS" ],
+    "expiry_milestone": -1
+  },
+  {
     "name": "ui-disable-partial-swap",
     "owners": [ "//components/viz/OWNERS" ],
     // This flag is used for in-the-field debugging of rendering issues,
@@ -4926,7 +4936,7 @@
   {
     "name": "use-chime-android-sdk",
     "owners": [ "xingliu" ],
-    "expiry_milestone": 89
+    "expiry_milestone": 95
   },
   {
     "name": "use-custom-messages-domain",
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json
index 74a8751..d2796a4 100644
--- a/chrome/browser/flag-never-expire-list.json
+++ b/chrome/browser/flag-never-expire-list.json
@@ -93,6 +93,7 @@
   "show-touch-hud",
   "tint-composited-content",
   "top-chrome-touch-ui",
+  "ui-debug-tools",
   "ui-disable-partial-swap",
   "ui-slow-animations",
   "unsafely-treat-insecure-origin-as-secure",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 4bff9552e..47739dc 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4272,6 +4272,11 @@
 const char kExperimentalAccessibilityChromeVoxAnnotationsDescription[] =
     "Allows users to create custom annotations for elements using ChromeVox.";
 
+const char kExperimentalAccessibilityDictationExtensionName[] =
+    "Experimental accessibility dictation extension.";
+const char kExperimentalAccessibilityDictationExtensionDescription[] =
+    "Enables the JavaScript dictation extension.";
+
 const char kExperimentalAccessibilitySwitchAccessTextName[] =
     "Enable enhanced Switch Access text input.";
 const char kExperimentalAccessibilitySwitchAccessTextDescription[] =
@@ -4989,6 +4994,13 @@
     "will be sent to Google.";
 #endif
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC)
+const char kUIDebugToolsName[] = "Debugging tools for UI";
+const char kUIDebugToolsDescription[] =
+    "Enables additional keyboard shortcuts to help debugging.";
+#endif
+
 #if defined(WEBRTC_USE_PIPEWIRE)
 const char kWebrtcPipeWireCapturerName[] = "WebRTC PipeWire support";
 const char kWebrtcPipeWireCapturerDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 9889284..8ffa179 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2496,6 +2496,9 @@
 extern const char kExperimentalAccessibilityChromeVoxTutorialName[];
 extern const char kExperimentalAccessibilityChromeVoxTutorialDescription[];
 
+extern const char kExperimentalAccessibilityDictationExtensionName[];
+extern const char kExperimentalAccessibilityDictationExtensionDescription[];
+
 extern const char kExperimentalAccessibilitySwitchAccessTextName[];
 extern const char kExperimentalAccessibilitySwitchAccessTextDescription[];
 
@@ -2929,6 +2932,12 @@
 extern const char kSendWebUIJavaScriptErrorReportsDescription[];
 #endif
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC)
+extern const char kUIDebugToolsName[];
+extern const char kUIDebugToolsDescription[];
+#endif
+
 #if defined(WEBRTC_USE_PIPEWIRE)
 extern const char kWebrtcPipeWireCapturerName[];
 extern const char kWebrtcPipeWireCapturerDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 74ad937..043ad0e 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -197,6 +197,7 @@
     &kOfflineIndicatorV2,
     &kOfflineMeasurementsBackgroundTask,
     &kOmniboxSpareRenderer,
+    &kPageAnnotationsService,
     &kProbabilisticCryptidRenderer,
     &kReachedCodeProfiler,
     &kReaderModeInCCT,
@@ -557,6 +558,9 @@
 const base::Feature kOmniboxSpareRenderer{"OmniboxSpareRenderer",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kPageAnnotationsService{"PageAnnotationsService",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kProbabilisticCryptidRenderer{
     "ProbabilisticCryptidRenderer", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 6f5e62f..5d6898c 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -94,6 +94,7 @@
 extern const base::Feature kOfflineIndicatorV2;
 extern const base::Feature kOfflineMeasurementsBackgroundTask;
 extern const base::Feature kOmniboxSpareRenderer;
+extern const base::Feature kPageAnnotationsService;
 extern const base::Feature kProbabilisticCryptidRenderer;
 extern const base::Feature kReachedCodeProfiler;
 extern const base::Feature kReengagementNotification;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index b3c190a..3913d4c 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -374,6 +374,7 @@
     public static final String OMNIBOX_SEARCH_READY_INCOGNITO = "OmniboxSearchReadyIncognito";
     public static final String OMNIBOX_SPARE_RENDERER = "OmniboxSpareRenderer";
     public static final String OVERLAY_NEW_LAYOUT = "OverlayNewLayout";
+    public static final String PAGE_ANNOTATIONS_SERVICE = "PageAnnotationsService";
     public static final String PAGE_INFO_PERFORMANCE_HINTS = "PageInfoPerformanceHints";
     public static final String PAINT_PREVIEW_DEMO = "PaintPreviewDemo";
     public static final String PAINT_PREVIEW_SHOW_ON_STARTUP = "PaintPreviewShowOnStartup";
diff --git a/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc b/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc
index 8b36867..1cf678c 100644
--- a/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc
+++ b/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc
@@ -34,8 +34,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Notifies kiosk session about the added guest.
-  chromeos::AppSession* app_session =
-      chromeos::KioskAppManager::Get()->app_session();
+  ash::AppSession* app_session = ash::KioskAppManager::Get()->app_session();
   if (app_session)
     app_session->OnGuestAdded(guest_web_contents);
 #endif
diff --git a/chrome/browser/lite_video/lite_video_keyed_service_browsertest.cc b/chrome/browser/lite_video/lite_video_keyed_service_browsertest.cc
index d16dde2..1b20da8 100644
--- a/chrome/browser/lite_video/lite_video_keyed_service_browsertest.cc
+++ b/chrome/browser/lite_video/lite_video_keyed_service_browsertest.cc
@@ -495,8 +495,18 @@
           lite_video::LiteVideoThrottleResult::kThrottledWithoutStop));
 }
 
+#if defined(OS_MAC)
+// Flaky on Mac, and in any case the feature under test is not used on Mac:
+// https://crbug.com/1172472
+#define MAYBE_MultipleNavigationsNotBlocklisted \
+  DISABLED_MultipleNavigationsNotBlocklisted
+#else
+#define MAYBE_MultipleNavigationsNotBlocklisted \
+  MultipleNavigationsNotBlocklisted
+#endif
+
 IN_PROC_BROWSER_TEST_P(LiteVideoKeyedServiceBrowserTest,
-                       MultipleNavigationsNotBlocklisted) {
+                       MAYBE_MultipleNavigationsNotBlocklisted) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
   WaitForBlocklistToBeLoaded();
   EXPECT_TRUE(
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list.cc b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
index 44895261..676e99c 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
@@ -52,7 +52,8 @@
   SkRect dest_rect =
       SkRect::MakeLTRB(center_rect.x(), center_rect.y(), center_rect.right(),
                        center_rect.bottom());
-  canvas.drawBitmapRect(*favicon.bitmap(), dest_rect, nullptr);
+  canvas.drawImageRect(favicon.bitmap()->asImage(), dest_rect,
+                       SkSamplingOptions());
 
   return gfx::ImageSkia::CreateFrom1xBitmap(result);
 }
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index aa28946..29db40b 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -523,13 +523,14 @@
                           this, ConnectionInitializationStatusCode::SUCCESS));
     notification_proxy_->ConnectToSignal(
         kFreedesktopNotificationsName, kSignalActionInvoked,
-        base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
+        base::BindRepeating(
+            &NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
         base::BindOnce(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
                        this));
     notification_proxy_->ConnectToSignal(
         kFreedesktopNotificationsName, kSignalNotificationClosed,
-        base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed,
-                   this),
+        base::BindRepeating(
+            &NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, this),
         base::BindOnce(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
                        this));
   }
@@ -1020,7 +1021,7 @@
     if (!product_logo_file_watcher_->Watch(
             product_logo_file_->file_path(),
             base::FilePathWatcher::Type::kNonRecursive,
-            base::Bind(
+            base::BindRepeating(
                 &NotificationPlatformBridgeLinuxImpl::OnProductLogoFileChanged,
                 this))) {
       product_logo_file_.reset();
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm b/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
index 8a174f8a..29418341 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
@@ -295,7 +295,7 @@
 
   int notification_count = -1;
   bridge->GetDisplayed(
-      profile(), base::Bind(&StoreNotificationCount, &notification_count));
+      profile(), base::BindOnce(&StoreNotificationCount, &notification_count));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, notification_count);
 }
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac_utils.mm b/chrome/browser/notifications/notification_platform_bridge_mac_utils.mm
index c6c1ca3..88e8cdf2 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac_utils.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac_utils.mm
@@ -51,9 +51,9 @@
 
   profileManager->LoadProfile(
       profileId, incognito,
-      base::Bind(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
-                 operation, type, origin, notificationId, actionIndex, reply,
-                 byUser));
+      base::BindOnce(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
+                     operation, type, origin, notificationId, actionIndex,
+                     reply, byUser));
 }
 
 // Implements the version check to determine if alerts are supported. Do not
diff --git a/chrome/browser/page_annotations/OWNERS b/chrome/browser/page_annotations/OWNERS
index 03269c6..d0ed117 100644
--- a/chrome/browser/page_annotations/OWNERS
+++ b/chrome/browser/page_annotations/OWNERS
@@ -1 +1 @@
-file://chrome/browser/persisted_state_db/OWNERS
\ No newline at end of file
+file://chrome/browser/persisted_state_db/OWNERS
diff --git a/chrome/browser/page_annotations/android/BUILD.gn b/chrome/browser/page_annotations/android/BUILD.gn
new file mode 100644
index 0000000..30f5ca76
--- /dev/null
+++ b/chrome/browser/page_annotations/android/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2020 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+  sources = [
+    "java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotation.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotation.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtils.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsService.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceConfig.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactory.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxy.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/SinglePageAnnotationsServiceResponse.java",
+  ]
+
+  deps = [
+    "//base:base_java",
+    "//chrome/browser/endpoint_fetcher:java",
+    "//chrome/browser/flags:java",
+    "//chrome/browser/profiles/android:java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//url:gurl_java",
+  ]
+}
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotation.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotation.java
new file mode 100644
index 0000000..e83a873
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotation.java
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.chromium.base.Log;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+
+import java.util.Locale;
+
+/**
+ * {@link PageAnnotation} for products in a page.
+ */
+public class BuyableProductPageAnnotation extends PageAnnotation {
+    private static final String TAG = "BPPA";
+    private static final String BUYABLE_PRODUCT_KEY = "buyableProduct";
+    private static final String CURRENT_PRICE_KEY = "currentPrice";
+    private static final String CURRENCY_CODE_KEY = "currencyCode";
+    private static final String AMOUNT_MICROS_KEY = "amountMicros";
+
+    private final long mPriceMicros;
+    private final String mCurrencyCode;
+
+    /** Creates a new instance. */
+    public BuyableProductPageAnnotation(long priceMicros, String currencyCode) {
+        super(PageAnnotationType.BUYABLE_PRODUCT);
+        mPriceMicros = priceMicros;
+        mCurrencyCode = currencyCode;
+    }
+
+    /** Gets the current price amount in micros. */
+    public long getCurrentPriceMicros() {
+        return mPriceMicros;
+    }
+
+    /** Gets the currency code used for the price. */
+    public String getCurrencyCode() {
+        return mCurrencyCode;
+    }
+
+    /** Creates a new {@link BuyableProductPageAnnotation} from a {@link JSONObject}. */
+    public static BuyableProductPageAnnotation fromJson(JSONObject object) {
+        try {
+            JSONObject metadata = object.getJSONObject(BUYABLE_PRODUCT_KEY);
+            JSONObject priceMetadata = metadata.getJSONObject(CURRENT_PRICE_KEY);
+            return new BuyableProductPageAnnotation(
+                    Long.parseLong(priceMetadata.getString(AMOUNT_MICROS_KEY)),
+                    priceMetadata.getString(CURRENCY_CODE_KEY));
+        } catch (JSONException e) {
+            Log.i(TAG,
+                    String.format(Locale.US,
+                            "There was a problem parsing "
+                                    + "BuyableProductPageAnnotation "
+                                    + "Details: %s",
+                            e.toString()));
+        }
+
+        return null;
+    }
+}
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotation.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotation.java
new file mode 100644
index 0000000..ef4afdb
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotation.java
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import androidx.annotation.StringDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base class for all page annotations.
+ */
+public abstract class PageAnnotation {
+    private final @PageAnnotationType String mAnnotationType;
+
+    /**
+     * Enumerates the various types of {@link PageAnnotation} subclasses.
+     */
+    @StringDef({PageAnnotationType.UNKNOWN, PageAnnotationType.BUYABLE_PRODUCT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PageAnnotationType {
+        String UNKNOWN = "UNKNOWN";
+        String BUYABLE_PRODUCT = "BUYABLE_PRODUCT";
+    }
+
+    /** Creates a new instance. */
+    PageAnnotation(@PageAnnotationType String type) {
+        mAnnotationType = type;
+    }
+
+    /** Gets the annotation type. */
+    @PageAnnotationType
+    String getType() {
+        return mAnnotationType;
+    }
+}
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtils.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtils.java
new file mode 100644
index 0000000..bc94e8a8
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtils.java
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.chromium.base.Log;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * A collection of helper functions for dealing with {@link PageAnnotation} instances.
+ */
+public class PageAnnotationUtils {
+    private static final String TAG = "PAU";
+    private static final String TYPE_KEY = "type";
+
+    private static final Map<Class<? extends PageAnnotation>, String> CLASS_TO_TYPE_MAP =
+            new LinkedHashMap<Class<? extends PageAnnotation>, String>() {
+                { put(BuyableProductPageAnnotation.class, PageAnnotationType.BUYABLE_PRODUCT); }
+            };
+
+    /**
+     * Creates a {@link PageAnnotation} object from the provided {@link JSONObject}.
+     */
+    public static PageAnnotation createPageAnnotationFromJson(JSONObject json) {
+        try {
+            @PageAnnotationType
+            String type = json.getString(TYPE_KEY);
+            if (type == null) {
+                type = PageAnnotationType.UNKNOWN;
+            }
+
+            switch (type) {
+                case PageAnnotationType.BUYABLE_PRODUCT: {
+                    return BuyableProductPageAnnotation.fromJson(json);
+                }
+
+                case PageAnnotationType.UNKNOWN:
+                default:
+                    break;
+            }
+
+        } catch (JSONException e) {
+            Log.i(TAG,
+                    String.format(Locale.US,
+                            "Failed to parse PageAnnotation."
+                                    + "Details: %s",
+                            e.toString()));
+        }
+
+        return null;
+    }
+
+    /**
+     * @return the first {@link PageAnnotation} object that matches the provided
+     * type from a list of generic {@link PageAnnotation} objects
+     */
+    public static <T extends PageAnnotation> T getAnnotation(
+            List<PageAnnotation> annotations, Class<T> clazz) {
+        if (annotations == null || annotations.size() == 0) {
+            return null;
+        }
+
+        @PageAnnotationType
+        String targetType = CLASS_TO_TYPE_MAP.get(clazz);
+        if (targetType == null) {
+            return null;
+        }
+
+        for (PageAnnotation annotation : annotations) {
+            if (targetType.equals(annotation.getType())) {
+                return (T) annotation;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsService.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsService.java
new file mode 100644
index 0000000..3710d88
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsService.java
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.chromium.base.Callback;
+import org.chromium.url.GURL;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Responsible for fetching and aggregating {@link PageAnnotation}s from the
+ * registered data sources.
+ */
+public class PageAnnotationsService {
+    private final PageAnnotationsServiceProxy mServiceProxy;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param serviceProxy {@link PageAnnotationsServiceProxy} instance to be used
+     *                     when fetching from the server.
+     */
+    PageAnnotationsService(PageAnnotationsServiceProxy serviceProxy) {
+        mServiceProxy = serviceProxy;
+    }
+
+    /**
+     * Fetches all {@link PageAnnotation}s for the provided URL. The caller of this
+     * method is expected to cast the {@link PageAnnotation} instances to their
+     * specific subclasses based on their types. See
+     * {@link PageAnnotationUtils#getAnnotation}.
+     *
+     * @param url      The URL to annotate.
+     * @param callback Invoked when the fetch is complete.
+     */
+    public void getAnnotations(GURL url, Callback<List<PageAnnotation>> callback) {
+        if (url == null || url.isEmpty()) {
+            callback.onResult(new LinkedList<PageAnnotation>());
+            return;
+        }
+
+        // TODO(crbug.com/1169545): Return cached annotations if possible.
+        mServiceProxy.fetchAnnotations(url, (response) -> {
+            // TODO(crbug.com/1169545): Cache annotations on the client.
+            callback.onResult(response == null ? new LinkedList<PageAnnotation>()
+                                               : response.getAnnotations());
+        });
+    }
+}
\ No newline at end of file
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceConfig.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceConfig.java
new file mode 100644
index 0000000..a1918326d
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceConfig.java
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.flags.StringCachedFieldTrialParameter;
+
+/** Flag configuration for Page Annotations Service. */
+public class PageAnnotationsServiceConfig {
+    private static final String BASE_URL_PARAM = "page_annotations_base_url";
+    private static final String DEFAULT_BASE_URL = "https://memex-pa.googleapis.com/v1/annotations";
+
+    public static final StringCachedFieldTrialParameter PAGE_ANNOTATIONS_BASE_URL =
+            new StringCachedFieldTrialParameter(
+                    ChromeFeatureList.PAGE_ANNOTATIONS_SERVICE, BASE_URL_PARAM, DEFAULT_BASE_URL);
+}
\ No newline at end of file
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactory.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactory.java
new file mode 100644
index 0000000..06a1e4a
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactory.java
@@ -0,0 +1,66 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.profiles.ProfileManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link PageAnnotationService} cached by {@link Profile}.
+ */
+public class PageAnnotationsServiceFactory {
+    @VisibleForTesting
+    protected static final Map<Profile, PageAnnotationsService> sProfileToPageAnnotationsService =
+            new HashMap<>();
+    private static ProfileManager.Observer sProfileManagerObserver;
+
+    /** Creates new instance. */
+    public PageAnnotationsServiceFactory() {
+        if (sProfileManagerObserver == null) {
+            sProfileManagerObserver = new ProfileManager.Observer() {
+                @Override
+                public void onProfileAdded(Profile profile) {}
+
+                @Override
+                public void onProfileDestroyed(Profile destroyedProfile) {
+                    PageAnnotationsService serviceToDestroy =
+                            sProfileToPageAnnotationsService.get(destroyedProfile);
+                    if (serviceToDestroy != null) {
+                        sProfileToPageAnnotationsService.remove(destroyedProfile);
+                    }
+
+                    if (sProfileToPageAnnotationsService.isEmpty()) {
+                        ProfileManager.removeObserver(sProfileManagerObserver);
+                        sProfileManagerObserver = null;
+                    }
+                }
+            };
+            ProfileManager.addObserver(sProfileManagerObserver);
+        }
+    }
+
+    /**
+     * Creates a new instance or reuses an existing one based on the current {@link Profile}.
+     *
+     * Note: Don't hold a reference to the returned value. Always use this method to access {@link
+     * PageAnnotationService} instead.
+     * @return {@link PageAnnotationsService} instance for the current regular
+     *         profile.
+     */
+    public PageAnnotationsService getForLastUsedProfile() {
+        Profile profile = Profile.getLastUsedRegularProfile();
+        PageAnnotationsService service = sProfileToPageAnnotationsService.get(profile);
+        if (service == null) {
+            service = new PageAnnotationsService(new PageAnnotationsServiceProxy(profile));
+            sProfileToPageAnnotationsService.put(profile, service);
+        }
+        return service;
+    }
+}
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxy.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxy.java
new file mode 100644
index 0000000..90b006f
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxy.java
@@ -0,0 +1,92 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.chromium.base.Callback;
+import org.chromium.base.LocaleUtils;
+import org.chromium.base.Log;
+import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher;
+import org.chromium.chrome.browser.endpoint_fetcher.EndpointResponse;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.url.GURL;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains the business logic to call the Page Annotations backend over HTTPS.
+ */
+public class PageAnnotationsServiceProxy {
+    private static final String TAG = "PASP";
+    private static final String GET_ANNOTATIONS_QUERY_PARAMS_TEMPLATE = "?url=%s";
+    private static final long TIMEOUT_MS = 1000L;
+    private static final String HTTPS_METHOD = "GET";
+    private static final String CONTENT_TYPE = "application/json; charset=UTF-8";
+    private static final String EMPTY_POST_DATA = "";
+    private static final String ANNOTATIONS_KEY = "annotations";
+    private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language";
+    private final Profile mProfile;
+
+    /**
+     * Creates a new proxy instance.
+     *
+     * @param profile Profile to use for auth.
+     */
+    PageAnnotationsServiceProxy(Profile profile) {
+        mProfile = profile;
+    }
+
+    /**
+     * Makes an HTTPS call to the backend and returns the service response through
+     * the provided callback.
+     *
+     * @param url      The URL to annotate.
+     * @param callback {@link Callback} to invoke once the request is complete.
+     */
+    public void fetchAnnotations(
+            GURL url, Callback<SinglePageAnnotationsServiceResponse> callback) {
+        if (url == null || url.isEmpty()) {
+            callback.onResult(null);
+            return;
+        }
+
+        EndpointFetcher.fetchUsingChromeAPIKey(
+                (endpointResponse)
+                        -> { fetchCallback(endpointResponse, callback); },
+                mProfile,
+                String.format(PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL.getValue()
+                                + GET_ANNOTATIONS_QUERY_PARAMS_TEMPLATE,
+                        url.getSpec()),
+                HTTPS_METHOD, CONTENT_TYPE, EMPTY_POST_DATA, TIMEOUT_MS,
+                new String[] {ACCEPT_LANGUAGE_KEY, LocaleUtils.getDefaultLocaleListString()});
+    }
+
+    private void fetchCallback(EndpointResponse response,
+            Callback<SinglePageAnnotationsServiceResponse> resultCallback) {
+        List<PageAnnotation> annotations = new ArrayList<>();
+        String responseString = response.getResponseString();
+        try {
+            JSONObject responseJson = new JSONObject(responseString);
+            JSONArray annotationsJson = responseJson.getJSONArray(ANNOTATIONS_KEY);
+
+            for (int i = 0; i < annotationsJson.length(); i++) {
+                PageAnnotation annotation = PageAnnotationUtils.createPageAnnotationFromJson(
+                        annotationsJson.getJSONObject(i));
+                if (annotation != null) {
+                    annotations.add(annotation);
+                }
+            }
+        } catch (JSONException e) {
+            Log.e(TAG,
+                    "Failed to parse SingleUrlPageAnnotations response. Details: " + e.toString());
+        }
+
+        resultCallback.onResult(new SinglePageAnnotationsServiceResponse(annotations));
+    }
+}
\ No newline at end of file
diff --git a/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/SinglePageAnnotationsServiceResponse.java b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/SinglePageAnnotationsServiceResponse.java
new file mode 100644
index 0000000..be816d9
--- /dev/null
+++ b/chrome/browser/page_annotations/android/java/src/org/chromium/chrome/browser/page_annotations/SinglePageAnnotationsServiceResponse.java
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import java.util.List;
+
+/**
+ * Represents the Page Annotations backend response for a single URL request.
+ */
+class SinglePageAnnotationsServiceResponse {
+    private final List<PageAnnotation> mAnnotations;
+
+    public SinglePageAnnotationsServiceResponse(List<PageAnnotation> annotations) {
+        mAnnotations = annotations;
+    }
+
+    /**
+     * List of annotations returned by the service.
+     */
+    public List<PageAnnotation> getAnnotations() {
+        return mAnnotations;
+    }
+}
diff --git a/chrome/browser/page_annotations/test/android/BUILD.gn b/chrome/browser/page_annotations/test/android/BUILD.gn
new file mode 100644
index 0000000..c411460
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/BUILD.gn
@@ -0,0 +1,63 @@
+# Copyright 2020 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+java_library("junit") {
+  # Skip platform checks since Robolectric depends on requires_android targets.
+  bypass_platform_checks = true
+
+  testonly = true
+
+  sources = [
+    "java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotationUnitTest.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceUnitTest.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsTestUtils.java",
+  ]
+
+  deps = [
+    "//base:base_java",
+    "//base:base_java_test_support",
+    "//base:base_junit_test_support",
+    "//chrome/browser/endpoint_fetcher:java",
+    "//chrome/browser/flags:java",
+    "//chrome/browser/page_annotations/android:java",
+    "//chrome/browser/profiles/android:java",
+    "//chrome/test/android:chrome_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//third_party/android_deps:androidx_test_runner_java",
+    "//third_party/android_deps:robolectric_all_java",
+    "//third_party/junit",
+    "//third_party/mockito:mockito_java",
+    "//url:gurl_java",
+    "//url:gurl_junit_test_support",
+  ]
+}
+
+android_library("javatests") {
+  testonly = true
+
+  sources = [
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactoryUnitTest.java",
+    "java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxyUnitTest.java",
+  ]
+
+  deps = [
+    "//base:base_java",
+    "//base:base_java_test_support",
+    "//chrome/browser/endpoint_fetcher:java",
+    "//chrome/browser/flags:java",
+    "//chrome/browser/page_annotations/android:java",
+    "//chrome/browser/profiles/android:java",
+    "//chrome/test/android:chrome_java_test_support",
+    "//third_party/android_deps:androidx_test_core_java",
+    "//third_party/android_deps:androidx_test_runner_java",
+    "//third_party/junit",
+    "//third_party/mockito:mockito_java",
+    "//url:gurl_java",
+    "//url:gurl_junit_test_support",
+  ]
+}
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotationUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotationUnitTest.java
new file mode 100644
index 0000000..7324085
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/BuyableProductPageAnnotationUnitTest.java
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+
+/**
+ * Tests for {@link BuyableProductPageAnnotation}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class BuyableProductPageAnnotationUnitTest {
+    private static final long FAKE_PRICE_MICORS = 10000L;
+    private static final String FAKE_CURRENCY_CODE = "USD";
+
+    @Test
+    public void testFromValidJsonObject() throws JSONException {
+        BuyableProductPageAnnotation annotation = BuyableProductPageAnnotation.fromJson(
+                PageAnnotationsTestUtils.createFakeBuyableProductJson(
+                        true, FAKE_PRICE_MICORS, FAKE_CURRENCY_CODE));
+        Assert.assertNotNull(annotation);
+        Assert.assertEquals(annotation.getType(), PageAnnotationType.BUYABLE_PRODUCT);
+        Assert.assertEquals(annotation.getCurrencyCode(), FAKE_CURRENCY_CODE);
+        Assert.assertEquals(annotation.getCurrentPriceMicros(), FAKE_PRICE_MICORS);
+    }
+
+    @Test
+    public void testFromMissingPriceMetadataJson() throws JSONException {
+        BuyableProductPageAnnotation annotation = BuyableProductPageAnnotation.fromJson(
+                PageAnnotationsTestUtils.createFakeBuyableProductJson());
+        Assert.assertNull(annotation);
+    }
+
+    @Test
+    public void testFromMissingPriceMicrosJson() throws JSONException {
+        BuyableProductPageAnnotation annotation = BuyableProductPageAnnotation.fromJson(
+                PageAnnotationsTestUtils.createFakeBuyableProductJson(
+                        true, null, FAKE_CURRENCY_CODE));
+        Assert.assertNull(annotation);
+    }
+
+    @Test
+    public void testFromMissingCurrencyCodeJson() throws JSONException {
+        BuyableProductPageAnnotation annotation = BuyableProductPageAnnotation.fromJson(
+                PageAnnotationsTestUtils.createFakeBuyableProductJson(
+                        true, FAKE_PRICE_MICORS, null));
+        Assert.assertNull(annotation);
+    }
+}
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java
new file mode 100644
index 0000000..13956dde
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java
@@ -0,0 +1,61 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Tests for {@link PageAnnotationUtils}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class PageAnnotationUtilsUnitTest {
+    private static final List<PageAnnotation> DUMMY_ANNOTATIONS_LIST = new LinkedList<>() {
+        { add(new BuyableProductPageAnnotation(100L, "USD")); }
+    };
+
+    private static class DummyPageAnnotation extends PageAnnotation {
+        DummyPageAnnotation() {
+            super(PageAnnotationType.UNKNOWN);
+        }
+    }
+
+    @Test
+    public void testCreateFromJsonUnknownType() throws JSONException {
+        PageAnnotation annotation = PageAnnotationUtils.createPageAnnotationFromJson(
+                PageAnnotationsTestUtils.createDummyPageAnnotationJson("DUMMY_TYPE"));
+        Assert.assertNull(annotation);
+    }
+
+    @Test
+    public void testCreateFromJsonBuyableProduct() throws JSONException {
+        PageAnnotation annotation = PageAnnotationUtils.createPageAnnotationFromJson(
+                PageAnnotationsTestUtils.createFakeBuyableProductJson(true, 100L, "USD"));
+        Assert.assertNotNull(annotation);
+    }
+
+    @Test
+    public void testGetAnnotationByType() {
+        BuyableProductPageAnnotation annotation = PageAnnotationUtils.getAnnotation(
+                DUMMY_ANNOTATIONS_LIST, BuyableProductPageAnnotation.class);
+        Assert.assertNotNull(annotation);
+    }
+
+    @Test
+    public void testGetAnnotationByTypeInvalid() {
+        DummyPageAnnotation annotation = PageAnnotationUtils.getAnnotation(
+                DUMMY_ANNOTATIONS_LIST, DummyPageAnnotation.class);
+        Assert.assertNull(annotation);
+    }
+}
\ No newline at end of file
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactoryUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactoryUnitTest.java
new file mode 100644
index 0000000..9d24942
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceFactoryUnitTest.java
@@ -0,0 +1,91 @@
+
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import static org.mockito.Mockito.spy;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.chromium.base.test.UiThreadTest;
+import org.chromium.base.test.util.Batch;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.profiles.ProfileManager;
+import org.chromium.chrome.test.ChromeBrowserTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+
+/**
+ * Unit tests for {@link PageAnnotationsServiceFactory}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@Batch(Batch.PER_CLASS)
+public class PageAnnotationsServiceFactoryUnitTest {
+    @Rule
+    public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
+
+    @Mock
+    private Profile mProfileOne;
+
+    @Mock
+    private Profile mProfileTwo;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    @SmallTest
+    @UiThreadTest
+    public void testFactoryMethod() {
+        PageAnnotationsServiceFactory factory = new PageAnnotationsServiceFactory();
+        PageAnnotationsService regularProfileService = factory.getForLastUsedProfile();
+        Assert.assertEquals(regularProfileService, factory.getForLastUsedProfile());
+
+        Profile.setLastUsedProfileForTesting(mProfileOne);
+        PageAnnotationsService regularProfileOneService = factory.getForLastUsedProfile();
+        Assert.assertNotEquals(regularProfileService, regularProfileOneService);
+        Assert.assertEquals(regularProfileOneService, factory.getForLastUsedProfile());
+
+        Profile.setLastUsedProfileForTesting(mProfileTwo);
+        PageAnnotationsService regularProfileTwoService = factory.getForLastUsedProfile();
+        Assert.assertNotEquals(regularProfileService, regularProfileTwoService);
+        Assert.assertEquals(regularProfileTwoService, factory.getForLastUsedProfile());
+
+        Profile.setLastUsedProfileForTesting(null);
+        Assert.assertEquals(regularProfileService, factory.getForLastUsedProfile());
+
+        Profile.setLastUsedProfileForTesting(mProfileOne);
+        Assert.assertEquals(regularProfileOneService, factory.getForLastUsedProfile());
+
+        Profile.setLastUsedProfileForTesting(mProfileTwo);
+        Assert.assertEquals(regularProfileTwoService, factory.getForLastUsedProfile());
+    }
+
+    @UiThreadTest
+    @SmallTest
+    @Test
+    public void testServiceDestroyedWhenProfileIsDestroyed() {
+        Profile.setLastUsedProfileForTesting(null);
+        Profile profile = Profile.getLastUsedRegularProfile();
+        PageAnnotationsServiceFactory factory = new PageAnnotationsServiceFactory();
+        PageAnnotationsService service = factory.getForLastUsedProfile();
+        Assert.assertEquals(
+                1, PageAnnotationsServiceFactory.sProfileToPageAnnotationsService.size());
+        PageAnnotationsService spyService = spy(service);
+        PageAnnotationsServiceFactory.sProfileToPageAnnotationsService.put(profile, spyService);
+        ProfileManager.onProfileDestroyed(profile);
+
+        Assert.assertTrue(PageAnnotationsServiceFactory.sProfileToPageAnnotationsService.isEmpty());
+    }
+}
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxyUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxyUnitTest.java
new file mode 100644
index 0000000..52805df
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceProxyUnitTest.java
@@ -0,0 +1,180 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import org.chromium.base.Callback;
+import org.chromium.base.LocaleUtils;
+import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher;
+import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcherJni;
+import org.chromium.chrome.browser.endpoint_fetcher.EndpointResponse;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.test.ChromeBrowserTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.url.GURL;
+import org.chromium.url.JUnitTestGURLs;
+
+import java.util.List;
+
+/**
+ * Tests for {@link PageAnnotationsServiceProxyUnitTest}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@Batch(Batch.PER_CLASS)
+@EnableFeatures({ChromeFeatureList.PAGE_ANNOTATIONS_SERVICE + "<Study"})
+@CommandLineFlags.
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-fieldtrials=Study/Group"})
+public class PageAnnotationsServiceProxyUnitTest {
+    @Rule
+    public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
+
+    @Rule
+    public JniMocker mMocker = new JniMocker();
+
+    private static final String EXPECTED_CONTENT_TYPE = "application/json; charset=UTF-8";
+    private static final String EXPECTED_METHOD = "GET";
+    private static final GURL DUMMY_PAGE_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.RED_1);
+    private static final String EMPTY_RESPONSE = "{}";
+    private static final String ENDPOINT_RESPONSE_BUYABLE_PRODUCT =
+            "{\"annotations\":[{\"type\":\"BUYABLE_PRODUCT\",\"buyableProduct\":"
+            + "{\"title\":\"foo title\",\"imageUrl\":\"https://images.com?q=1234\","
+            + "\"currentPrice\":{\"currencyCode\":\"USD\",\"amountMicros\":\"123456789012345\"},"
+            + "\"referenceType\":\"MAIN_PRODUCT\"}}]}";
+
+    @Mock
+    EndpointFetcher.Natives mEndpointFetcherJniMock;
+
+    @Mock
+    private Profile mProfile;
+
+    private PageAnnotationsServiceProxy mServiceProxy;
+
+    private static final String DEFAULT_ENDPOINT = "https://memex-pa.googleapis.com/v1/annotations";
+    private static final String ENDPOINT_OVERRIDE = "my-endpoint.com";
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mMocker.mock(EndpointFetcherJni.TEST_HOOKS, mEndpointFetcherJniMock);
+        doReturn(false).when(mProfile).isOffTheRecord();
+        mServiceProxy = new PageAnnotationsServiceProxy(mProfile);
+    }
+
+    @Test
+    @SmallTest
+    public void testEmptyUrl() {
+        mServiceProxy.fetchAnnotations(
+                GURL.emptyGURL(), (result) -> { Assert.assertNull(result); });
+    }
+
+    @Test
+    @SmallTest
+    public void testNullUrl() {
+        mServiceProxy.fetchAnnotations(null, (result) -> { Assert.assertNull(result); });
+    }
+
+    @Test
+    @SmallTest
+    public void testSingleUrlAnnotations() {
+        mockEndpointResponse(ENDPOINT_RESPONSE_BUYABLE_PRODUCT);
+        mServiceProxy.fetchAnnotations(DUMMY_PAGE_URL, (result) -> {
+            Assert.assertNotNull(result);
+            Assert.assertNotNull(result.getAnnotations());
+            verifyAnnotations(result.getAnnotations());
+        });
+    }
+
+    @Test
+    @SmallTest
+    public void testEmptyServiceResponse() {
+        mockEndpointResponse(EMPTY_RESPONSE);
+        mServiceProxy.fetchAnnotations(DUMMY_PAGE_URL,
+                (result) -> { Assert.assertTrue(result.getAnnotations().isEmpty()); });
+    }
+
+    @Test
+    @SmallTest
+    public void testDefaultRequestUrl() {
+        Assert.assertEquals(DEFAULT_ENDPOINT,
+                PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL.getValue());
+    }
+
+    @Test
+    @SmallTest
+    @CommandLineFlags.
+    Add({"force-fieldtrial-params=Study.Group:page_annotations_base_url/my-endpoint.com"})
+    public void testRequestUrlOverride() {
+        Assert.assertEquals(ENDPOINT_OVERRIDE,
+                PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL.getValue());
+    }
+
+    @Test
+    @SmallTest
+    @CommandLineFlags.
+    Add({"force-fieldtrial-params=Study.Group:page_annotations_base_url/my-endpoint.com"})
+    public void testFetchSinglePageAnnotationsUrl() {
+        mServiceProxy.fetchAnnotations(DUMMY_PAGE_URL, (result) -> {
+            Assert.assertNotNull(result);
+            Assert.assertNotNull(result.getAnnotations());
+            verifyAnnotations(result.getAnnotations());
+        });
+        verifyEndpointFetcherCalled(1, "my-endpoint.com?url=" + DUMMY_PAGE_URL.getSpec(),
+                new String[] {"Accept-Language", LocaleUtils.getDefaultLocaleListString()});
+    }
+
+    private void verifyEndpointFetcherCalled(
+            int numTimes, String expectedUrl, String[] expectedHeaders) {
+        verify(mEndpointFetcherJniMock, times(numTimes))
+                .nativeFetchChromeAPIKey(any(Profile.class), eq(expectedUrl), eq(EXPECTED_METHOD),
+                        eq(EXPECTED_CONTENT_TYPE), anyString(), anyLong(), eq(expectedHeaders),
+                        any(Callback.class));
+    }
+
+    private void mockEndpointResponse(String response) {
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                Callback callback = (Callback) invocation.getArguments()[7];
+                callback.onResult(new EndpointResponse(response));
+                return null;
+            }
+        })
+                .when(mEndpointFetcherJniMock)
+                .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
+                        anyString(), anyLong(), any(String[].class), any(Callback.class));
+    }
+
+    private void verifyAnnotations(List<PageAnnotation> annotations) {
+        Assert.assertEquals(1, annotations.size());
+        Assert.assertEquals(annotations.get(0).getType(), PageAnnotationType.BUYABLE_PRODUCT);
+    }
+}
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceUnitTest.java
new file mode 100644
index 0000000..0a3182f10
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsServiceUnitTest.java
@@ -0,0 +1,92 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.Callback;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+import org.chromium.url.GURL;
+import org.chromium.url.JUnitTestGURLs;
+
+import java.util.LinkedList;
+
+/**
+ * Tests for {@link PageAnnotationsServiceUnitTest}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class PageAnnotationsServiceUnitTest {
+    private static final GURL DUMMY_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.RED_1);
+
+    private static final LinkedList<PageAnnotation> FAKE_ANNOTATIONS_LIST =
+            new LinkedList<PageAnnotation>() {
+                { add(new BuyableProductPageAnnotation(10000000L, "USD")); }
+            };
+
+    @Mock
+    private PageAnnotationsServiceProxy mServiceProxyMock;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    private void mockServiceProxyResult(SinglePageAnnotationsServiceResponse response) {
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                Callback callback = (Callback) invocation.getArguments()[1];
+                callback.onResult(response);
+                return null;
+            }
+        })
+                .when(mServiceProxyMock)
+                .fetchAnnotations(any(GURL.class), any(Callback.class));
+    }
+
+    @Test
+    public void testReturnEmptyListOnNullResponse() {
+        mockServiceProxyResult(null);
+        PageAnnotationsService service = new PageAnnotationsService(mServiceProxyMock);
+        service.getAnnotations(DUMMY_URL, (result) -> {
+            Assert.assertNotNull(result);
+            Assert.assertEquals(0, result.size());
+        });
+    }
+
+    @Test
+    public void testNullUrl() {
+        mockServiceProxyResult(new SinglePageAnnotationsServiceResponse(FAKE_ANNOTATIONS_LIST));
+        PageAnnotationsService service = new PageAnnotationsService(mServiceProxyMock);
+        service.getAnnotations(null, (result) -> {
+            Assert.assertNotNull(result);
+            Assert.assertEquals(0, result.size());
+        });
+    }
+
+    @Test
+    public void testServerGeneratedAnnotations() {
+        mockServiceProxyResult(new SinglePageAnnotationsServiceResponse(FAKE_ANNOTATIONS_LIST));
+        PageAnnotationsService service = new PageAnnotationsService(mServiceProxyMock);
+        service.getAnnotations(DUMMY_URL, (result) -> {
+            Assert.assertNotNull(result);
+            Assert.assertEquals(1, result.size());
+            Assert.assertEquals(PageAnnotationType.BUYABLE_PRODUCT, result.get(0).getType());
+        });
+    }
+}
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsTestUtils.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsTestUtils.java
new file mode 100644
index 0000000..0cafd76
--- /dev/null
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationsTestUtils.java
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.page_annotations;
+
+import androidx.annotation.Nullable;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
+
+/** Utility functions used in page annotations unit tests. */
+class PageAnnotationsTestUtils {
+    private static final String BUYABLE_PRODUCT_KEY = "buyableProduct";
+    private static final String CURRENT_PRICE_KEY = "currentPrice";
+    private static final String CURRENCY_CODE_KEY = "currencyCode";
+    private static final String AMOUNT_MICROS_KEY = "amountMicros";
+    private static final String TYPE_KEY = "type";
+
+    static JSONObject createFakeBuyableProductJson() throws JSONException {
+        return createFakeBuyableProductJson(false, null, null);
+    }
+
+    static JSONObject createFakeBuyableProductJson(boolean includePriceMetadata,
+            @Nullable Long priceInMicros, @Nullable String currencyCode) throws JSONException {
+        JSONObject root = new JSONObject();
+        JSONObject buyableProductJson = new JSONObject();
+
+        if (includePriceMetadata) {
+            JSONObject priceMetadata = new JSONObject();
+            if (priceInMicros != null) {
+                priceMetadata.put(AMOUNT_MICROS_KEY, priceInMicros);
+            }
+
+            if (currencyCode != null) {
+                priceMetadata.put(CURRENCY_CODE_KEY, currencyCode);
+            }
+
+            buyableProductJson.put(CURRENT_PRICE_KEY, priceMetadata);
+        }
+
+        root.put(BUYABLE_PRODUCT_KEY, buyableProductJson);
+        root.put(TYPE_KEY, PageAnnotationType.BUYABLE_PRODUCT);
+        return root;
+    }
+
+    static JSONObject createDummyPageAnnotationJson(String type) throws JSONException {
+        JSONObject root = new JSONObject();
+        root.put("type", type);
+        return root;
+    }
+}
diff --git a/chrome/browser/payments/android/BUILD.gn b/chrome/browser/payments/android/BUILD.gn
index 9b8cced3..68d307bd 100644
--- a/chrome/browser/payments/android/BUILD.gn
+++ b/chrome/browser/payments/android/BUILD.gn
@@ -43,6 +43,8 @@
     "//url:origin_java",
   ]
   sources = [
+    "java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowPaymentFeatureList.java",
+    "java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowWebContentsStatics.java",
     "java/src/org/chromium/chrome/browser/payments/test_support/MockPaymentUiServiceBuilder.java",
     "java/src/org/chromium/chrome/browser/payments/test_support/PaymentRequestParamsBuilder.java",
     "java/src/org/chromium/chrome/browser/payments/test_support/ShadowPaymentFeatureList.java",
@@ -64,6 +66,7 @@
     "//chrome/android:chrome_java",
     "//chrome/browser/profiles/android:java",
     "//components/payments/content/android:java",
+    "//components/payments/content/android:junit_test_support",
     "//components/payments/content/android:service_java",
     "//components/payments/mojom:mojom_java",
     "//components/security_state/core:security_state_enums_java",
diff --git a/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowPaymentFeatureList.java b/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowPaymentFeatureList.java
new file mode 100644
index 0000000..f09d737
--- /dev/null
+++ b/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowPaymentFeatureList.java
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.payments.test_support;
+
+/**
+ * TODO(crbug.com/1170916): Removed soon. This class is a temporary replacement of
+ * ShadowPaymentFeatureList, used to transition downstream dependencies.
+ */
+public class LegacyShadowPaymentFeatureList extends ShadowPaymentFeatureList {}
diff --git a/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowWebContentsStatics.java b/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowWebContentsStatics.java
new file mode 100644
index 0000000..d7addfc
--- /dev/null
+++ b/chrome/browser/payments/android/java/src/org/chromium/chrome/browser/payments/test_support/LegacyShadowWebContentsStatics.java
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.payments.test_support;
+
+/**
+ * TODO(crbug.com/1170916): Removed soon. This class is a temporary replacement of
+ * LegacyShadowWebContentsStatics, used to transition downstream dependencies.
+ */
+public class LegacyShadowWebContentsStatics extends ShadowWebContentsStatics {}
diff --git a/chrome/browser/permissions/chrome_permission_request_manager_unittest.cc b/chrome/browser/permissions/chrome_permission_request_manager_unittest.cc
index 80e99f7d..946758d 100644
--- a/chrome/browser/permissions/chrome_permission_request_manager_unittest.cc
+++ b/chrome/browser/permissions/chrome_permission_request_manager_unittest.cc
@@ -131,7 +131,7 @@
     user_manager->AddWebKioskAppUser(account_id);
     user_manager->LoginUser(account_id);
 
-    auto kiosk_app_manager = std::make_unique<chromeos::WebKioskAppManager>();
+    auto kiosk_app_manager = std::make_unique<ash::WebKioskAppManager>();
     kiosk_app_manager->AddAppForTesting(account_id, app_url);
 
     NavigateAndCommit(url);
diff --git a/chrome/browser/permissions/chrome_permissions_client.cc b/chrome/browser/permissions/chrome_permissions_client.cc
index dddb71a..69c929ee 100644
--- a/chrome/browser/permissions/chrome_permissions_client.cc
+++ b/chrome/browser/permissions/chrome_permissions_client.cc
@@ -273,9 +273,9 @@
       user_manager::UserManager::Get()->IsLoggedInAsWebKioskApp()) {
     const AccountId& account_id =
         user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
-    DCHECK(chromeos::WebKioskAppManager::IsInitialized());
-    const chromeos::WebKioskAppData* app_data =
-        chromeos::WebKioskAppManager::Get()->GetAppByAccountId(account_id);
+    DCHECK(ash::WebKioskAppManager::IsInitialized());
+    const ash::WebKioskAppData* app_data =
+        ash::WebKioskAppManager::Get()->GetAppByAccountId(account_id);
     DCHECK(app_data);
     return url::Origin::Create(app_data->install_url());
   }
diff --git a/chrome/browser/plugins/plugin_info_host_impl.cc b/chrome/browser/plugins/plugin_info_host_impl.cc
index 2d60fc4a..6de814c 100644
--- a/chrome/browser/plugins/plugin_info_host_impl.cc
+++ b/chrome/browser/plugins/plugin_info_host_impl.cc
@@ -152,8 +152,8 @@
   shutdown_subscription_ =
       PluginInfoHostImplShutdownNotifierFactory::GetInstance()
           ->Get(profile)
-          ->Subscribe(base::Bind(&PluginInfoHostImpl::ShutdownOnUIThread,
-                                 base::Unretained(this)));
+          ->Subscribe(base::BindRepeating(
+              &PluginInfoHostImpl::ShutdownOnUIThread, base::Unretained(this)));
 }
 
 void PluginInfoHostImpl::ShutdownOnUIThread() {
diff --git a/chrome/browser/plugins/plugin_info_host_impl_unittest.cc b/chrome/browser/plugins/plugin_info_host_impl_unittest.cc
index e127a33..e94fee6a 100644
--- a/chrome/browser/plugins/plugin_info_host_impl_unittest.cc
+++ b/chrome/browser/plugins/plugin_info_host_impl_unittest.cc
@@ -32,9 +32,9 @@
 
 namespace {
 
-void PluginsLoaded(const base::Closure& callback,
+void PluginsLoaded(base::OnceClosure callback,
                    const std::vector<content::WebPluginInfo>& plugins) {
-  callback.Run();
+  std::move(callback).Run();
 }
 
 class FakePluginServiceFilter : public content::PluginServiceFilter {
diff --git a/chrome/browser/plugins/plugin_prefs.cc b/chrome/browser/plugins/plugin_prefs.cc
index 5888dba8..45b86b41 100644
--- a/chrome/browser/plugins/plugin_prefs.cc
+++ b/chrome/browser/plugins/plugin_prefs.cc
@@ -176,8 +176,8 @@
   UpdatePdfPolicy(prefs::kPluginsAlwaysOpenPdfExternally);
   registrar_.Init(prefs_);
   registrar_.Add(prefs::kPluginsAlwaysOpenPdfExternally,
-                 base::Bind(&PluginPrefs::UpdatePdfPolicy,
-                 base::Unretained(this)));
+                 base::BindRepeating(&PluginPrefs::UpdatePdfPolicy,
+                                     base::Unretained(this)));
 }
 
 void PluginPrefs::ShutdownOnUIThread() {
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 30ff1224..a52bf0d 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1537,6 +1537,11 @@
   handlers->AddHandler(
       std::make_unique<
           enterprise_connectors::EnterpriseConnectorsPolicyHandler>(
+          key::kSendDownloadToCloudEnterpriseConnector,
+          enterprise_connectors::kSendDownloadToCloudPref, chrome_schema));
+  handlers->AddHandler(
+      std::make_unique<
+          enterprise_connectors::EnterpriseConnectorsPolicyHandler>(
           key::kOnFileAttachedEnterpriseConnector,
           enterprise_connectors::kOnFileAttachedPref,
           enterprise_connectors::kOnFileAttachedScopePref, chrome_schema));
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 7d0ebb1..4dfe345c 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -739,8 +739,8 @@
   chromeos::FastTransitionObserver::RegisterPrefs(registry);
   chromeos::HIDDetectionScreenHandler::RegisterPrefs(registry);
   chromeos::KerberosCredentialsManager::RegisterLocalStatePrefs(registry);
-  chromeos::KioskAppManager::RegisterPrefs(registry);
-  chromeos::KioskCryptohomeRemover::RegisterPrefs(registry);
+  ash::KioskAppManager::RegisterPrefs(registry);
+  ash::KioskCryptohomeRemover::RegisterPrefs(registry);
   chromeos::language_prefs::RegisterPrefs(registry);
   chromeos::local_search_service::SearchMetricsReporter::
       RegisterLocalStatePrefs(registry);
@@ -765,7 +765,7 @@
   chromeos::TimeZoneResolver::RegisterPrefs(registry);
   chromeos::UserImageManager::RegisterPrefs(registry);
   chromeos::UserSessionManager::RegisterPrefs(registry);
-  chromeos::WebKioskAppManager::RegisterPrefs(registry);
+  ash::WebKioskAppManager::RegisterPrefs(registry);
   component_updater::MetadataTable::RegisterPrefs(registry);
   cryptauth::CryptAuthDeviceIdProviderImpl::RegisterLocalPrefs(registry);
   extensions::ExtensionAssetsManagerChromeOS::RegisterPrefs(registry);
diff --git a/chrome/browser/profiles/avatar_menu.h b/chrome/browser/profiles/avatar_menu.h
index dab19028..82b5cda 100644
--- a/chrome/browser/profiles/avatar_menu.h
+++ b/chrome/browser/profiles/avatar_menu.h
@@ -71,12 +71,6 @@
     // Whether or not the current profile requires sign-in before use.
     bool signin_required;
 
-    // Whether or not the current profile is a legacy supervised user profile
-    // (see SupervisedUserService).
-    // TODO(crbug/1155729): Remove this as legacy supervised users are
-    // deprecated.
-    bool legacy_supervised;
-
     // Whether or not the profile is associated with a child account
     // (see SupervisedUserService).
     bool child_account;
diff --git a/chrome/browser/profiles/profile_avatar_icon_util.cc b/chrome/browser/profiles/profile_avatar_icon_util.cc
index e3f290ed..430632e 100644
--- a/chrome/browser/profiles/profile_avatar_icon_util.cc
+++ b/chrome/browser/profiles/profile_avatar_icon_util.cc
@@ -812,7 +812,7 @@
                                app_icon_bitmap.height());
   SkCanvas offscreen_canvas(badged_bitmap, SkSurfaceProps{});
   offscreen_canvas.clear(SK_ColorTRANSPARENT);
-  offscreen_canvas.drawBitmap(app_icon_bitmap, 0, 0);
+  offscreen_canvas.drawImage(app_icon_bitmap.asImage(), 0, 0);
 
   // Render the avatar in a cutout circle. If the avatar is not square, center
   // it in the circle but favor pushing it further down.
@@ -826,7 +826,7 @@
       SkRect::MakeXYWH(cutout_left, cutout_top, cutout_size, cutout_size));
 
   offscreen_canvas.clipRRect(clip_circle, true);
-  offscreen_canvas.drawBitmap(sk_icon, icon_left, icon_top);
+  offscreen_canvas.drawImage(sk_icon.asImage(), icon_left, icon_top);
   return badged_bitmap;
 }
 #endif  // OS_WIN
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 57856a8..dff31edc 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1060,7 +1060,7 @@
   // If this is a kiosk profile, reset some of its prefs which should not
   // persist between sessions.
   if (chrome::IsRunningInForcedAppMode()) {
-    chromeos::ResetEphemeralKioskPreferences(prefs_.get());
+    ash::ResetEphemeralKioskPreferences(prefs_.get());
   }
 #endif
 
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index d5e45ef5..39f7142b 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -39,9 +39,9 @@
   if (is_chromeos_ash) {
     public_deps += [
       ":bluetooth_pairing_dialog_resources",
-      "chromeos:cellular_setup_resources",
       "chromeos:multidevice_setup_resources",
       "chromeos/accessibility:build",
+      "chromeos/cellular_setup:resources",
       "chromeos/emoji_picker:resources",
       "chromeos/multidevice_internals:resources",
       "nearby_internals:resources",
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
index 51bc1a9d..cea0b925 100644
--- a/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -8,19 +8,6 @@
 
 assert(is_chromeos, "Only Chrome OS resources in //c/b/resources//chromeos.")
 
-grit("cellular_setup_resources") {
-  source = "cellular_setup/cellular_setup_resources.grd"
-
-  defines = chrome_grit_defines
-  outputs = [
-    "grit/cellular_setup_resources.h",
-    "grit/cellular_setup_resources_map.cc",
-    "grit/cellular_setup_resources_map.h",
-    "cellular_setup_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chrome"
-}
-
 grit("multidevice_setup_resources") {
   source = "multidevice_setup/multidevice_setup_resources.grd"
 
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
index c4c639b..ffb8dd8 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
@@ -3,6 +3,7 @@
      found in the LICENSE file. -->
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-get-more">
   <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
index 431a0f9..aae84d9 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
@@ -8,6 +8,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-loading">
   <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
index e2c6b67..652e34a 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
@@ -24,6 +24,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <include src="../login/components/oobe_buttons.html">
 <include src="assistant_optin_flow.html">
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
index 18f0596..96b0131 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
@@ -6,7 +6,6 @@
 // <include src="../login/components/multi_step_behavior.js">
 // <include src="../login/components/oobe_types.js">
 // <include src="../login/components/oobe_buttons.js">
-// <include src="../login/components/oobe_dialog_host_behavior.js">
 // <include src="assistant_optin_flow.js">
 // <include src="browser_proxy.js">
 
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.html
index 5ee64514..d1ddd20 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.html
@@ -17,6 +17,7 @@
 <link rel="import" href="/components/common_styles.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-optin-flow-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_related_info.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_related_info.html
index ea682de..64a17f1 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_related_info.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_related_info.html
@@ -4,6 +4,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-related-info">
 <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
index ed00bdf86..19e9390 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
@@ -4,6 +4,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-third-party">
   <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
index 1333957..5d40d45 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -7,6 +7,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-value-prop">
   <template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
index 59c724c..c042ec86 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
@@ -8,6 +8,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="assistant-voice-match">
   <template>
diff --git a/chrome/browser/resources/chromeos/cellular_setup/BUILD.gn b/chrome/browser/resources/chromeos/cellular_setup/BUILD.gn
new file mode 100644
index 0000000..a0b992b
--- /dev/null
+++ b/chrome/browser/resources/chromeos/cellular_setup/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/common/features.gni")
+import("//tools/grit/grit_rule.gni")
+import("//ui/webui/resources/tools/generate_grd.gni")
+
+assert(is_chromeos, "Only Chrome OS resources in //c/b/resources//chromeos.")
+
+generate_grd("build_grd") {
+  input_files = [
+    "cellular_setup_dialog.html",
+    "i18n_setup.html",
+  ]
+  input_files_base_dir = rebase_path(".", "//")
+
+  grd_prefix = "cellular_setup"
+  out_grd = "$target_gen_dir/resources.grd"
+}
+
+grit("resources") {
+  defines = chrome_grit_defines
+
+  # These arguments are needed since the grd is generated at build time.
+  enable_input_discovery_for_gn_analyze = false
+  source = "$target_gen_dir/resources.grd"
+  deps = [ ":build_grd" ]
+
+  outputs = [
+    "grit/cellular_setup_resources.h",
+    "grit/cellular_setup_resources_map.cc",
+    "grit/cellular_setup_resources_map.h",
+    "cellular_setup_resources.pak",
+  ]
+  output_dir = "$root_gen_dir/chrome"
+}
diff --git a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html
index 2a6492d..e25b961 100644
--- a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html
+++ b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html
@@ -16,7 +16,7 @@
   </style>
 </head>
 <body>
-  <link rel="import" href="chrome://resources/css/text_defaults_md.css">
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <link rel="import" href="i18n_setup.html">
   <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/cellular_setup.html">
   <cellular-setup></cellular-setup>
diff --git a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd
deleted file mode 100644
index 319dbda..0000000
--- a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/cellular_setup_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/cellular_setup_resources_map.cc"
-            type="resource_file_map_source" />
-    <output filename="grit/cellular_setup_resources_map.h"
-            type="resource_map_header" />
-    <output filename="cellular_setup_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <structures>
-      <structure name="IDR_CELLULAR_SETUP_I18N_SETUP_HTML"
-                 file="i18n_setup.html"
-                 type="chrome_html" />
-      <structure name="IDR_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_HTML"
-                 file="cellular_setup_dialog.html"
-                 flattenhtml="true"
-                 allowexternalscript="true"
-                 type="chrome_html" />
-    </structures>
-  </release>
-</grit>
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index 26e90c9b..01c9bf87 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -70,9 +70,9 @@
   deps = [
     "components:fake_oobe",
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/webui/resources/js/cr/ui:dialogs",
   ]
@@ -83,8 +83,8 @@
   deps = [
     ":oobe_select",
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/webui/resources/cr_elements/cr_input:cr_input",
     "//ui/webui/resources/js:load_time_data",
@@ -111,17 +111,17 @@
 js_library("app_downloading") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_adaptive_dialog:oobe_adaptive_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
 
 js_library("arc_terms_of_service") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -129,8 +129,8 @@
 js_library("demo_preferences") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_adaptive_dialog:oobe_adaptive_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -139,8 +139,8 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -149,8 +149,8 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -158,16 +158,16 @@
 js_library("family_link_notice") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
 
 js_library("fingerprint_setup") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components/oobe_adaptive_dialog:oobe_adaptive_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc",
     "//ui/webui/resources/cr_elements/cr_lottie:cr_lottie",
@@ -190,8 +190,8 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/login:login_ui_tools",
   ]
@@ -200,16 +200,16 @@
 js_library("gesture_navigation") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
 
 js_library("marketing_opt_in") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -230,8 +230,8 @@
 js_library("offline_login") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -243,8 +243,8 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_adaptive_dialog:oobe_adaptive_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -252,8 +252,8 @@
 js_library("oobe_enable_kiosk") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -262,9 +262,9 @@
   deps = [
     ":web_view_helper",
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -272,9 +272,9 @@
 js_library("oobe_hid_detection") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_adaptive_dialog:oobe_adaptive_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -285,17 +285,17 @@
 
 js_library("oobe_network") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
 
 js_library("oobe_reset") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -303,8 +303,8 @@
 js_library("oobe_screen_assistant_optin_flow") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -328,8 +328,8 @@
 js_library("oobe_supervision_transition") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -337,8 +337,8 @@
 js_library("oobe_update") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -346,8 +346,8 @@
 js_library("parental_handoff") {
   deps = [
     "components:login_screen_behavior",
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -356,8 +356,8 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_types",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/webui/resources/cr_components/chromeos/quick_unlock:setup_pin_keyboard",
   ]
@@ -367,9 +367,9 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_types",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -378,18 +378,18 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
 
 js_library("saml_confirm_password") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
     "//ui/login:login_ui_tools",
   ]
@@ -397,8 +397,8 @@
 
 js_library("sync_consent") {
   deps = [
-    "components:oobe_dialog_host_behavior",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
@@ -407,9 +407,9 @@
   deps = [
     "components:login_screen_behavior",
     "components:multi_step_behavior",
-    "components:oobe_dialog_host_behavior",
     "components:oobe_modal_dialog",
     "components/oobe_dialog:oobe_dialog",
+    "components/oobe_dialog_host_behavior:oobe_dialog_host_behavior",
     "components/oobe_i18n_behavior:oobe_i18n_behavior",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/login/app_downloading.html b/chrome/browser/resources/chromeos/login/app_downloading.html
index 13d9677..9c8dc80d 100644
--- a/chrome/browser/resources/chromeos/login/app_downloading.html
+++ b/chrome/browser/resources/chromeos/login/app_downloading.html
@@ -9,6 +9,7 @@
 <link rel="import" href="/components/common_styles.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="app-downloading-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/checking_downloading_update.html b/chrome/browser/resources/chromeos/login/checking_downloading_update.html
index f705055..36f42c9 100644
--- a/chrome/browser/resources/chromeos/login/checking_downloading_update.html
+++ b/chrome/browser/resources/chromeos/login/checking_downloading_update.html
@@ -10,6 +10,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <!--
   UI for checking and downloading updates as part of the update process.
diff --git a/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chrome/browser/resources/chromeos/login/components/BUILD.gn
index ffe94f2..894fe79 100644
--- a/chrome/browser/resources/chromeos/login/components/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/components/BUILD.gn
@@ -11,6 +11,7 @@
     "hd_iron_icon:closure_compile",
     "oobe_carousel:closure_compile",
     "oobe_content_dialog:closure_compile",
+    "oobe_dialog_host_behavior:closure_compile",
     "oobe_focus_behavior:closure_compile",
     "oobe_i18n_behavior:closure_compile",
     "oobe_scrollable_behavior:closure_compile",
@@ -27,7 +28,6 @@
     ":login_screen_behavior",
     ":multi_step_behavior",
     ":oobe_buttons",
-    ":oobe_dialog_host_behavior",
     ":oobe_modal_dialog",
     ":oobe_types",
   ]
@@ -64,9 +64,6 @@
   deps = [ "oobe_i18n_behavior:oobe_i18n_behavior" ]
 }
 
-js_library("oobe_dialog_host_behavior") {
-}
-
 js_library("oobe_modal_dialog") {
   deps = [ "oobe_i18n_behavior:oobe_i18n_behavior" ]
 }
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_buttons.html b/chrome/browser/resources/chromeos/login/components/oobe_buttons.html
index 6e2b7400..a357433 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_buttons.html
+++ b/chrome/browser/resources/chromeos/login/components/oobe_buttons.html
@@ -62,7 +62,7 @@
 -->
 <dom-module id="oobe-text-button">
   <template>
-    <style include="cr-shared-style oobe-common oobe-buttons">
+    <style include="cr-shared-style oobe-common">
       cr-button {
         border-color: var(--oobe-button-border-color);
         border-radius: var(--oobe-button-radius);
@@ -118,7 +118,7 @@
 -->
 <dom-module id="oobe-back-button">
   <template>
-    <style include="cr-icons cr-shared-style oobe-common oobe-buttons">
+    <style include="cr-icons cr-shared-style oobe-common">
       cr-button {
         border-color: var(--oobe-button-border-color);
         border-radius: var(--oobe-button-radius);
@@ -156,7 +156,7 @@
 
 <dom-module id="oobe-next-button">
   <template>
-    <style include="cr-icons cr-shared-style oobe-common oobe-buttons">
+    <style include="cr-icons cr-shared-style oobe-common">
       cr-button {
         border-color: var(--oobe-button-border-color);
         border-radius: var(--oobe-button-radius);
@@ -218,7 +218,7 @@
 -->
 <dom-module id="oobe-welcome-secondary-button">
   <template>
-    <style include="cr-icons cr-shared-style oobe-common oobe-buttons">
+    <style include="cr-icons cr-shared-style oobe-common">
       cr-button {
         border-color: var(--oobe-button-border-color);
         border-radius: var(--oobe-button-radius);
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/BUILD.gn b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/BUILD.gn
new file mode 100644
index 0000000..e85e7d9
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+  deps = [ ":oobe_dialog_host_behavior" ]
+}
+
+js_library("oobe_dialog_host_behavior") {
+}
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.html b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.html
new file mode 100644
index 0000000..72a0f538
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.html
@@ -0,0 +1 @@
+<script src="oobe_dialog_host_behavior.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js
rename to chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior/oobe_dialog_host_behavior.js
diff --git a/chrome/browser/resources/chromeos/login/demo_preferences.html b/chrome/browser/resources/chromeos/login/demo_preferences.html
index 66b2f483..312d01f 100644
--- a/chrome/browser/resources/chromeos/login/demo_preferences.html
+++ b/chrome/browser/resources/chromeos/login/demo_preferences.html
@@ -6,6 +6,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="demo-preferences-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/demo_setup.html b/chrome/browser/resources/chromeos/login/demo_setup.html
index ce9fd95..52c61e76 100644
--- a/chrome/browser/resources/chromeos/login/demo_setup.html
+++ b/chrome/browser/resources/chromeos/login/demo_setup.html
@@ -3,6 +3,7 @@
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/progress_list_item.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="demo-setup-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/device_disabled.html b/chrome/browser/resources/chromeos/login/device_disabled.html
index 96e0797..227011e 100644
--- a/chrome/browser/resources/chromeos/login/device_disabled.html
+++ b/chrome/browser/resources/chromeos/login/device_disabled.html
@@ -8,6 +8,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="device-disabled-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/encryption_migration.html b/chrome/browser/resources/chromeos/login/encryption_migration.html
index e40ba7eaa..2cadd46 100644
--- a/chrome/browser/resources/chromeos/login/encryption_migration.html
+++ b/chrome/browser/resources/chromeos/login/encryption_migration.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="encryption-migration-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/family_link_notice.html b/chrome/browser/resources/chromeos/login/family_link_notice.html
index 2670ceb9..efe3b40 100644
--- a/chrome/browser/resources/chromeos/login/family_link_notice.html
+++ b/chrome/browser/resources/chromeos/login/family_link_notice.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="family-link-notice-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/fingerprint_setup.html b/chrome/browser/resources/chromeos/login/fingerprint_setup.html
index 547d705a..f90f5eb 100644
--- a/chrome/browser/resources/chromeos/login/fingerprint_setup.html
+++ b/chrome/browser/resources/chromeos/login/fingerprint_setup.html
@@ -13,6 +13,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="fingerprint-setup-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/gaia_password_changed.html b/chrome/browser/resources/chromeos/login/gaia_password_changed.html
index 692162b..aad18303 100644
--- a/chrome/browser/resources/chromeos/login/gaia_password_changed.html
+++ b/chrome/browser/resources/chromeos/login/gaia_password_changed.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <!--
   Password changed UI for the Gaia flow.
diff --git a/chrome/browser/resources/chromeos/login/marketing_opt_in.html b/chrome/browser/resources/chromeos/login/marketing_opt_in.html
index 830843ba..1ab33c5 100644
--- a/chrome/browser/resources/chromeos/login/marketing_opt_in.html
+++ b/chrome/browser/resources/chromeos/login/marketing_opt_in.html
@@ -10,6 +10,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <iron-iconset-svg name="marketing-opt-in-32" size="32">
     <svg>
diff --git a/chrome/browser/resources/chromeos/login/offline_login.html b/chrome/browser/resources/chromeos/login/offline_login.html
index 8cafcf2..6e6e185 100644
--- a/chrome/browser/resources/chromeos/login/offline_login.html
+++ b/chrome/browser/resources/chromeos/login/offline_login.html
@@ -11,6 +11,8 @@
 
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
+
 <!--
   Offline UI for the Login flow.
   Contains two cards with a slide transition between them:
diff --git a/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.html b/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.html
index 4b0384e..f1de4316 100644
--- a/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.html
+++ b/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.html
@@ -7,6 +7,7 @@
 <link rel="import" href="/components/common_styles.html">
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="oobe-adb-sideloading-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_enable_kiosk.html b/chrome/browser/resources/chromeos/login/oobe_enable_kiosk.html
index a9c63f99..71d3936 100644
--- a/chrome/browser/resources/chromeos/login/oobe_enable_kiosk.html
+++ b/chrome/browser/resources/chromeos/login/oobe_enable_kiosk.html
@@ -9,6 +9,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="kiosk-enable-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html
index 0285ce0..33d0de3a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html
+++ b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html
@@ -6,6 +6,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <iron-iconset-svg name="oobe-hid-detection" size="24">
   <svg>
diff --git a/chrome/browser/resources/chromeos/login/oobe_network.html b/chrome/browser/resources/chromeos/login/oobe_network.html
index 32f7d0d1..305cfde 100644
--- a/chrome/browser/resources/chromeos/login/oobe_network.html
+++ b/chrome/browser/resources/chromeos/login/oobe_network.html
@@ -6,6 +6,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="oobe-network-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html
index e5d0ad4..6d8b340 100644
--- a/chrome/browser/resources/chromeos/login/oobe_reset.html
+++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="oobe-reset-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html b/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
index f5975a45..45c1d5f6 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
@@ -3,6 +3,7 @@
      found in the LICENSE file. -->
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <include src="../assistant_optin/assistant_optin_flow.html">
 
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_autolaunch.html b/chrome/browser/resources/chromeos/login/oobe_screen_autolaunch.html
index ccc1757..5a6a604 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_autolaunch.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_autolaunch.html
@@ -1,3 +1,10 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="/components/common_styles.html">
+<link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
+
 <dom-module id="autolaunch-element">
   <template>
     <style include="oobe-dialog-host">
@@ -27,4 +34,4 @@
       </div>
     </oobe-dialog>
   </template>
-</dom-module>
\ No newline at end of file
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_terms_of_service.html b/chrome/browser/resources/chromeos/login/oobe_terms_of_service.html
index 419f60d..62fa886 100644
--- a/chrome/browser/resources/chromeos/login/oobe_terms_of_service.html
+++ b/chrome/browser/resources/chromeos/login/oobe_terms_of_service.html
@@ -13,6 +13,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="terms-of-service-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.html b/chrome/browser/resources/chromeos/login/oobe_update.html
index 02a40fb..d4c46e3 100644
--- a/chrome/browser/resources/chromeos/login/oobe_update.html
+++ b/chrome/browser/resources/chromeos/login/oobe_update.html
@@ -12,6 +12,7 @@
 <link rel="import" href="/components/oobe_slide.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="oobe-update-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index c73a771a..63135e4 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <iron-iconset-svg name="oobe-welcome-32" size="32">
   <svg>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
index d4ba0a3b..e1b6e95 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
@@ -9,6 +9,7 @@
 
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <!--
   OOBE Welcome screen
diff --git a/chrome/browser/resources/chromeos/login/packaged_license_screen.html b/chrome/browser/resources/chromeos/login/packaged_license_screen.html
index d6f6d7d9..c8b4b7e 100644
--- a/chrome/browser/resources/chromeos/login/packaged_license_screen.html
+++ b/chrome/browser/resources/chromeos/login/packaged_license_screen.html
@@ -10,6 +10,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_adaptive_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="packaged-license-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/parental_handoff.html b/chrome/browser/resources/chromeos/login/parental_handoff.html
index 7cf6e58..3663965 100644
--- a/chrome/browser/resources/chromeos/login/parental_handoff.html
+++ b/chrome/browser/resources/chromeos/login/parental_handoff.html
@@ -9,6 +9,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="parental-handoff-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/pin_setup.html b/chrome/browser/resources/chromeos/login/pin_setup.html
index 67b7550a..51c399d 100644
--- a/chrome/browser/resources/chromeos/login/pin_setup.html
+++ b/chrome/browser/resources/chromeos/login/pin_setup.html
@@ -14,6 +14,7 @@
 <link rel="import" href="/components/common_styles.html">
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="pin-setup-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.html b/chrome/browser/resources/chromeos/login/recommend_apps.html
index 1315b22..15c90c5 100644
--- a/chrome/browser/resources/chromeos/login/recommend_apps.html
+++ b/chrome/browser/resources/chromeos/login/recommend_apps.html
@@ -9,6 +9,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="recommend-apps-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/saml_confirm_password.html b/chrome/browser/resources/chromeos/login/saml_confirm_password.html
index 0546d90..ddf38fa 100644
--- a/chrome/browser/resources/chromeos/login/saml_confirm_password.html
+++ b/chrome/browser/resources/chromeos/login/saml_confirm_password.html
@@ -13,6 +13,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <!--
   SAML password confirmation UI for the Gaia flow.
diff --git a/chrome/browser/resources/chromeos/login/screen_signin_fatal_error.html b/chrome/browser/resources/chromeos/login/screen_signin_fatal_error.html
index 96f630f..410f7d9 100644
--- a/chrome/browser/resources/chromeos/login/screen_signin_fatal_error.html
+++ b/chrome/browser/resources/chromeos/login/screen_signin_fatal_error.html
@@ -6,6 +6,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="signin-fatal-error-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/screen_tpm_error.html b/chrome/browser/resources/chromeos/login/screen_tpm_error.html
index 98d7799..60355e3c 100644
--- a/chrome/browser/resources/chromeos/login/screen_tpm_error.html
+++ b/chrome/browser/resources/chromeos/login/screen_tpm_error.html
@@ -4,6 +4,7 @@
 
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="tpm-error-message-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/screen_wrong_hwid.html b/chrome/browser/resources/chromeos/login/screen_wrong_hwid.html
index f163746..732bd53 100644
--- a/chrome/browser/resources/chromeos/login/screen_wrong_hwid.html
+++ b/chrome/browser/resources/chromeos/login/screen_wrong_hwid.html
@@ -6,6 +6,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="wrong-hwid-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin.html b/chrome/browser/resources/chromeos/login/security_token_pin.html
index fbebaac2..320dc08 100644
--- a/chrome/browser/resources/chromeos/login/security_token_pin.html
+++ b/chrome/browser/resources/chromeos/login/security_token_pin.html
@@ -8,6 +8,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="security-token-pin">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/structure/components_common.html b/chrome/browser/resources/chromeos/login/structure/components_common.html
index 9cd4f750..1f47f27 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_common.html
+++ b/chrome/browser/resources/chromeos/login/structure/components_common.html
@@ -4,6 +4,7 @@
 
 <!-- Common components -->
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 <link rel="import" href="/components/common_styles.html">
 <link rel="import" href="/components/hd_iron_icon.html">
 
diff --git a/chrome/browser/resources/chromeos/login/structure/components_common.js b/chrome/browser/resources/chromeos/login/structure/components_common.js
index 0b147e7..4eccf0a 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_common.js
+++ b/chrome/browser/resources/chromeos/login/structure/components_common.js
@@ -9,7 +9,6 @@
 // This inclusion is types-only. No actual code to execute.
 // <include src="../components/oobe_types.js">
 
-// <include src="../components/oobe_dialog_host_behavior.js">
 // <include src="../components/login_screen_behavior.js">
 // <include src="../components/multi_step_behavior.js">
 // <include src="../components/oobe_buttons.js">
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.html b/chrome/browser/resources/chromeos/login/sync_consent.html
index 5866b461..c85119f 100644
--- a/chrome/browser/resources/chromeos/login/sync_consent.html
+++ b/chrome/browser/resources/chromeos/login/sync_consent.html
@@ -13,6 +13,7 @@
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
 <link rel="import" href="/components/throbber_notice.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="sync-consent-element">
   <template>
diff --git a/chrome/browser/resources/chromeos/login/update_required_card.html b/chrome/browser/resources/chromeos/login/update_required_card.html
index 07a6167..09ee8d3 100644
--- a/chrome/browser/resources/chromeos/login/update_required_card.html
+++ b/chrome/browser/resources/chromeos/login/update_required_card.html
@@ -8,6 +8,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <!--
   Update required card that informs user that current chromeos version does not
diff --git a/chrome/browser/resources/chromeos/login/user_creation.html b/chrome/browser/resources/chromeos/login/user_creation.html
index 1937c15..bddae9c 100644
--- a/chrome/browser/resources/chromeos/login/user_creation.html
+++ b/chrome/browser/resources/chromeos/login/user_creation.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/components/hd_iron_icon.html">
 <link rel="import" href="/components/oobe_dialog.html">
 <link rel="import" href="/components/oobe_i18n_behavior.html">
+<link rel="import" href="/components/oobe_dialog_host_behavior.html">
 
 <dom-module id="user-creation-element">
   <template>
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html
index fba7bc3..a54dbd2 100644
--- a/chrome/browser/resources/new_tab_page/app.html
+++ b/chrome/browser/resources/new_tab_page/app.html
@@ -108,14 +108,20 @@
   }
 
   #customizeButtonContainer {
-    align-self: flex-end;
     background-color: var(--ntp-background-override-color);
     border-radius: calc(.5 * var(--cr-button-height));
     bottom: 16px;
-    margin-inline-end: 16px;
     position: fixed;
   }
 
+  :host-context([dir='ltr']) #customizeButtonContainer {
+    right: 16px;
+  }
+
+  :host-context([dir='rtl']) #customizeButtonContainer {
+    left: 16px;
+  }
+
   :host([show-background-image_]) #customizeButtonContainer {
     background-color: transparent;
   }
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/module.html b/chrome/browser/resources/new_tab_page/modules/cart/module.html
index 73695c3..1d7a602 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/cart/module.html
@@ -46,7 +46,7 @@
   }
 
   .cart-title {
-    color: var(--ntp-theme-text-color);
+    color: var(--cr-primary-text-color);
     display: block;
     font-size: 12px;
     height: 20px;
@@ -160,18 +160,18 @@
     --cr-icon-button-margin-start: 0;
     --cr-icon-button-margin-end: 0;
     --cr-icon-image: url(icons/chevron.svg);
-    background-color: var(--ntp-theme-shortcut-background-color);
+    background-color: var(--ntp-module-scroll-button-color);
     border-radius: 50%;
     position: absolute;
-    top: 50%;
-    transform: translateY(-50%);
+    top: 45%;
+    transform: translateY(-45%);
     visibility: hidden;
     z-index: 2;
   }
 
   .side-scroll-button:hover {
     --cr-icon-button-fill-color: var(--ntp-icon-button-color-active);
-    background-color: var( --ntp-active-background-color);
+    background-color: var(--ntp-module-scroll-button-hover-color);
   }
 
   #leftScrollButton {
diff --git a/chrome/browser/resources/new_tab_page/shared_vars.css b/chrome/browser/resources/new_tab_page/shared_vars.css
index 0eae3b0..2d53a21 100644
--- a/chrome/browser/resources/new_tab_page/shared_vars.css
+++ b/chrome/browser/resources/new_tab_page/shared_vars.css
@@ -25,6 +25,8 @@
   --ntp-chip-text-color: white;
   --ntp-icon-button-color-active: var(--google-grey-refresh-700);
   --ntp-icon-button-color: var(--google-grey-600);
+  --ntp-module-scroll-button-color: var(--google-grey-refresh-100);
+  --ntp-module-scroll-button-hover-color: var(--google-grey-refresh-300);
 
   /* Other: */
   --ntp-focus-shadow: 0 0 0 2px var(--ntp-focus-shadow-color);
@@ -47,5 +49,7 @@
     --ntp-chip-text-color: var(--google-grey-900);
     --ntp-icon-button-color-active: var(--google-grey-refresh-300);
     --ntp-icon-button-color: white;
+    --ntp-module-scroll-button-color: var(--google-grey-refresh-700);
+    --ntp-module-scroll-button-hover-color: var(--google-grey-600);
   }
 }
diff --git a/chrome/browser/resources/read_later/app.js b/chrome/browser/resources/read_later/app.js
index 9ccdb132..c093d60 100644
--- a/chrome/browser/resources/read_later/app.js
+++ b/chrome/browser/resources/read_later/app.js
@@ -65,15 +65,23 @@
             Math.round(window.performance.now()));
       }, 0);
     });
-    this.updateItems_();
+
+    // Fetch the latest read later entry data.
+    const getEntriesStartTimestamp = Date.now();
+    this.apiProxy_.getReadLaterEntries().then(({entries}) => {
+      chrome.metricsPrivate.recordTime(
+          'ReadingList.WebUI.ReadingListDataReceived',
+          Math.round(Date.now() - getEntriesStartTimestamp));
+      this.updateItems_(entries);
+    });
   }
 
   /** @override */
   connectedCallback() {
     super.connectedCallback();
     const callbackRouter = this.apiProxy_.getCallbackRouter();
-    this.listenerId_ =
-        callbackRouter.itemsChanged.addListener(() => this.updateItems_());
+    this.listenerId_ = callbackRouter.itemsChanged.addListener(
+        entries => this.updateItems_(entries));
   }
 
   /** @override */
@@ -84,17 +92,13 @@
     this.listenerId_ = null;
   }
 
-  /** @private */
-  updateItems_() {
-    const getEntriesStartTimestamp = Date.now();
-    this.apiProxy_.getReadLaterEntries().then(({entries}) => {
-      chrome.metricsPrivate.recordTime(
-          'ReadingList.WebUI.ReadingListDataReceived',
-          Math.round(Date.now() - getEntriesStartTimestamp));
-
-      this.unreadItems_ = entries.unreadEntries;
-      this.readItems_ = entries.readEntries;
-    });
+  /**
+   * @param {!readLater.mojom.ReadLaterEntriesByStatus} entries
+   * @private
+   */
+  updateItems_(entries) {
+    this.unreadItems_ = entries.unreadEntries;
+    this.readItems_ = entries.readEntries;
   }
 
   /**
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 7edeb30..b91dc5e2 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -323,6 +323,8 @@
     "chromeos/google_assistant_page/google_assistant_browser_proxy.m.js",
     "chromeos/google_assistant_page/google_assistant_page.m.js",
     "chromeos/guest_os/guest_os_browser_proxy.m.js",
+    "chromeos/guest_os/guest_os_shared_paths.m.js",
+    "chromeos/guest_os/guest_os_shared_usb_devices.m.js",
     "chromeos/internet_page/esim_remove_profile_dialog.m.js",
     "chromeos/internet_page/esim_rename_dialog.m.js",
     "chromeos/internet_page/cellular_networks_list.m.js",
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/BUILD.gn b/chrome/browser/resources/settings/chromeos/guest_os/BUILD.gn
index 464f4e1..75fa5ef 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/guest_os/BUILD.gn
@@ -23,6 +23,7 @@
   deps = [
     ":guest_os_browser_proxy",
     "..:metrics_recorder",
+    "//ui/webui/resources/js:i18n_behavior",
   ]
 }
 
@@ -30,12 +31,18 @@
   deps = [
     ":guest_os_browser_proxy",
     "..:metrics_recorder",
+    "//ui/webui/resources/js:i18n_behavior",
+    "//ui/webui/resources/js:web_ui_listener_behavior",
   ]
 }
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [ ":guest_os_browser_proxy.m" ]
+  deps = [
+    ":guest_os_browser_proxy.m",
+    ":guest_os_shared_paths.m",
+    ":guest_os_shared_usb_devices.m",
+  ]
 }
 
 js_library("guest_os_browser_proxy.m") {
@@ -50,7 +57,11 @@
 js_library("guest_os_shared_usb_devices.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.m.js" ]
   deps = [
-    # TODO: Fill those in.
+    ":guest_os_browser_proxy.m",
+    "..:metrics_recorder.m",
+    "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
+    "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
   extra_deps = [ ":guest_os_shared_usb_devices_module" ]
 }
@@ -58,7 +69,11 @@
 js_library("guest_os_shared_paths.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.m.js" ]
   deps = [
-    # TODO: Fill those in.
+    ":guest_os_browser_proxy.m",
+    "..:metrics_recorder.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
   ]
   extra_deps = [ ":guest_os_shared_paths_module" ]
 }
@@ -75,12 +90,16 @@
   js_file = "guest_os_shared_paths.js"
   html_file = "guest_os_shared_paths.html"
   html_type = "dom-module"
+  auto_imports = os_settings_auto_imports
+  namespace_rewrites = os_settings_namespace_rewrites
 }
 
 polymer_modulizer("guest_os_shared_usb_devices") {
   js_file = "guest_os_shared_usb_devices.js"
   html_file = "guest_os_shared_usb_devices.html"
   html_type = "dom-module"
+  auto_imports = os_settings_auto_imports
+  namespace_rewrites = os_settings_namespace_rewrites
 }
 
 js_modulizer("modulize") {
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_browser_proxy.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_browser_proxy.js
index d76ddd4..c0b2051 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_browser_proxy.js
@@ -12,7 +12,10 @@
  *            sharedWith: ?string,
  *            promptBeforeSharing: boolean}}
  */
-let GuestOsSharedUsbDevice;
+/* #export */ let GuestOsSharedUsbDevice;
+
+/* #export */ const CROSTINI_TYPE = 'crostini';
+/* #export */ const PLUGIN_VM_TYPE = 'pluginVm';
 
 /**
  * @fileoverview A helper object used by the both the Crostini and Plugin VM
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.html b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.html
index 6b97f61..0b4e5d3 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.html
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.html
@@ -5,6 +5,8 @@
 <link rel="import" href="guest_os_browser_proxy.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../metrics_recorder.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/assert.html">
 
 <dom-module id="settings-guest-os-shared-paths">
   <template>
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
index 0ff456a..6f7e382 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
@@ -7,11 +7,6 @@
  * 'guest-os-shared-paths' is the settings shared paths subpage for guest OSes.
  */
 
-(function() {
-
-const CROSTINI_TYPE = 'crostini';
-const PLUGIN_VM_TYPE = 'pluginVm';
-
 Polymer({
   is: 'settings-guest-os-shared-paths',
 
@@ -140,4 +135,3 @@
     return 'path-display-text-' + index;
   },
 });
-})();
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.html b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.html
index 36c7fadd..97df344 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.html
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.html
@@ -1,9 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../metrics_recorder.html">
+<link rel="import" href="guest_os_browser_proxy.html">
 
 <dom-module id="settings-guest-os-shared-usb-devices">
   <template>
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
index 707ba6f..aab52c2b 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
@@ -8,9 +8,6 @@
  * guest OSes.
  */
 
-const CROSTINI_TYPE = 'crostini';
-const PLUGIN_VM_TYPE = 'pluginVm';
-
 Polymer({
   is: 'settings-guest-os-shared-usb-devices',
 
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index fadcbc0..dac8106 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -101,6 +101,7 @@
                              "chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.html|InternetPageBrowserProxy,InternetPageBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/deep_linking_behavior.html|DeepLinkingBehavior",
                              "chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_browser_proxy.html|GoogleAssistantBrowserProxy,GoogleAssistantBrowserProxyImpl",
+                             "chrome/browser/resources/settings/chromeos/guest_os/guest_os_browser_proxy.html|GuestOsBrowserProxy, GuestOsBrowserProxyImpl, GuestOsSharedUsbDevice, CROSTINI_TYPE, PLUGIN_VM_TYPE",
                              "chrome/browser/resources/settings/chromeos/metrics_recorder.html|recordSettingChange",
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.html|MultiDeviceBrowserProxy,MultiDeviceBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.html|MultiDeviceSettingsMode,MultiDeviceFeature,MultiDeviceFeatureState,MultiDevicePageContentData,PhoneHubNotificationAccessStatus,SmartLockSignInEnabledState",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index 94f5d8fd..72312bda 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -17,6 +17,8 @@
 import './crostini_page/crostini_mic_sharing_dialog.m.js';
 import './crostini_page/crostini_port_forwarding.m.js';
 import './crostini_page/crostini_port_forwarding_add_port_dialog.m.js';
+import './guest_os/guest_os_shared_usb_devices.m.js';
+import './guest_os/guest_os_shared_paths.m.js';
 import './internet_page/cellular_setup_dialog.m.js';
 import './internet_page/esim_remove_profile_dialog.m.js';
 import './internet_page/internet_config.m.js';
@@ -65,6 +67,7 @@
 export {CrostiniBrowserProxy, CrostiniBrowserProxyImpl} from './crostini_page/crostini_browser_proxy.m.js';
 export {GoogleAssistantBrowserProxyImpl} from './google_assistant_page/google_assistant_browser_proxy.m.js';
 export {ConsentStatus, DspHotwordState} from './google_assistant_page/google_assistant_page.m.js';
+export {CROSTINI_TYPE, GuestOsBrowserProxy, GuestOsBrowserProxyImpl, GuestOsSharedUsbDevice, PLUGIN_VM_TYPE} from './guest_os/guest_os_browser_proxy.m.js';
 export {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page/internet_page_browser_proxy.m.js';
 export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.m.js';
 export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubNotificationAccessStatus, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.m.js';
diff --git a/chrome/browser/resources/tab_strip/drag_manager.js b/chrome/browser/resources/tab_strip/drag_manager.js
index df8c3d0..c765de4 100644
--- a/chrome/browser/resources/tab_strip/drag_manager.js
+++ b/chrome/browser/resources/tab_strip/drag_manager.js
@@ -286,7 +286,8 @@
 
   /** @param {!DragEvent} event */
   finish(event) {
-    if (this.isDraggingPlaceholderTab_()) {
+    const wasDraggingPlaceholder = this.isDraggingPlaceholderTab_();
+    if (wasDraggingPlaceholder) {
       const id = Number(event.dataTransfer.getData(getTabIdDataType()));
       this.element_.tab = Object.assign({}, this.element_.tab, {id});
     } else if (this.isDraggingPlaceholderGroup_()) {
@@ -311,7 +312,9 @@
     this.element_.setDragging(false);
     this.element_.setDraggedOut(false);
 
-    this.maybeShowTabContextMenu_();
+    if (!wasDraggingPlaceholder) {
+      this.maybeShowTabContextMenu_();
+    }
   }
 
   /** @private */
@@ -511,6 +514,9 @@
 
     /** @private {!TabsApiProxy} */
     this.tabsProxy_ = TabsApiProxyImpl.getInstance();
+
+    /** @private {!TabStripEmbedderProxy} */
+    this.tabStripEmbedderProxy_ = TabStripEmbedderProxyImpl.getInstance();
   }
 
   /**
@@ -539,11 +545,6 @@
 
   /** @param {!DragEvent} event */
   onDragStart_(event) {
-    if (this.delegate_.shouldPreventDrag()) {
-      event.preventDefault();
-      return;
-    }
-
     const draggedItem =
         /** @type {!Array<!Element>} */ (event.composedPath()).find(item => {
           return isTabElement(item) || isTabGroupElement(item);
@@ -552,6 +553,19 @@
       return;
     }
 
+    if (this.delegate_.shouldPreventDrag()) {
+      event.preventDefault();
+
+      // The gesture to start a drag and to open a context menu are the same
+      // on touch, so fallback to showing the context menu when drag is
+      // prevented.
+      if (isTabElement(draggedItem)) {
+        this.tabStripEmbedderProxy_.showTabContextMenu(
+            draggedItem.tab.id, event.clientX, event.clientY);
+      }
+      return;
+    }
+
     this.dragSession_ = DragSession.createFromElement(
         this.delegate_,
         /** @type {!TabElement|!TabGroupElement} */ (draggedItem));
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
index 43cf188..ce28540 100644
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
@@ -36,10 +36,6 @@
 
 constexpr size_t kMaxNumberOfNavigationsToAppend = 5;
 
-// Logging the number of events cleaned up every 2 minutes is excessive, so we
-// sample by this rate.
-const double kNavigationCleanUpSamplingRate = 0.01;
-
 // Given when an event happened and its TTL, determine if it is already expired.
 // Note, if for some reason this event's timestamp is in the future, this
 // event's timestamp is invalid, hence we treat it as expired.
@@ -553,13 +549,7 @@
 }
 
 void SafeBrowsingNavigationObserverManager::CleanUpNavigationEvents() {
-  std::size_t removal_count = navigation_event_list_.CleanUpNavigationEvents();
-
-  if (base::RandDouble() < kNavigationCleanUpSamplingRate) {
-    UMA_HISTOGRAM_COUNTS_10000(
-        "SafeBrowsing.NavigationObserver.NavigationEventCleanUpCount",
-        removal_count);
-  }
+  navigation_event_list_.CleanUpNavigationEvents();
 }
 
 void SafeBrowsingNavigationObserverManager::CleanUpUserGestures() {
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 698356a..ac37b00e 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -536,23 +536,11 @@
   Browser* popup = CreateBrowserForPopup(browser()->profile());
   ASSERT_EQ(2u, active_browser_list_->size());
 
-  SessionService* session_service =
-      SessionServiceFactory::GetForProfile(browser()->profile());
-  SessionServiceTestHelper test_helper(session_service);
-  auto backend_task_runner = test_helper.GetBackendTaskRunner();
-
   // Simulate an exit by shutting down the session service. If we don't do this
   // the first window close is treated as though the user closed the window
   // and won't be restored.
   SessionServiceFactory::ShutdownForProfile(browser()->profile());
 
-  // Ensure the session service finishes writing. This is necessary as the
-  // code following this creates a new SessionService, which will use a
-  // different task runner for reading/writing to the same files.
-  base::RunLoop run_loop;
-  backend_task_runner->PostNonNestableTask(FROM_HERE, run_loop.QuitClosure());
-  run_loop.Run();
-
   // Restart and make sure we have two windows.
   CloseBrowserSynchronously(popup);
   QuitBrowserAndRestore(browser(), 1);
@@ -1955,10 +1943,7 @@
 
 // Test that when closing a profile with multiple browsers, all browsers are
 // restored when the profile is reopened.
-// Flaky:
-//  - Bulk-disabled for arm64 bot stabilization: https://crbug.com/1154345
-//  - Disabled for all platforms: https://crbug.com/1158715
-IN_PROC_BROWSER_TEST_F(SessionRestoreTest, DISABLED_RestoreAllBrowsers) {
+IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreAllBrowsers) {
   // Create two profiles with two browsers each.
   Browser* first_profile_browser_one = browser();
   chrome::NewWindow(first_profile_browser_one);
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc
index 7b2d6f9..8f6220bd 100644
--- a/chrome/browser/sessions/session_service.cc
+++ b/chrome/browser/sessions/session_service.cc
@@ -73,8 +73,53 @@
 using sessions::ContentSerializedNavigationBuilder;
 using sessions::SerializedNavigationEntry;
 
+namespace {
+
 // Every kWritesPerReset commands triggers recreating the file.
-static const int kWritesPerReset = 250;
+const int kWritesPerReset = 250;
+
+// User data key for BrowserContextData.
+const void* const kProfileTaskRunnerKey = &kProfileTaskRunnerKey;
+
+// Tracks the SequencedTaskRunner that SessionService uses for a particular
+// profile. At certain points SessionService may be destroyed, and then
+// recreated. This class ensures that when this happens, the same
+// SequencedTaskRunner is used. Without this, each instance would have its
+// own SequencedTaskRunner, which is problematic as it might then be possible
+// for the newly created SessionService to attempt to read from a file the
+// previous SessionService was still writing to. No two instances of
+// SessionService for a particular profile exist at the same time, but the
+// backend (CommandStorageBackend) is destroyed on the SequencedTaskRunner,
+// meaning without this, it might be possible for two CommandStorageBackends
+// to exist at the same time and attempt to use the same file.
+class TaskRunnerData : public base::SupportsUserData::Data {
+ public:
+  TaskRunnerData()
+      : task_runner_(
+            sessions::CommandStorageManager::CreateDefaultBackendTaskRunner()) {
+  }
+  TaskRunnerData(const TaskRunnerData&) = delete;
+  TaskRunnerData& operator=(const TaskRunnerData&) = delete;
+  ~TaskRunnerData() override = default;
+
+  static scoped_refptr<base::SequencedTaskRunner>
+  GetBackendTaskRunnerForProfile(Profile* profile) {
+    TaskRunnerData* data = static_cast<TaskRunnerData*>(
+        profile->GetUserData(kProfileTaskRunnerKey));
+    if (!data) {
+      profile->SetUserData(kProfileTaskRunnerKey,
+                           std::make_unique<TaskRunnerData>());
+      data = static_cast<TaskRunnerData*>(
+          profile->GetUserData(kProfileTaskRunnerKey));
+    }
+    return data->task_runner_;
+  }
+
+ private:
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
+}  // namespace
 
 // SessionService -------------------------------------------------------------
 
@@ -85,7 +130,10 @@
               sessions::CommandStorageManager::kSessionRestore,
               profile->GetPath(),
               this,
-              /* use_marker */ true)) {
+              /* use_marker */ true,
+              /* enable_crypto */ false,
+              std::vector<uint8_t>(),
+              TaskRunnerData::GetBackendTaskRunnerForProfile(profile))) {
   // We should never be created when incognito.
   DCHECK(!profile->IsOffTheRecord());
   BrowserList::AddObserver(this);
diff --git a/chrome/browser/sessions/session_service_factory.cc b/chrome/browser/sessions/session_service_factory.cc
index 225e343d..5efa8ca 100644
--- a/chrome/browser/sessions/session_service_factory.cc
+++ b/chrome/browser/sessions/session_service_factory.cc
@@ -60,7 +60,7 @@
   // with an explicit NULL to prevent it being recreated on the next access.
   factory->BrowserContextShutdown(profile);
   factory->BrowserContextDestroyed(profile);
-  factory->Associate(profile, NULL);
+  factory->Associate(profile, nullptr);
 }
 
 SessionServiceFactory* SessionServiceFactory::GetInstance() {
@@ -73,8 +73,7 @@
         BrowserContextDependencyManager::GetInstance()) {
 }
 
-SessionServiceFactory::~SessionServiceFactory() {
-}
+SessionServiceFactory::~SessionServiceFactory() = default;
 
 KeyedService* SessionServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index 3433a5b1d8..acc176ab 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -57,6 +57,7 @@
     "//chrome/browser/endpoint_fetcher:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/optimization_guide/android:java",
+    "//chrome/browser/page_annotations/android:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/ui/android/native_page:java",
     "//components/browser_ui/util/android:java",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/DEPS b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/DEPS
index 1022d3cd..7d53302 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/DEPS
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
   "+chrome/browser/tabpersistence",
+  "+chrome/browser/page_annotations",
   "+components/payments/content/android",
-]
-
+]
\ No newline at end of file
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
index 751858f..76783898 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
@@ -10,21 +10,17 @@
 
 import com.google.protobuf.InvalidProtocolBufferException;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
 import org.chromium.base.Callback;
-import org.chromium.base.LocaleUtils;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplierImpl;
-import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.IntCachedFieldTrialParameter;
-import org.chromium.chrome.browser.flags.StringCachedFieldTrialParameter;
 import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridgeFactory;
-import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.page_annotations.BuyableProductPageAnnotation;
+import org.chromium.chrome.browser.page_annotations.PageAnnotation;
+import org.chromium.chrome.browser.page_annotations.PageAnnotationUtils;
+import org.chromium.chrome.browser.page_annotations.PageAnnotationsServiceFactory;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.proto.ShoppingPersistedTabData.ShoppingPersistedTabDataProto;
@@ -36,6 +32,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
@@ -44,43 +41,8 @@
  */
 public class ShoppingPersistedTabData extends PersistedTabData {
     private static final String TAG = "SPTD";
-    private static final String ENDPOINT_DEFAULT = "https://memex-pa.googleapis.com/v1/annotations";
-    private static final String ENDPOINT_QUERY_STRING_PARAMS = "?url=%s";
-    private static final long TIMEOUT_MS = 1000L;
-    private static final String HTTPS_METHOD = "GET";
-    private static final String CONTENT_TYPE = "application/json; charset=UTF-8";
-    private static final String OAUTH_NAME = "SPTD";
-    private static final String EMPTY_POST_DATA = "";
-
-    private static final String ANNOTATIONS_KEY = "annotations";
-    private static final String PRICE_KEY = "price";
-    private static final String TYPE_KEY = "type";
-    private static final String BUYABLE_PRODUCT_ANNOTATION_KEY = "BUYABLE_PRODUCT";
-    private static final String BUYABLE_PRODUCT_KEY = "buyableProduct";
-    private static final String CURRENT_PRICE_KEY = "currentPrice";
-    private static final String CURRENCY_CODE_KEY = "currencyCode";
-    private static final String AMOUNT_MICROS_KEY = "amountMicros";
-    private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language";
-
     private static final String TIME_TO_LIVE_MS_PARAM = "price_tracking_time_to_live_ms";
     private static final String DISPLAY_TIME_MS_PARAM = "price_tracking_display_time_ms";
-    private static final String ENDPOINT_PARAM = "price_tracking_endpoint";
-
-    private static final long ONE_WEEK_MS = TimeUnit.DAYS.toMillis(7);
-    @VisibleForTesting
-    public static final long ONE_HOUR_MS = TimeUnit.HOURS.toMillis(1);
-
-    public static final IntCachedFieldTrialParameter TIME_TO_LIVE_MS =
-            new IntCachedFieldTrialParameter(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
-                    TIME_TO_LIVE_MS_PARAM, (int) ONE_HOUR_MS);
-
-    public static final IntCachedFieldTrialParameter DISPLAY_TIME_MS =
-            new IntCachedFieldTrialParameter(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
-                    DISPLAY_TIME_MS_PARAM, (int) ONE_WEEK_MS);
-
-    public static final StringCachedFieldTrialParameter ENDPOINT =
-            new StringCachedFieldTrialParameter(
-                    ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, ENDPOINT_PARAM, ENDPOINT_DEFAULT);
 
     private static final int FRACTIONAL_DIGITS_LESS_THAN_TEN_UNITS = 2;
     private static final int FRACTIONAL_DIGITS_GREATER_THAN_TEN_UNITS = 0;
@@ -91,6 +53,18 @@
     private static final long TWO_UNITS = 2 * MICROS_TO_UNITS;
     private static final long TEN_UNITS = 10 * MICROS_TO_UNITS;
     private static final int MINIMUM_DROP_PERCENTAGE = 10;
+    private static final long ONE_WEEK_MS = TimeUnit.DAYS.toMillis(7);
+
+    @VisibleForTesting
+    public static final long ONE_HOUR_MS = TimeUnit.HOURS.toMillis(1);
+
+    public static final IntCachedFieldTrialParameter TIME_TO_LIVE_MS =
+            new IntCachedFieldTrialParameter(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
+                    TIME_TO_LIVE_MS_PARAM, (int) ONE_HOUR_MS);
+
+    public static final IntCachedFieldTrialParameter DISPLAY_TIME_MS =
+            new IntCachedFieldTrialParameter(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
+                    DISPLAY_TIME_MS_PARAM, (int) ONE_WEEK_MS);
 
     @VisibleForTesting
     public static final long NO_TRANSITIONS_OCCURRED = -1;
@@ -110,6 +84,10 @@
             new ObservableSupplierImpl<>();
 
     @VisibleForTesting
+    protected static PageAnnotationsServiceFactory sPageAnnotationsServiceFactory =
+            new PageAnnotationsServiceFactory();
+
+    @VisibleForTesting
     protected EmptyTabObserver mUrlUpdatedObserver;
 
     // Lazy initialization of OptimizationGuideBridgeFactory
@@ -210,19 +188,12 @@
                             supplierCallback.onResult(null);
                             return;
                         }
-                        EndpointFetcher.fetchUsingChromeAPIKey(
-                                (endpointResponse)
-                                        -> {
+
+                        sPageAnnotationsServiceFactory.getForLastUsedProfile().getAnnotations(
+                                tab.getUrl(), (result) -> {
                                     supplierCallback.onResult(
-                                            build(tab, endpointResponse.getResponseString(),
-                                                    previousShoppingPersistedTabData));
-                                },
-                                Profile.getLastUsedRegularProfile(),
-                                String.format(ENDPOINT.getValue() + ENDPOINT_QUERY_STRING_PARAMS,
-                                        tab.getUrlString()),
-                                HTTPS_METHOD, CONTENT_TYPE, EMPTY_POST_DATA, TIMEOUT_MS,
-                                new String[] {ACCEPT_LANGUAGE_KEY,
-                                        LocaleUtils.getDefaultLocaleListString()});
+                                            build(tab, result, previousShoppingPersistedTabData));
+                                });
                     });
                 },
                 ShoppingPersistedTabData.class, callback);
@@ -261,35 +232,22 @@
         mIsTabSaveEnabledSupplier.set(false);
     }
 
-    private static ShoppingPersistedTabData build(Tab tab, String responseString,
+    private static ShoppingPersistedTabData build(Tab tab, List<PageAnnotation> annotations,
             ShoppingPersistedTabData previousShoppingPersistedTabData) {
         ShoppingPersistedTabData res = new ShoppingPersistedTabData(tab);
         @FoundBuyableProductAnnotation
         int foundBuyableProductAnnotation = FoundBuyableProductAnnotation.NOT_FOUND;
-        try {
-            JSONObject jsonObject = new JSONObject(responseString);
-            JSONArray annotations = jsonObject.getJSONArray(ANNOTATIONS_KEY);
-            for (int i = 0; i < annotations.length(); i++) {
-                JSONObject annotation = annotations.getJSONObject(i);
-                if (BUYABLE_PRODUCT_ANNOTATION_KEY.equals(annotation.getString(TYPE_KEY))) {
-                    JSONObject metadata = annotation.getJSONObject(BUYABLE_PRODUCT_KEY);
-                    JSONObject priceMetadata = metadata.getJSONObject(CURRENT_PRICE_KEY);
-                    res.setPriceMicros(Long.parseLong(priceMetadata.getString(AMOUNT_MICROS_KEY)),
-                            previousShoppingPersistedTabData);
-                    res.setCurrencyCode(priceMetadata.getString(CURRENCY_CODE_KEY));
-                    res.setLastUpdatedMs(System.currentTimeMillis());
-                    foundBuyableProductAnnotation = FoundBuyableProductAnnotation.FOUND;
-                    break;
-                }
-            }
-        } catch (JSONException e) {
-            Log.i(TAG,
-                    String.format(Locale.US,
-                            "There was a problem acquiring "
-                                    + "ShoppingPersistedTabData "
-                                    + "Details: %s",
-                            e.toString()));
+
+        BuyableProductPageAnnotation buyableProduct =
+                PageAnnotationUtils.getAnnotation(annotations, BuyableProductPageAnnotation.class);
+        if (buyableProduct != null) {
+            res.setPriceMicros(
+                    buyableProduct.getCurrentPriceMicros(), previousShoppingPersistedTabData);
+            res.setCurrencyCode(buyableProduct.getCurrencyCode());
+            res.setLastUpdatedMs(System.currentTimeMillis());
+            foundBuyableProductAnnotation = FoundBuyableProductAnnotation.FOUND;
         }
+
         RecordHistogram.recordEnumeratedHistogram(
                 "Tabs.ShoppingPersistedTabData.FoundBuyableProductAnnotation",
                 foundBuyableProductAnnotation, FoundBuyableProductAnnotation.NUM_ENTRIES);
diff --git a/chrome/browser/taskbar/taskbar_decorator_win.cc b/chrome/browser/taskbar/taskbar_decorator_win.cc
index 99902dc..182d8d9 100644
--- a/chrome/browser/taskbar/taskbar_decorator_win.cc
+++ b/chrome/browser/taskbar/taskbar_decorator_win.cc
@@ -92,7 +92,7 @@
     // it in the paintable region instead, rounding up to the closest pixel to
     // avoid smearing.
     const int y_offset = std::ceilf((kOverlayIconSize - resized_height) / 2.0f);
-    offscreen_canvas.drawBitmap(sk_icon, 0, y_offset);
+    offscreen_canvas.drawImage(sk_icon.asImage(), 0, y_offset);
 
     icon = IconUtil::CreateHICONFromSkBitmap(offscreen_bitmap);
     if (!icon.is_valid())
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 73b2ec01..73ec30f5 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -368,7 +368,8 @@
   SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size));
   // Note(oshima): The following scaling code doesn't work with
   // a mask image.
-  canvas.drawBitmapRect(source_bitmap, scaled_bounds, nullptr);
+  canvas.drawImageRect(source_bitmap.asImage(), scaled_bounds,
+                       SkSamplingOptions());
   return scaled_bitmap;
 }
 
diff --git a/chrome/browser/thumbnail/cc/thumbnail_cache.cc b/chrome/browser/thumbnail/cc/thumbnail_cache.cc
index a9757d2..99419df 100644
--- a/chrome/browser/thumbnail/cc/thumbnail_cache.cc
+++ b/chrome/browser/thumbnail/cc/thumbnail_cache.cc
@@ -28,6 +28,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkMallocPixelRef.h"
 #include "third_party/skia/include/core/SkPixelRef.h"
 #include "ui/android/resources/ui_resource_provider.h"
@@ -995,7 +996,7 @@
       raw_data_small.allocPixels(SkImageInfo::MakeN32(
           content_size.width(), content_size.height(), kOpaque_SkAlphaType));
       SkCanvas small_canvas(raw_data_small);
-      small_canvas.drawBitmap(raw_data, 0, 0);
+      small_canvas.drawImage(raw_data.asImage(), 0, 0);
       raw_data_small.setImmutable();
     }
   }
@@ -1026,7 +1027,7 @@
   dst_bitmap.eraseColor(0);
   SkCanvas canvas(dst_bitmap);
   canvas.scale(new_scale, new_scale);
-  canvas.drawBitmap(bitmap, 0, 0, nullptr);
+  canvas.drawImage(bitmap.asImage(), 0, 0);
   dst_bitmap.setImmutable();
 
   return std::make_pair(dst_bitmap, new_scale * scale);
diff --git a/chrome/browser/translate/translate_service.cc b/chrome/browser/translate/translate_service.cc
index 9fe8c2e..276ebfc 100644
--- a/chrome/browser/translate/translate_service.cc
+++ b/chrome/browser/translate/translate_service.cc
@@ -136,8 +136,6 @@
   // - empty (can happen for popups created with window.open(""))
   // - an internal URL:
   //   - chrome:// and chrome-native:// for all platforms
-  //   - file:// and content:// are Android-specific, and are thus impossible
-  //     on other platforms
   // - the devtools (which is considered UI)
   // - about:blank
   // - Chrome OS file manager extension
@@ -145,8 +143,6 @@
   //   confuse the CLD)
   return !url.is_empty() && !url.SchemeIs(content::kChromeUIScheme) &&
          !url.SchemeIs(chrome::kChromeNativeScheme) &&
-         !url.SchemeIs(url::kFileScheme) &&
-         !url.SchemeIs(url::kContentScheme) &&
          !url.SchemeIs(content::kChromeDevToolsScheme) && !url.IsAboutBlank() &&
 #if BUILDFLAG(IS_CHROMEOS_ASH)
          !(url.SchemeIs(extensions::kExtensionScheme) &&
diff --git a/chrome/browser/translate/translate_service_unittest.cc b/chrome/browser/translate/translate_service_unittest.cc
index 1f20a29..3d68ecd7 100644
--- a/chrome/browser/translate/translate_service_unittest.cc
+++ b/chrome/browser/translate/translate_service_unittest.cc
@@ -41,14 +41,16 @@
   GURL chrome_native_url = GURL(chrome_native);
   EXPECT_FALSE(TranslateService::IsTranslatableURL(chrome_native_url));
 
-  // kContentScheme and kFileScheme are Android-specific.
-  std::string content = std::string(url::kContentScheme) + "://";
-  GURL content_url = GURL(content);
-  EXPECT_FALSE(TranslateService::IsTranslatableURL(content_url));
-
   std::string file = std::string(url::kFileScheme) + "://";
   GURL file_url = GURL(file);
-  EXPECT_FALSE(TranslateService::IsTranslatableURL(file_url));
+  EXPECT_TRUE(TranslateService::IsTranslatableURL(file_url));
+
+  // kContentScheme is only used on Android.
+#if defined(OS_ANDROID)
+  std::string content = std::string(url::kContentScheme) + "://";
+  GURL content_url = GURL(content);
+  EXPECT_TRUE(TranslateService::IsTranslatableURL(content_url));
+#endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   std::string filemanager = std::string(extensions::kExtensionScheme) +
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 7cf5243..4e38a2d 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2897,7 +2897,6 @@
       "sync/one_click_signin_links_delegate.h",
       "sync/one_click_signin_links_delegate_impl.cc",
       "sync/one_click_signin_links_delegate_impl.h",
-      "user_manager.cc",
       "user_manager.h",
       "views/profiles/badged_profile_photo.cc",
       "views/profiles/badged_profile_photo.h",
diff --git a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm
index 46e5d12f..947b5516 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm
@@ -179,48 +179,14 @@
   // available, so disallow creating or editing a profile.
   Profile* activeProfile = ProfileManager::GetLastUsedProfileIfLoaded();
   if (!activeProfile || activeProfile->IsGuestSession()) {
-    return [menuItem action] != @selector(newProfile:) &&
-           [menuItem action] != @selector(editProfile:);
+    if ([menuItem action] == @selector(newProfile:) ||
+        [menuItem action] == @selector(editProfile:)) {
+      return NO;
+    }
   }
 
-  if (!IsAddPersonEnabled())
-    return [menuItem action] != @selector(newProfile:);
-
-  size_t index = _avatarMenu->GetActiveProfileIndex();
-  if (_avatarMenu->GetNumberOfItems() <= index) {
-    ValidateMenuItemSelector currentSelector = UNKNOWN_SELECTOR;
-    if ([menuItem action] == @selector(newProfile:))
-      currentSelector = NEW_PROFILE;
-    else if ([menuItem action] == @selector(editProfile:))
-      currentSelector = EDIT_PROFILE;
-    else if ([menuItem action] == @selector(switchToProfileFromMenu:))
-      currentSelector = SWITCH_PROFILE_MENU;
-    else if ([menuItem action] == @selector(switchToProfileFromDock:))
-      currentSelector = SWITCH_PROFILE_DOCK;
-    UMA_HISTOGRAM_BOOLEAN("Profile.ValidateMenuItemInvalidIndex.IsGuest",
-                          false);
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Profile.ValidateMenuItemInvalidIndex.ProfileCount",
-        _avatarMenu->GetNumberOfItems(),
-        1, 20, 20);
-    UMA_HISTOGRAM_ENUMERATION("Profile.ValidateMenuItemInvalidIndex.Selector",
-                              currentSelector,
-                              MAX_VALIDATE_MENU_SELECTOR);
-
+  if (!IsAddPersonEnabled() && [menuItem action] == @selector(newProfile:))
     return NO;
-  }
-
-  const AvatarMenu::Item& itemData = _avatarMenu->GetItemAt(index);
-  if ([menuItem action] == @selector(switchToProfileFromDock:) ||
-      [menuItem action] == @selector(switchToProfileFromMenu:)) {
-    if (!itemData.legacy_supervised)
-      return YES;
-
-    return [menuItem tag] == static_cast<NSInteger>(itemData.menu_index);
-  }
-
-  if ([menuItem action] == @selector(newProfile:))
-    return !itemData.legacy_supervised;
 
   return YES;
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index e1142f3..bfa3493 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -72,12 +72,6 @@
 const ui::KeyboardCode kSearchKeywordKeys[] = {
   ui::VKEY_F, ui::VKEY_O, ui::VKEY_O, ui::VKEY_UNKNOWN
 };
-const ui::KeyboardCode kSearchKeywordPrefixKeys[] = {
-  ui::VKEY_F, ui::VKEY_O, ui::VKEY_UNKNOWN
-};
-const ui::KeyboardCode kSearchKeywordCompletionKeys[] = {
-  ui::VKEY_O, ui::VKEY_UNKNOWN
-};
 const char kSearchURL[] = "http://www.foo.com/search?q={searchTerms}";
 const char kSearchShortName[] = "foo";
 const char kSearchText[] = "abc";
@@ -891,219 +885,6 @@
   ASSERT_EQ(ASCIIToUTF16("?"), omnibox_view->GetText());
 }
 
-// Flaky on TSAN. https://crbug.com/911614
-#if defined(THREAD_SANITIZER)
-#define MAYBE_AcceptKeywordBySpace DISABLED_AcceptKeywordBySpace
-#else
-#define MAYBE_AcceptKeywordBySpace AcceptKeywordBySpace
-#endif
-IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_AcceptKeywordBySpace) {
-  // AcceptKeywordBySpace is disabled when keyword search button is enabled.
-  if (OmniboxFieldTrial::IsKeywordSearchButtonEnabled())
-    return;
-
-  OmniboxView* omnibox_view = nullptr;
-  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
-
-  base::string16 search_keyword(ASCIIToUTF16(kSearchKeyword));
-
-  // Trigger keyword hint mode.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword, omnibox_view->GetText());
-
-  // Trigger keyword mode by space.
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_TRUE(omnibox_view->GetText().empty());
-  size_t start, end;
-  omnibox_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(0U, start);
-  EXPECT_EQ(0U, end);
-
-  // Revert to keyword hint mode.
-  omnibox_view->model()->ClearKeyword();
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + base::char16(' '), omnibox_view->GetText());
-  omnibox_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(search_keyword.length() + 1, start);
-  EXPECT_EQ(search_keyword.length() + 1, end);
-
-  // Keyword should also be accepted by typing an ideographic space.
-  omnibox_view->OnBeforePossibleChange();
-  omnibox_view->SetWindowTextAndCaretPos(search_keyword +
-      base::WideToUTF16(L"\x3000"), search_keyword.length() + 1, false, false);
-  omnibox_view->OnAfterPossibleChange(true);
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_TRUE(omnibox_view->GetText().empty());
-
-  // Revert to keyword hint mode.
-  omnibox_view->model()->ClearKeyword();
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + base::char16(' '), omnibox_view->GetText());
-
-  // Keyword shouldn't be accepted by pressing space with a trailing
-  // whitespace.
-  omnibox_view->SetWindowTextAndCaretPos(search_keyword + base::char16(' '),
-      search_keyword.length() + 1, false, false);
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
-
-  // Keyword shouldn't be accepted by deleting the trailing space.
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + base::char16(' '), omnibox_view->GetText());
-
-  // Keyword shouldn't be accepted by pressing space before a trailing space.
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
-
-  // Keyword should be accepted by pressing space in the middle of context and
-  // just after the keyword.
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(ASCIIToUTF16("a "), omnibox_view->GetText());
-  omnibox_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(0U, start);
-  EXPECT_EQ(0U, end);
-
-  // Keyword shouldn't be accepted by pasting "foo bar".
-  omnibox_view->SetUserText(base::string16());
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
-
-  omnibox_view->OnBeforePossibleChange();
-  omnibox_view->model()->OnPaste();
-  omnibox_view->SetWindowTextAndCaretPos(search_keyword +
-      ASCIIToUTF16(" bar"), search_keyword.length() + 4, false, false);
-  omnibox_view->OnAfterPossibleChange(true);
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
-  ASSERT_EQ(search_keyword + ASCIIToUTF16(" bar"), omnibox_view->GetText());
-
-  // Keyword shouldn't be accepted for case like: "foo b|ar" -> "foo b |ar".
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
-  ASSERT_EQ(search_keyword + ASCIIToUTF16(" b ar"), omnibox_view->GetText());
-
-  // Keyword could be accepted by pressing space with a selected range at the
-  // end of text.
-  omnibox_view->OnBeforePossibleChange();
-  omnibox_view->OnInlineAutocompleteTextMaybeChanged(
-      search_keyword + ASCIIToUTF16("  "),
-      {{search_keyword.length() + 2, search_keyword.length()}},
-      search_keyword.length());
-  omnibox_view->OnAfterPossibleChange(true);
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
-
-  omnibox_view->GetSelectionBounds(&start, &end);
-  ASSERT_NE(start, end);
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(base::string16(), omnibox_view->GetText());
-
-  // Space should accept keyword even when inline autocomplete is available.
-  omnibox_view->SetUserText(base::string16());
-  const TestHistoryEntry kHistoryFoobar = {
-    "http://www.foobar.com", "Page foobar", 100, 100, true
-  };
-
-  // Add a history entry to trigger inline autocomplete when typing "foo".
-  ASSERT_NO_FATAL_FAILURE(AddHistoryEntry(
-      kHistoryFoobar, base::Time::Now() - base::TimeDelta::FromHours(1)));
-
-  // Type "fo" to trigger inline autocomplete.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordPrefixKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(omnibox_view->model()->popup_model()->IsOpen());
-  ASSERT_NE(search_keyword, omnibox_view->GetText());
-
-  // Keyword hint shouldn't be visible.
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
-
-  // Add the "o".  Inline autocompletion should still happen, but now we
-  // should also get a keyword hint because we've typed a keyword exactly.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordCompletionKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(omnibox_view->model()->popup_model()->IsOpen());
-  ASSERT_NE(search_keyword, omnibox_view->GetText());
-  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_FALSE(omnibox_view->model()->keyword().empty());
-
-  // Trigger keyword mode by space.
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_TRUE(omnibox_view->GetText().empty());
-
-  // Space in the middle of a temporary text, which separates the text into
-  // keyword and replacement portions, should trigger keyword mode.
-  omnibox_view->SetUserText(base::string16());
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
-  ASSERT_TRUE(popup_model->IsOpen());
-  ASSERT_EQ(ASCIIToUTF16("foobar.com"), omnibox_view->GetText());
-  omnibox_view->model()->OnUpOrDownKeyPressed(1);
-  omnibox_view->model()->OnUpOrDownKeyPressed(-1);
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
-  ASSERT_EQ(ASCIIToUTF16("bar.com"), omnibox_view->GetText());
-
-  // Space after temporary text that looks like a keyword, when the original
-  // input does not look like a keyword, should trigger keyword mode.
-  omnibox_view->SetUserText(base::string16());
-  const TestHistoryEntry kHistoryFoo = {
-    "http://footest.com", "Page footest", 1000, 1000, true
-  };
-
-  // Add a history entry to trigger HQP matching with text == keyword when
-  // typing "fo te".
-  ASSERT_NO_FATAL_FAILURE(AddHistoryEntry(
-      kHistoryFoo, base::Time::Now() - base::TimeDelta::FromMinutes(10)));
-
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_F, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_O, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_T, 0));
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_E, 0));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-  base::string16 search_keyword2(ASCIIToUTF16(kSearchKeyword2));
-  while ((omnibox_view->GetText() != search_keyword2) &&
-         (popup_model->selected_line() < popup_model->result().size() - 1))
-    omnibox_view->model()->OnUpOrDownKeyPressed(1);
-  ASSERT_EQ(search_keyword2, omnibox_view->GetText());
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
-  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
-  ASSERT_EQ(search_keyword2, omnibox_view->model()->keyword());
-  ASSERT_TRUE(omnibox_view->GetText().empty());
-}
-
 IN_PROC_BROWSER_TEST_F(OmniboxViewTest, NonSubstitutingKeywordTest) {
   OmniboxView* omnibox_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
diff --git a/chrome/browser/ui/user_manager.cc b/chrome/browser/ui/user_manager.cc
deleted file mode 100644
index 32a3c09..0000000
--- a/chrome/browser/ui/user_manager.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/user_manager.h"
-
-UserManagerProfileDialog::BaseDialogDelegate::BaseDialogDelegate() = default;
-
-bool UserManagerProfileDialog::BaseDialogDelegate::HandleContextMenu(
-    content::RenderFrameHost* render_frame_host,
-    const content::ContextMenuParams& params) {
-  // Ignores context menu.
-  return true;
-}
diff --git a/chrome/browser/ui/user_manager.h b/chrome/browser/ui/user_manager.h
index 2c7c0e5..30d2219 100644
--- a/chrome/browser/ui/user_manager.h
+++ b/chrome/browser/ui/user_manager.h
@@ -10,7 +10,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile_window.h"
 #include "components/signin/public/base/signin_metrics.h"
-#include "content/public/browser/web_contents_delegate.h"
 
 namespace base {
 class FilePath;
@@ -90,23 +89,6 @@
 
   // Hides the dialog if it is showing.
   static void HideDialog();
-
-  // Abstract base class for performing online reauthentication of profiles in
-  // the User Manager. It is concretely implemented in UserManagerMac and
-  // UserManagerView to specialize the closing of the UI's dialog widgets.
-  class BaseDialogDelegate : public content::WebContentsDelegate {
-   public:
-    BaseDialogDelegate();
-    BaseDialogDelegate(const BaseDialogDelegate&) = delete;
-    BaseDialogDelegate& operator=(const BaseDialogDelegate&) = delete;
-
-    // content::WebContentsDelegate:
-    bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
-                           const content::ContextMenuParams& params) override;
-
-   protected:
-    virtual void CloseDialog() = 0;
-  };
 };
 
 #endif  // CHROME_BROWSER_UI_USER_MANAGER_H_
diff --git a/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.cc b/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.cc
index cc1a8cb8..b0f58dd 100644
--- a/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.cc
+++ b/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.cc
@@ -60,6 +60,17 @@
   web_view_->LoadInitialURL(GURL(chrome::kChromeUISigninErrorURL));
 }
 
+bool UserManagerProfileDialogDelegate::HandleContextMenu(
+    content::RenderFrameHost* render_frame_host,
+    const content::ContextMenuParams& params) {
+  // Prevents the context menu from being shown. While the signin page could do
+  // this just with JS, there could be a brief moment before a context menu
+  // handler could be registered when the user could still open a context menu,
+  // so we block the attempt here. Note that the signin page is responsible for
+  // preventing context menus in any <webview> contents it creates.
+  return true;
+}
+
 web_modal::WebContentsModalDialogHost*
 UserManagerProfileDialogDelegate::GetWebContentsModalDialogHost() {
   return this;
diff --git a/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.h b/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.h
index 69ef7e3..0690b80 100644
--- a/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.h
+++ b/chrome/browser/ui/views/profiles/user_manager_profile_dialog_delegate.h
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
 #include "chrome/browser/ui/user_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -31,7 +32,7 @@
 
 class UserManagerProfileDialogDelegate
     : public views::DialogDelegateView,
-      public UserManagerProfileDialog::BaseDialogDelegate,
+      public content::WebContentsDelegate,
       public ChromeWebModalDialogManagerDelegate,
       public web_modal::WebContentsModalDialogHost {
  public:
@@ -45,12 +46,15 @@
   UserManagerProfileDialogDelegate& operator=(
       const UserManagerProfileDialogDelegate&) = delete;
 
-  // UserManagerProfileDialog::BaseDialogDelegate
-  void CloseDialog() override;
+  void CloseDialog();
 
   // Display the local error message inside login window.
   void DisplayErrorMessage();
 
+  // content::WebContentsDelegate
+  bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
+                         const content::ContextMenuParams& params) override;
+
   // ChromeWebModalDialogManagerDelegate
   web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
       override;
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
index 2434ce1..2831274 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
@@ -23,7 +23,10 @@
 ChromeLabsButton::~ChromeLabsButton() = default;
 
 void ChromeLabsButton::UpdateIcon() {
-  UpdateIconsWithStandardColors(kChromeLabsIcon);
+  const gfx::VectorIcon& chrome_labs_image =
+      ui::TouchUiController::Get()->touch_ui() ? kChromeLabsTouchIcon
+                                               : kChromeLabsIcon;
+  UpdateIconsWithStandardColors(chrome_labs_image);
 }
 
 void ChromeLabsButton::SetLabInfoForTesting(
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index 75ce1d1..ed49178 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -207,21 +207,42 @@
   UpdateColorsAndInsets();
 }
 
+void ToolbarButton::TouchUiChanged() {
+  UpdateIcon();
+  UpdateColorsAndInsets();
+  PreferredSizeChanged();
+}
+
 void ToolbarButton::ClearHighlight() {
   highlight_color_animation_.Hide();
   ShrinkDownThenClearText();
 }
 
 void ToolbarButton::UpdateColorsAndInsets() {
+  // First, calculate new border insets assuming CalculatePreferredSize()
+  // accurately reflects the desired content size.
+
+  const gfx::Size current_preferred_size = CalculatePreferredSize();
+  const gfx::Insets current_insets = GetInsets();
+  const gfx::Size target_contents_size =
+      current_preferred_size - current_insets.size();
+
+  const gfx::Insets target_insets =
+      layout_insets_.value_or(::GetLayoutInsets(TOOLBAR_BUTTON)) +
+      layout_inset_delta_ + *GetProperty(views::kInternalPaddingKey);
+
+  const gfx::Size target_size = target_contents_size + target_insets.size();
+
   const int highlight_radius =
       ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
-          views::EMPHASIS_MAXIMUM, size());
+          views::EMPHASIS_MAXIMUM, target_size);
 
   SetEnabledTextColors(highlight_color_animation_.GetTextColor());
 
   // ToolbarButtons are always the height the location bar.
   const gfx::Insets paint_insets =
-      gfx::Insets((height() - GetLayoutConstant(LOCATION_BAR_HEIGHT)) / 2) +
+      gfx::Insets(
+          (target_size.height() - GetLayoutConstant(LOCATION_BAR_HEIGHT)) / 2) +
       *GetProperty(views::kInternalPaddingKey);
 
   base::Optional<SkColor> background_color =
@@ -234,12 +255,11 @@
     SetBackground(nullptr);
   }
 
-  gfx::Insets target_insets =
-      layout_insets_.value_or(::GetLayoutInsets(TOOLBAR_BUTTON)) +
-      layout_inset_delta_ + *GetProperty(views::kInternalPaddingKey);
+  // Apply new border with target insets.
+
   base::Optional<SkColor> border_color =
       highlight_color_animation_.GetBorderColor();
-  if (!border() || target_insets != border()->GetInsets() ||
+  if (!border() || target_insets != current_insets ||
       last_border_color_ != border_color ||
       last_paint_insets_ != paint_insets) {
     if (border_color) {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index 4abfe45..d4522bb 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -220,6 +220,8 @@
     gfx::SlideAnimation highlight_color_animation_;
   };
 
+  void TouchUiChanged();
+
   // Clears the current highlight, i.e. it sets the label to an empty string and
   // clears the highlight color. If there was a non-empty highlight, previously,
   // it hides the current highlight using an animation. Otherwise, it is a
@@ -295,7 +297,7 @@
 
   base::CallbackListSubscription subscription_ =
       ui::TouchUiController::Get()->RegisterCallback(
-          base::BindRepeating(&ToolbarButton::UpdateIcon,
+          base::BindRepeating(&ToolbarButton::TouchUiChanged,
                               base::Unretained(this)));
 
   // A factory for tasks that show the dropdown context menu for the button.
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
index 498d0b8..febebff 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
@@ -15,6 +15,7 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/models/simple_menu_model.h"
+#include "ui/base/pointer/touch_ui_controller.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/menu/menu_runner.h"
 
@@ -200,20 +201,6 @@
       std::make_unique<views::View>());  // Deletes |button_|.
 }
 
-// Tests to make sure the button's border is updated as its height changes.
-TEST_F(ToolbarButtonUITest, TestBorderUpdateHeightChange) {
-  const gfx::Insets toolbar_padding = GetLayoutInsets(TOOLBAR_BUTTON);
-
-  button_->ResetBorderUpdateFlag();
-  for (int bounds_height : {8, 12, 20}) {
-    EXPECT_FALSE(button_->did_border_update());
-    button_->SetBoundsRect({bounds_height, bounds_height});
-    EXPECT_TRUE(button_->did_border_update());
-    EXPECT_EQ(button_->border()->GetInsets(), gfx::Insets(toolbar_padding));
-    button_->ResetBorderUpdateFlag();
-  }
-}
-
 // Tests to make sure the button's border color is updated as its animation
 // color changes.
 TEST_F(ToolbarButtonUITest, TestBorderUpdateColorChange) {
@@ -229,3 +216,28 @@
     button_->ResetBorderUpdateFlag();
   }
 }
+
+// Ensures ToolbarButton updates its border on touch mode changes to
+// match layout constants.
+//
+// Regression test for crbug.com/1163451: ToolbarButton updates its
+// border on bounds change, which usually happens during layout.
+// Updating the border itself invalidates layout if the border change
+// results in a new preferred size. But View::SetBoundsRect() sets
+// needs_layout_ = false right after the OnBoundsChanged() call.
+//
+// On touch mode changes the border change only happened after several
+// layouts. When the bug occurred, the border was eventually set
+// correctly but too late: its final size did not reflect the preferred
+// size after the border update.
+//
+// This test ensures ToolbarButtons update their border promptly after
+// the touch mode change, just after the icon update.
+TEST_F(ToolbarButtonUITest, BorderUpdatedOnTouchModeSwitch) {
+  ui::TouchUiController::TouchUiScoperForTesting touch_mode_override(false);
+  EXPECT_EQ(button_->GetInsets(), GetLayoutInsets(TOOLBAR_BUTTON));
+
+  // This constant is different in touch mode.
+  touch_mode_override.UpdateState(true);
+  EXPECT_EQ(button_->GetInsets(), GetLayoutInsets(TOOLBAR_BUTTON));
+}
diff --git a/chrome/browser/ui/webui/chrome_web_contents_handler.cc b/chrome/browser/ui/webui/chrome_web_contents_handler.cc
index c7e3359..868c0254 100644
--- a/chrome/browser/ui/webui/chrome_web_contents_handler.cc
+++ b/chrome/browser/ui/webui/chrome_web_contents_handler.cc
@@ -35,13 +35,17 @@
     WebContents* source,
     const OpenURLParams& params) {
   if (!context)
-    return NULL;
+    return nullptr;
 
   Profile* profile = Profile::FromBrowserContext(context);
 
   Browser* browser = chrome::FindTabbedBrowser(profile, false);
   const bool browser_created = !browser;
   if (!browser) {
+    if (Browser::GetCreationStatusForProfile(profile) !=
+        Browser::CreationStatus::kOk) {
+      return nullptr;
+    }
     // TODO(erg): OpenURLParams should pass a user_gesture flag, pass it to
     // CreateParams, and pass the real value to nav_params below.
     browser = Browser::Create(
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index af24b32..f33cae4 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -160,6 +160,10 @@
 constexpr char kCommonStylesHTML[] = "components/common_styles.html";
 constexpr char kI18nBehaviorHTML[] = "components/oobe_i18n_behavior.html";
 constexpr char kI18nBehaviorJS[] = "components/oobe_i18n_behavior.js";
+constexpr char kDialogHostBehaviorHTML[] =
+    "components/oobe_dialog_host_behavior.html";
+constexpr char kDialogHostBehaviorJS[] =
+    "components/oobe_dialog_host_behavior.js";
 constexpr char kFocusBehaviorHTML[] = "components/oobe_focus_behavior.html";
 constexpr char kFocusBehaviorJS[] = "components/oobe_focus_behavior.js";
 constexpr char kScrollableBehaviorHTML[] =
@@ -679,6 +683,10 @@
                           IDR_OOBE_COMPONENTS_I18N_BEHAVIOR_HTML);
   source->AddResourcePath(kI18nBehaviorJS,
                           IDR_OOBE_COMPONENTS_I18N_BEHAVIOR_JS);
+  source->AddResourcePath(kDialogHostBehaviorHTML,
+                          IDR_OOBE_COMPONENTS_DIALOG_HOST_BEHAVIOR_HTML);
+  source->AddResourcePath(kDialogHostBehaviorJS,
+                          IDR_OOBE_COMPONENTS_DIALOG_HOST_BEHAVIOR_JS);
   source->AddResourcePath(kFocusBehaviorHTML,
                           IDR_OOBE_COMPONENTS_FOCUS_BEHAVIOR_HTML);
   source->AddResourcePath(kFocusBehaviorJS,
diff --git a/chrome/browser/ui/webui/devtools_ui.cc b/chrome/browser/ui/webui/devtools_ui.cc
index a8fcfb6..9f2ce2c 100644
--- a/chrome/browser/ui/webui/devtools_ui.cc
+++ b/chrome/browser/ui/webui/devtools_ui.cc
@@ -13,6 +13,7 @@
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
+#include "content/public/common/bindings_policy.h"
 #include "content/public/common/user_agent.h"
 #include "net/base/load_flags.h"
 
@@ -62,7 +63,7 @@
 
 DevToolsUI::DevToolsUI(content::WebUI* web_ui)
     : WebUIController(web_ui), bindings_(web_ui->GetWebContents()) {
-  web_ui->SetBindings(0);
+  web_ui->SetBindings(content::BINDINGS_POLICY_NONE);
   auto factory = content::BrowserContext::GetDefaultStoragePartition(
                      web_ui->GetWebContents()->GetBrowserContext())
                      ->GetURLLoaderFactoryForBrowserProcess();
diff --git a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
index 595c048..5d96f88 100644
--- a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
+++ b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
@@ -175,7 +175,7 @@
 
 void KioskAppsHandler::OnGetConsumerKioskAutoLaunchStatus(
     const std::string& callback_id,
-    chromeos::KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
+    ash::KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
   initialized_ = true;
   if (KioskAppManager::IsConsumerKioskEnabled()) {
     if (!base::SysInfo::IsRunningOnChromeOS()) {
@@ -201,7 +201,6 @@
   ResolveJavascriptCallback(base::Value(callback_id), kiosk_params);
 }
 
-
 void KioskAppsHandler::OnKioskAppsSettingsChanged() {
   FireWebUIListener("kiosk-app-settings-changed", *GetSettingsDictionary());
 }
diff --git a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h
index d20d930..9e87133e 100644
--- a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h
+++ b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h
@@ -20,7 +20,6 @@
 
 namespace chromeos {
 
-class KioskAppManager;
 class OwnerSettingsServiceChromeOS;
 
 class KioskAppsHandler : public content::WebUIMessageHandler,
@@ -61,7 +60,7 @@
   // Callback for KioskAppManager::GetConsumerKioskModeStatus().
   void OnGetConsumerKioskAutoLaunchStatus(
       const std::string& callback_id,
-      chromeos::KioskAppManager::ConsumerKioskAutoLaunchStatus status);
+      KioskAppManager::ConsumerKioskAutoLaunchStatus status);
 
   KioskAppManager* kiosk_app_manager_;  // not owned.
   bool initialized_;
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
index 77de5f8..d36d263 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
@@ -32,7 +32,7 @@
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
   // Send an empty result to simulate a cancelled dialog.
diff --git a/chrome/browser/ui/webui/read_later/read_later.mojom b/chrome/browser/ui/webui/read_later/read_later.mojom
index 34b514f..9803a5dd 100644
--- a/chrome/browser/ui/webui/read_later/read_later.mojom
+++ b/chrome/browser/ui/webui/read_later/read_later.mojom
@@ -53,7 +53,8 @@
 
 // WebUI-side handler for requests from the browser.
 interface Page {
-  // Callback when any item in read later is
-  // changed/removed.
-  ItemsChanged();
+  // Callback when any item in read later is changed/removed. `entries` is a
+  // collection of all read later entries by read/unread status. This data
+  // structure is always present, even if the read/unread lists are empty.
+  ItemsChanged(ReadLaterEntriesByStatus entries);
 };
diff --git a/chrome/browser/ui/webui/read_later/read_later_page_handler.cc b/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
index 2133e64..2ad459d3 100644
--- a/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
+++ b/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
@@ -58,24 +58,7 @@
 
 void ReadLaterPageHandler::GetReadLaterEntries(
     GetReadLaterEntriesCallback callback) {
-  auto entries = read_later::mojom::ReadLaterEntriesByStatus::New();
-
-  for (const auto& url : reading_list_model_->Keys()) {
-    const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
-    DCHECK(entry);
-    if (entry->IsRead()) {
-      entries->read_entries.push_back(GetEntryData(entry));
-    } else {
-      entries->unread_entries.push_back(GetEntryData(entry));
-    }
-  }
-
-  std::sort(entries->read_entries.begin(), entries->read_entries.end(),
-            EntrySorter);
-  std::sort(entries->unread_entries.begin(), entries->unread_entries.end(),
-            EntrySorter);
-
-  std::move(callback).Run(std::move(entries));
+  std::move(callback).Run(CreateReadLaterEntriesByStatusData());
 }
 
 void ReadLaterPageHandler::OpenSavedEntry(const GURL& url) {
@@ -88,12 +71,12 @@
 
 void ReadLaterPageHandler::UpdateReadStatus(const GURL& url, bool read) {
   reading_list_model_->SetReadStatus(url, read);
-  page_->ItemsChanged();
+  page_->ItemsChanged(CreateReadLaterEntriesByStatusData());
 }
 
 void ReadLaterPageHandler::RemoveEntry(const GURL& url) {
   reading_list_model_->RemoveEntryByURL(url);
-  page_->ItemsChanged();
+  page_->ItemsChanged(CreateReadLaterEntriesByStatusData());
 }
 
 void ReadLaterPageHandler::ShowUI() {
@@ -129,6 +112,28 @@
   return entry_data;
 }
 
+read_later::mojom::ReadLaterEntriesByStatusPtr
+ReadLaterPageHandler::CreateReadLaterEntriesByStatusData() {
+  auto entries = read_later::mojom::ReadLaterEntriesByStatus::New();
+
+  for (const auto& url : reading_list_model_->Keys()) {
+    const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
+    DCHECK(entry);
+    if (entry->IsRead()) {
+      entries->read_entries.push_back(GetEntryData(entry));
+    } else {
+      entries->unread_entries.push_back(GetEntryData(entry));
+    }
+  }
+
+  std::sort(entries->read_entries.begin(), entries->read_entries.end(),
+            EntrySorter);
+  std::sort(entries->unread_entries.begin(), entries->unread_entries.end(),
+            EntrySorter);
+
+  return entries;
+}
+
 std::string ReadLaterPageHandler::GetTimeSinceLastUpdate(
     int64_t last_update_time) {
   const int64_t now = TimeToUS(clock_->Now());
diff --git a/chrome/browser/ui/webui/read_later/read_later_page_handler.h b/chrome/browser/ui/webui/read_later/read_later_page_handler.h
index 727b4ba..fe2416b2 100644
--- a/chrome/browser/ui/webui/read_later/read_later_page_handler.h
+++ b/chrome/browser/ui/webui/read_later/read_later_page_handler.h
@@ -47,6 +47,10 @@
   read_later::mojom::ReadLaterEntryPtr GetEntryData(
       const ReadingListEntry* entry);
 
+  // Returns the lists for the read/unread entries.
+  read_later::mojom::ReadLaterEntriesByStatusPtr
+  CreateReadLaterEntriesByStatusData();
+
   // Converts |last_update_time| from microseconds since epoch in Unix-like
   // system (Jan 1, 1970), since this is how ReadingListEntry's |update_time| is
   // stored, to a localized representation as a delay (e.g. "5 minutes ago").
diff --git a/chrome/browser/ui/webui/read_later/read_later_page_handler_unittest.cc b/chrome/browser/ui/webui/read_later/read_later_page_handler_unittest.cc
index 1f95047..20039e7 100644
--- a/chrome/browser/ui/webui/read_later/read_later_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/read_later/read_later_page_handler_unittest.cc
@@ -43,7 +43,8 @@
   }
   mojo::Receiver<read_later::mojom::Page> receiver_{this};
 
-  MOCK_METHOD0(ItemsChanged, void());
+  MOCK_METHOD1(ItemsChanged,
+               void(read_later::mojom::ReadLaterEntriesByStatusPtr));
 };
 
 void ExpectNewReadLaterEntry(const read_later::mojom::ReadLaterEntry* entry,
@@ -160,7 +161,7 @@
 
 TEST_F(TestReadLaterPageHandlerTest, UpdateReadStatus) {
   handler()->UpdateReadStatus(GURL(kTabUrl3), true);
-  EXPECT_CALL(page_, ItemsChanged()).Times(1);
+  EXPECT_CALL(page_, ItemsChanged(testing::_)).Times(1);
 
   // Get Read later entries.
   read_later::mojom::PageHandler::GetReadLaterEntriesCallback callback1 =
@@ -182,7 +183,7 @@
 
 TEST_F(TestReadLaterPageHandlerTest, RemoveEntry) {
   handler()->RemoveEntry(GURL(kTabUrl3));
-  EXPECT_CALL(page_, ItemsChanged()).Times(1);
+  EXPECT_CALL(page_, ItemsChanged(testing::_)).Times(1);
 
   // Get Read later entries.
   read_later::mojom::PageHandler::GetReadLaterEntriesCallback callback1 =
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index 78b8f19..9138b66 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -83,7 +83,7 @@
 }
 
 void TabSearchPageHandler::GetProfileTabs(GetProfileTabsCallback callback) {
-  TRACE_EVENT0("browser", "webui_metric:TabSearchPageHandler:GetProfileTabs");
+  TRACE_EVENT0("browser", "custom_metric:TabSearchPageHandler:GetProfileTabs");
   auto profile_tabs = CreateProfileTabs();
   // On first run record the number of windows and tabs open for the given
   // profile.
@@ -235,7 +235,7 @@
   Browser* browser = chrome::FindBrowserWithWebContents(contents);
   if (!browser)
     return;
-  TRACE_EVENT0("browser", "webui_metric:TabSearchPageHandler:TabChangedAt");
+  TRACE_EVENT0("browser", "custom_metric:TabSearchPageHandler:TabChangedAt");
   page_->TabUpdated(GetTabData(browser->tab_strip_model(), contents, index));
 }
 
diff --git a/chrome/browser/vr/elements/environment/background.cc b/chrome/browser/vr/elements/environment/background.cc
index c90d87e..363c3bc7 100644
--- a/chrome/browser/vr/elements/environment/background.cc
+++ b/chrome/browser/vr/elements/environment/background.cc
@@ -120,7 +120,7 @@
   DCHECK(surface->get());
   SkCanvas* canvas = (*surface)->getCanvas();
   if (bitmap) {
-    canvas->drawBitmap(*bitmap, 0, 0);
+    canvas->drawImage(bitmap->asImage(), 0, 0);
   } else {
     // If we are missing a gradient image, blending with channels at .5 will
     // have no effect -- it will be as if there is no gradient image.
diff --git a/chrome/browser/web_applications/manifest_update_manager.cc b/chrome/browser/web_applications/manifest_update_manager.cc
index 5b77c1b..e940435 100644
--- a/chrome/browser/web_applications/manifest_update_manager.cc
+++ b/chrome/browser/web_applications/manifest_update_manager.cc
@@ -85,8 +85,8 @@
   tasks_.insert_or_assign(
       app_id, std::make_unique<ManifestUpdateTask>(
                   url, app_id, web_contents,
-                  base::Bind(&ManifestUpdateManager::OnUpdateStopped,
-                             base::Unretained(this)),
+                  base::BindOnce(&ManifestUpdateManager::OnUpdateStopped,
+                                 base::Unretained(this)),
                   hang_update_checks_for_testing_, *registrar_, *icon_manager_,
                   ui_manager_, install_manager_));
 }
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index dea04cc..0c6fd77e 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -497,8 +497,8 @@
             policy::policy_prefs::kSystemFeaturesDisableList)) {
       local_state_pref_change_registrar_.Add(
           policy::policy_prefs::kSystemFeaturesDisableList,
-          base::Bind(&SystemWebAppManager::OnAppsPolicyChanged,
-                     base::Unretained(this)));
+          base::BindRepeating(&SystemWebAppManager::OnAppsPolicyChanged,
+                              base::Unretained(this)));
     }
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/win/chrome_select_file_dialog_factory.cc b/chrome/browser/win/chrome_select_file_dialog_factory.cc
index 49f097c..f32d0146 100644
--- a/chrome/browser/win/chrome_select_file_dialog_factory.cc
+++ b/chrome/browser/win/chrome_select_file_dialog_factory.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/win/win_util.h"
 #include "chrome/browser/win/util_win_service.h"
 #include "chrome/services/util_win/public/mojom/util_win.mojom.h"
@@ -32,7 +33,7 @@
       const base::FilePath& default_path,
       const std::vector<ui::FileFilterSpec>& filter,
       int file_type_index,
-      const base::string16& default_extension,
+      const std::wstring& default_extension,
       HWND owner,
       ui::OnSelectFileExecutedCallback on_select_file_executed_callback);
 
@@ -43,7 +44,7 @@
       const base::FilePath& default_path,
       const std::vector<ui::FileFilterSpec>& filter,
       int file_type_index,
-      const base::string16& default_extension,
+      const std::wstring& default_extension,
       HWND owner,
       ui::OnSelectFileExecutedCallback on_select_file_executed_callback);
 
@@ -74,7 +75,7 @@
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
   // Self-deleting when the select file operation completes.
@@ -89,7 +90,7 @@
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     ui::OnSelectFileExecutedCallback on_select_file_executed_callback)
     : on_select_file_executed_callback_(
@@ -103,7 +104,7 @@
 
   remote_util_win_->CallExecuteSelectFile(
       type, base::win::HandleToUint32(owner), title, default_path, filter,
-      file_type_index, default_extension,
+      file_type_index, base::WideToUTF16(default_extension),
       base::BindOnce(&UtilWinHelper::OnSelectFileExecuted,
                      base::Unretained(this)));
 }
@@ -134,7 +135,7 @@
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
   UtilWinHelper::ExecuteSelectFile(type, title, default_path, filter,
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index c7b9640e..711b775 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1612179896-0409fbe35d3488924f5047acaa71269a53440493.profdata
+chrome-mac-master-1612202232-c23514403c27d1c9a0bd5d8f832db00108891fa1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 1d31d22..5f80317 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1612179896-83f6077cb5f304792ffbe6980e38ce94ebc2ed7b.profdata
+chrome-win64-master-1612190886-bd867870b3b3c51f0e6b887ea8b6b36e612aaa64.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 1dda102..dfaa1b2 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -197,8 +197,8 @@
       deps += [
         "//ash/public/cpp/resources:ash_public_unscaled_resources",
         "//chrome/browser/resources:bluetooth_pairing_dialog_resources",
-        "//chrome/browser/resources/chromeos:cellular_setup_resources",
         "//chrome/browser/resources/chromeos:multidevice_setup_resources",
+        "//chrome/browser/resources/chromeos/cellular_setup:resources",
         "//chrome/browser/resources/chromeos/emoji_picker:resources",
         "//chrome/browser/resources/chromeos/multidevice_internals:resources",
         "//chrome/browser/resources/nearby_internals:resources",
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 3d667bcf..bfa277a 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -180,6 +180,7 @@
     "//components/favicon_base",
     "//components/flags_ui:switches",
     "//components/gcm_driver/common",
+    "//components/memories/common",
     "//components/metrics",
     "//components/metrics:net",
     "//components/nacl/common:buildflags",
diff --git a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
index 104e68e..e03b043 100644
--- a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
+++ b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
@@ -114,7 +114,9 @@
   dest_rect.offset(delta_x, delta_y);
   SkRect dino_bounds;
   dino_bitmap_.getBounds(&dino_bounds);
-  canvas->drawBitmapRect(dino_bitmap_, dino_bounds, dest_rect, nullptr);
+  canvas->drawImageRect(dino_bitmap_.asImage(), dino_bounds, dest_rect,
+                        SkSamplingOptions(), nullptr,
+                        SkCanvas::kStrict_SrcRectConstraint);
 }
 
 // Draws QR locators at three corners of |canvas|.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0c77b9d..ba86a767 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3871,7 +3871,6 @@
       "../browser/android/history_report/delta_file_backend_leveldb_unittest.cc",
       "../browser/android/history_report/delta_file_commons_unittest.cc",
       "../browser/android/history_report/usage_reports_buffer_backend_unittest.cc",
-      "../browser/android/javascript/web_context_fetcher_util_unittest.cc",
       "../browser/android/locale/locale_template_url_loader_unittest.cc",
       "../browser/android/metrics/background_task_memory_metrics_emitter_unittest.cc",
       "../browser/android/oom_intervention/near_oom_monitor_unittest.cc",
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc
index 4881bcc2..fd094fca 100644
--- a/chrome/test/base/browser_with_test_window_test.cc
+++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -108,7 +108,7 @@
   // If initialized, the KioskAppManager will register an observer to
   // CrosSettings and will need to be destroyed before it. Having it destroyed
   // as part of the teardown will avoid unexpected test failures.
-  chromeos::KioskAppManager::Shutdown();
+  ash::KioskAppManager::Shutdown();
 
   test_views_delegate_.reset();
   ash_test_helper_.TearDown();
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
index f8723ec..a26013b 100644
--- a/chrome/test/data/autofill/captured_sites/testcases.json
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
@@ -3,7 +3,7 @@
     { "site_name": "1aauto" },
     { "site_name": "aarons" },
     { "site_name": "abebooks" },
-    { "site_name": "abercrombie", "expectation":"FAIL", "disabled":true, "bug_number":984664 },
+    { "site_name": "abercrombie", "disabled":true, "bug_number":1172845 },
     { "site_name": "academy" },
     { "site_name": "accesscorrections" },
     { "site_name": "aeropostale" },
@@ -13,20 +13,20 @@
     { "site_name": "apple" },
     { "site_name": "autoanything" },
     { "site_name": "avon" },
-    { "site_name": "barnes_and_noble" },
+    { "site_name": "barnes_and_noble", "bug_number":1172847 },
     { "site_name": "bath_and_body_works" },
     { "site_name": "beachbody" },
     { "site_name": "bed_bath_beyond" },
     { "site_name": "belk" },
     { "site_name": "bestbuy" },
-    { "site_name": "bhphotovideo", "disabled":true, "bug_number":1017266 },
+    { "site_name": "bhphotovideo", "disabled":true, "bug_number":1173033 },
     { "site_name": "bloomingdales" },
     { "site_name": "bodybuilding" },
     { "site_name": "booking" },
     { "site_name": "boostmobile" },
     { "site_name": "bradfordexchange" },
     { "site_name": "brandfactoryonline" },
-    { "site_name": "bricklink", "disabled":true, "bug_number":1159936 },
+    { "site_name": "bricklink", "bug_number":1172846 },
     { "site_name": "broadway" },
     { "site_name": "brownells" },
     { "site_name": "cabelas" },
@@ -47,7 +47,7 @@
     { "site_name": "chewy" },
     { "site_name": "cinemark" },
     { "site_name": "coach" },
-    { "site_name": "collage" },
+    { "site_name": "collage", "bug_number":1172848 },
     { "site_name": "container_store" },
     { "site_name": "coolstuffinc" },
     { "site_name": "crate_and_barrel" },
@@ -57,26 +57,26 @@
     { "site_name": "customink" },
     { "site_name": "cvs" },
     { "site_name": "davidsbridal" },
-    { "site_name": "dell", "disabled":true, "bug_number":993044 },
+    { "site_name": "dell", "bug_number":1172945 },
     { "site_name": "dickblick" },
     { "site_name": "dicks_sporting_goods" },
     { "site_name": "dish" },
     { "site_name": "dsw" },
-    { "site_name": "duluthtrading", "disabled":true, "bug_number":1041744},
+    { "site_name": "duluthtrading", "disabled":true, "bug_number":1173034 },
     { "site_name": "ebags" },
-    { "site_name": "ebay", "disabled":true, "bug_number":984664 },
+    { "site_name": "ebay", "bug_number":1172711 },
     { "site_name": "eddiebauer" },
-    { "site_name": "elementvape", "disabled":true, "bug_number":984664 },
+    { "site_name": "elementvape", "bug_number":1172700 },
     { "site_name": "etsy" },
     { "site_name": "evo" },
-    { "site_name": "expedia", "disabled":true, "bug_number":1101864 },
+    { "site_name": "expedia", "disabled":true, "bug_number":1173035 },
     { "site_name": "fanatics" },
     { "site_name": "fansedge" },
-    { "site_name": "fender", "disabled":true, "bug_number":1151204 },
+    { "site_name": "fender", "disabled":true, "bug_number":1173036 },
     { "site_name": "findmeagift" },
     { "site_name": "fingerhut" },
     { "site_name": "finish_line" },
-    { "site_name": "forever21", "disabled":true, "bug_number":984664 },
+    { "site_name": "forever21", "disabled":true, "bug_number":1172701 },
     { "site_name": "fromyouflowers" },
     { "site_name": "frys" },
     { "site_name": "gamestop" },
@@ -106,14 +106,14 @@
     { "site_name": "juno" },
     { "site_name": "just_fab" },
     { "site_name": "kmart" },
-    { "site_name": "kohls", "disabled":true, "bug_number":1006308 },
+    { "site_name": "kohls", "bug_number":1172702 },
     { "site_name": "levi" },
     { "site_name": "living_social" },
     { "site_name": "llbean" },
     { "site_name": "lordandtaylor" },
     { "site_name": "lowes" },
-    { "site_name": "lululemon", "disabled":true, "bug_number":1033737 },
-    { "site_name": "macys", "disabled":true, "bug_number":984664 },
+    { "site_name": "lululemon", "disabled":true, "bug_number":1173032 },
+    { "site_name": "macys", "bug_number":1172851 },
     { "site_name": "mango" },
     { "site_name": "mapsofindia" },
     { "site_name": "mercurypay" },
@@ -140,16 +140,16 @@
     { "site_name": "northerntool" },
     { "site_name": "notonthehighstreet" },
     { "site_name": "nyandcompany" },
-    { "site_name": "omahasteaks", "disabled":true, "bug_number":984664 },
+    { "site_name": "omahasteaks", "disabled":true, "bug_number":1172703 },
     { "site_name": "opticsplanet" },
     { "site_name": "oriental_trading" },
     { "site_name": "oshkosh" },
     { "site_name": "oup" },
     { "site_name": "overstock" },
-    { "site_name": "pac_sun", "expectation":"FAIL", "bug_number":1090042 },
+    { "site_name": "pac_sun", "expectation":"FAIL", "bug_number":1173037 },
     { "site_name": "palmettostatearmory" },
     { "site_name": "pandora" },
-    { "site_name": "panerabread", "disabled":true, "bug_number":984664 },
+    { "site_name": "panerabread", "bug_number":1172704 },
     { "site_name": "paparazziaccessories" },
     { "site_name": "partycity" },
     { "site_name": "payless" },
@@ -157,7 +157,7 @@
     { "site_name": "pets_mart" },
     { "site_name": "pier1" },
     { "site_name": "pizzahut_uk" },
-    { "site_name": "polar", "disabled":true, "bug_number":984664 },
+    { "site_name": "polar", "bug_number":1172705 },
     { "site_name": "pottery_barn" },
     { "site_name": "priceline" },
     { "site_name": "prima_games" },
@@ -186,7 +186,7 @@
     { "site_name": "ticketmaster_uk" },
     { "site_name": "tickets" },
     { "site_name": "tiger_direct" },
-    { "site_name": "tillys", "disabled":true, "bug_number":1101866 },
+    { "site_name": "tillys", "bug_number":1172707 },
     { "site_name": "timberland", "disabled":true, "bug_number":1159947 },
     { "site_name": "tirerack" },
     { "site_name": "torrid" },
@@ -197,19 +197,19 @@
     { "site_name": "vanillagift" },
     { "site_name": "vans" },
     { "site_name": "venus" },
-    { "site_name": "verizonwireless", "disabled":true, "bug_number":1006308 },
+    { "site_name": "verizonwireless", "bug_number":1172706 },
     { "site_name": "victorias_secret" },
     { "site_name": "vitacost" },
     { "site_name": "walgreen" },
     { "site_name": "walmart" },
     { "site_name": "walmart_ca" },
     { "site_name": "walmartmoneycard" },
-    { "site_name": "warby_parker", "disabled":true, "bug_number":1033737 },
+    { "site_name": "warby_parker", "disabled":true, "bug_number":1173039 },
     { "site_name": "wayfair" },
     { "site_name": "west_elm" },
     { "site_name": "wiley" },
     { "site_name": "williams_sonoma" },
-    { "site_name": "worldmarket", "disabled":true, "bug_number":1006322 },
+    { "site_name": "worldmarket", "disabled":true, "bug_number":1173040 },
     { "site_name": "zappos" },
     { "site_name": "zenni_optical" },
     { "site_name": "zulily" }
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index f6ed108..437a82eb 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -7792,6 +7792,64 @@
     ]
   },
 
+  "SendDownloadToCloudEnterpriseConnector": {
+    "os": [ "win", "linux", "mac", "chromeos" ],
+    "policy_pref_mapping_tests": [
+      {
+        "policies": {
+          "SendDownloadToCloudEnterpriseConnector": [
+            {
+              "service_provider": "Google",
+              "enterprise_id": "1234567890",
+              "enable": [
+                {
+                  "url_list": [ "*" ],
+                  "mime_types": [ "text/plain" ]
+                },
+                {
+                  "url_list": [ "*.them.com", "*.others.com" ],
+                  "mime_types": [ "image/png" ]
+                }
+              ],
+              "disable": [
+                {
+                  "url_list": [ "*.us.com" ],
+                  "mime_types": [ "application/zip" ]
+                }
+              ]
+            }
+          ]
+        },
+        "prefs": {
+          "enterprise_connectors.send_download_to_cloud": {
+             "value":  [
+              {
+                "service_provider": "Google",
+                "enterprise_id": "1234567890",
+                "enable": [
+                  {
+                    "url_list": [ "*" ],
+                    "mime_types": [ "text/plain" ]
+                  },
+                  {
+                    "url_list": [ "*.them.com", "*.others.com" ],
+                    "mime_types": [ "image/png" ]
+                  }
+                ],
+                "disable": [
+                  {
+                    "url_list": [ "*.us.com" ],
+                    "mime_types": [ "application/zip" ]
+                  }
+                ]
+              }
+            ]
+          }
+        }
+      }
+    ]
+  },
+
   "OnFileAttachedEnterpriseConnector": {
     "os": ["win", "linux", "mac", "chromeos"],
     "policy_pref_mapping_tests": [
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 75ee1f4..3bb4de6e 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -331,6 +331,8 @@
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_receive_manager.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/google_assistant_page_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/guest_os_shared_paths_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/guest_os_shared_usb_devices_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/input_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/internet_config_test.m.js",
@@ -375,6 +377,7 @@
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/switch_access_action_assignment_dialog_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_cups_printers_browser_proxy.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_guest_os_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_os_languages_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_os_languages_metrics_proxy.m.js",
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 34223f6..e29b316 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -50,6 +50,8 @@
     "fake_settings_search_handler.js",
     "fake_user_action_recorder.js",
     "google_assistant_page_test.js",
+    "guest_os_shared_paths_test.js",
+    "guest_os_shared_usb_devices_test.js",
     "input_method_options_page_test.js",
     "input_page_test.js",
     "internet_config_test.js",
@@ -97,6 +99,7 @@
     "test_about_page_browser_proxy_chromeos.js",
     "test_cups_printers_browser_proxy.js",
     "test_device_name_browser_proxy.js",
+    "test_guest_os_browser_proxy.js",
     "test_multidevice_browser_proxy.js",
     "test_os_languages_browser_proxy.js",
     "test_os_languages_metrics_proxy.js",
diff --git a/chrome/test/data/webui/settings/chromeos/guest_os_shared_paths_test.js b/chrome/test/data/webui/settings/chromeos/guest_os_shared_paths_test.js
index 71f1da73..bae1060 100644
--- a/chrome/test/data/webui/settings/chromeos/guest_os_shared_paths_test.js
+++ b/chrome/test/data/webui/settings/chromeos/guest_os_shared_paths_test.js
@@ -2,6 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {flush} from'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+// #import {GuestOsBrowserProxyImpl} from 'chrome://os-settings/chromeos/os_settings.js';
+// clang-format on
+
 /** @implements {settings.GuestOsBrowserProxy} */
 class TestGuestOsBrowserProxy extends TestBrowserProxy {
   constructor() {
diff --git a/chrome/test/data/webui/settings/chromeos/guest_os_shared_usb_devices_test.js b/chrome/test/data/webui/settings/chromeos/guest_os_shared_usb_devices_test.js
index e8865046..4ffdcb44 100644
--- a/chrome/test/data/webui/settings/chromeos/guest_os_shared_usb_devices_test.js
+++ b/chrome/test/data/webui/settings/chromeos/guest_os_shared_usb_devices_test.js
@@ -2,6 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {flush} from'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+// #import {GuestOsBrowserProxyImpl} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {eventToPromise, flushTasks} from 'chrome://test/test_util.m.js';
+// clang-format on
+
 /** @implements {settings.GuestOsBrowserProxy} */
 class TestGuestOsBrowserProxy extends TestBrowserProxy {
   constructor() {
diff --git a/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni b/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
index 6515c0c..a6e3b36e 100644
--- a/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
+++ b/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
@@ -14,6 +14,7 @@
                                "settings.FakeSettingsPrivate|FakeSettingsPrivate",
                                "settings.getFakeLanguagePrefs|getFakeLanguagePrefs",
                                "settings.MultiDeviceSettingsMode|MultiDeviceSettingsMode",
+                               "settings.TestGuestOsBrowserProxy|TestGuestOsBrowserProxy",
                                "settings.TestLanguagesBrowserProxy|TestLanguagesBrowserProxy",
                                "settings.TestLanguagesMetricsProxy|TestLanguagesMetricsProxy",
                                "settings.TestLifetimeBrowserProxy|TestLifetimeBrowserProxy",
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 882cfcf..c650530 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -208,6 +208,8 @@
  ['EsimRenameDialog', 'esim_rename_dialog_test.m.js'],
  ['FilesPage', 'os_files_page_test.m.js'],
  ['GoogleAssistantPage', 'google_assistant_page_test.m.js'],
+ ['GuestOsSharedPaths', 'guest_os_shared_paths_test.m.js'],
+ ['GuestOsSharedUsbDevices', 'guest_os_shared_usb_devices_test.m.js'],
  ['InputMethodOptionPage', 'input_method_options_page_test.m.js'],
  ['InputPage', 'input_page_test.m.js'],
  ['InternetConfig', 'internet_config_test.m.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/test_guest_os_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_guest_os_browser_proxy.js
index eb4838d..6e3f396 100644
--- a/chrome/test/data/webui/settings/chromeos/test_guest_os_browser_proxy.js
+++ b/chrome/test/data/webui/settings/chromeos/test_guest_os_browser_proxy.js
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+// clang-format on
+
 /** @implements {settings.GuestOsBrowserProxy} */
 class TestGuestOsBrowserProxy extends TestBrowserProxy {
   constructor() {
diff --git a/chrome/test/data/webui/tab_strip/drag_manager_test.js b/chrome/test/data/webui/tab_strip/drag_manager_test.js
index c21cf5c..bf58ed9 100644
--- a/chrome/test/data/webui/tab_strip/drag_manager_test.js
+++ b/chrome/test/data/webui/tab_strip/drag_manager_test.js
@@ -715,6 +715,25 @@
     assertEquals(dragDetails.clientY, clientY);
   });
 
+  test('DropPlaceholderWithoutMovingDoesNotShowContextMenu', () => {
+    const externalTabId = 1000;
+    const mockDataTransfer = new MockDataTransfer();
+    mockDataTransfer.setData(strings.tabIdDataType, `${externalTabId}`);
+    const dragEnterEvent = new DragEvent('dragenter', {
+      bubbles: true,
+      composed: true,
+      dataTransfer: mockDataTransfer,
+    });
+    delegate.dispatchEvent(dragEnterEvent);
+    delegate.dispatchEvent(new DragEvent('drop', {
+      bubbles: true,
+      composed: true,
+      dataTransfer: mockDataTransfer,
+    }));
+    assertEquals(
+        0, testTabStripEmbedderProxy.getCallCount('showTabContextMenu'));
+  });
+
   test('DragEndWithDropEffectMoveDoesNotRemoveDraggedOutAttribute', () => {
     const draggedTab = delegate.children[0];
     const dataTransfer = new MockDataTransfer();
@@ -751,7 +770,7 @@
     assertFalse(draggedTab.isDraggedOut());
   });
 
-  test('DragIsPrevented', () => {
+  test('DragIsPrevented', async () => {
     // Mock the delegate to return true for shouldPreventDrag.
     delegate.shouldPreventDrag = () => true;
 
@@ -771,5 +790,12 @@
       dataTransfer,
     }));
     assertTrue(isDefaultPrevented);
+
+    // The tab's context menu should be opened instead.
+    const [tabId, x, y] =
+        await testTabStripEmbedderProxy.whenCalled('showTabContextMenu');
+    assertEquals(draggedTab.tab.id, tabId);
+    assertEquals(100, x);
+    assertEquals(150, y);
   });
 });
diff --git a/chromecast/media/cma/BUILD.gn b/chromecast/media/cma/BUILD.gn
index d177387..86f25df 100644
--- a/chromecast/media/cma/BUILD.gn
+++ b/chromecast/media/cma/BUILD.gn
@@ -81,6 +81,7 @@
   if (!is_android) {
     sources += [
       "backend/proxy/audio_decoder_pipeline_node_unittest.cc",
+      "backend/proxy/buffer_id_manager_unittest.cc",
       "backend/proxy/cma_backend_proxy_unittest.cc",
       "backend/proxy/proxy_call_translator_unittest.cc",
       "backend/proxy/push_buffer_queue_unittest.cc",
diff --git a/chromecast/media/cma/backend/proxy/BUILD.gn b/chromecast/media/cma/backend/proxy/BUILD.gn
index a21a29c..2465acf 100644
--- a/chromecast/media/cma/backend/proxy/BUILD.gn
+++ b/chromecast/media/cma/backend/proxy/BUILD.gn
@@ -36,6 +36,8 @@
   sources = [
     "audio_decoder_pipeline_node.cc",
     "audio_decoder_pipeline_node.h",
+    "buffer_id_manager.cc",
+    "buffer_id_manager.h",
     "cast_runtime_audio_channel_broker.cc",
     "cast_runtime_audio_channel_broker.h",
     "cma_backend_proxy.cc",
diff --git a/chromecast/media/cma/backend/proxy/buffer_id_manager.cc b/chromecast/media/cma/backend/proxy/buffer_id_manager.cc
new file mode 100644
index 0000000..341962c
--- /dev/null
+++ b/chromecast/media/cma/backend/proxy/buffer_id_manager.cc
@@ -0,0 +1,109 @@
+// Copyright 2020 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 "chromecast/media/cma/backend/proxy/buffer_id_manager.h"
+
+#include <cmath>
+
+#include "base/callback.h"
+#include "base/callback_forward.h"
+#include "base/rand_util.h"
+#include "base/time/time.h"
+#include "chromecast/public/media/decoder_config.h"
+#include "chromecast/public/media/media_pipeline_device_params.h"
+
+namespace chromecast {
+namespace media {
+namespace {
+
+// Mask to apply to a uint64_t to get a BufferId.
+constexpr uint64_t kBufferIdMask = (uint64_t{1} << 63) - 1;
+
+}  // namespace
+
+BufferIdManager::BufferIdQueue::BufferIdQueue() {
+  next_id_ = base::RandUint64();
+}
+
+BufferIdManager::BufferId BufferIdManager::BufferIdQueue::Front() {
+  return static_cast<int64_t>(next_id_ & kBufferIdMask);
+}
+
+BufferIdManager::BufferId BufferIdManager::BufferIdQueue::Pop() {
+  BufferIdManager::BufferId id = Front();
+  next_id_++;
+  return id;
+}
+
+BufferIdManager::BufferInfo::BufferInfo(
+    BufferId buffer_id,
+    double buffer_playback_time_in_microseconds)
+    : id(buffer_id),
+      playback_time_in_microseconds(buffer_playback_time_in_microseconds) {}
+
+BufferIdManager::BufferIdManager(CmaBackend::AudioDecoder* audio_decoder)
+    : audio_decoder_(audio_decoder), weak_factory_(this) {
+  DCHECK(audio_decoder_);
+}
+
+BufferIdManager::~BufferIdManager() = default;
+
+void BufferIdManager::SetAudioConfig(const AudioConfig& config) {
+  bytes_per_microsecond_ = config.bytes_per_channel * config.channel_number *
+                           (static_cast<double>(config.samples_per_second) /
+                            base::Time::kMicrosecondsPerSecond);
+}
+
+BufferIdManager::BufferId BufferIdManager::AssignBufferId(
+    size_t buffer_size_in_bytes) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(bytes_per_microsecond_);
+
+  PruneBufferInfos();
+
+  const double additional_playback_time =
+      static_cast<double>(buffer_size_in_bytes) / bytes_per_microsecond_;
+  buffer_infos_.emplace(buffer_id_queue_.Front(), additional_playback_time);
+  pending_playback_time_in_microseconds_ += additional_playback_time;
+  return buffer_id_queue_.Pop();
+}
+
+BufferIdManager::BufferId BufferIdManager::GetCurrentlyProcessingBuffer() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  PruneBufferInfos();
+  if (buffer_infos_.empty()) {
+    return buffer_id_queue_.Front() == 0 ? 0 : buffer_id_queue_.Front() - 1;
+  }
+
+  return buffer_infos_.front().id;
+}
+
+void BufferIdManager::PruneBufferInfos() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!isnan(pending_playback_time_in_microseconds_));
+
+  const auto rendering_delay = audio_decoder_->GetRenderingDelay();
+
+  // Special case meaning that the Rendering Delay is unavailable.
+  if (rendering_delay.timestamp_microseconds ==
+      std::numeric_limits<int64_t>::min()) {
+    return;
+  }
+
+  const double delay_in_microseconds = rendering_delay.delay_microseconds;
+  DCHECK_GE(delay_in_microseconds, 0);
+  while (delay_in_microseconds < pending_playback_time_in_microseconds_ &&
+         !buffer_infos_.empty()) {
+    const BufferInfo& oldest_buffer = buffer_infos_.front();
+    DCHECK_NE(oldest_buffer.id, -1);
+    DCHECK_NE(oldest_buffer.playback_time_in_microseconds, -1);
+    pending_playback_time_in_microseconds_ -=
+        oldest_buffer.playback_time_in_microseconds;
+    buffer_infos_.pop();
+  }
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/cma/backend/proxy/buffer_id_manager.h b/chromecast/media/cma/backend/proxy/buffer_id_manager.h
new file mode 100644
index 0000000..115621a
--- /dev/null
+++ b/chromecast/media/cma/backend/proxy/buffer_id_manager.h
@@ -0,0 +1,121 @@
+// Copyright 2020 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 CHROMECAST_MEDIA_CMA_BACKEND_PROXY_BUFFER_ID_MANAGER_H_
+#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_BUFFER_ID_MANAGER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <queue>
+
+#include "base/sequence_checker.h"
+#include "chromecast/media/api/cma_backend.h"
+
+namespace chromecast {
+namespace media {
+
+struct AudioConfig;
+
+// This class is responsible for assigning the IDs for PushBuffer commands sent
+// over the CastRuntimeAudioChannel. Each PushBuffer command is expected to have
+// an increasing BufferId (with the exception of wrap-around of large integers),
+// to be used for audio synchronization between playback in the runtime and any
+// further processing or work done on the other side of the gRPC Channel.
+//
+// This class does NOT attempt to track the association between a given
+// PushBuffer and its ID. Instead, it tracks the number of bytes of playback
+// data associated with each frame. By calculating the number of bytes
+// associated with one microsecond of PushBuffer data, the currently playing
+// buffer ID can then be calculated by using the GetRenderingDelay() function
+// provided by a CmaBackend::AudioDecoder, which gives the total amount of time
+// of playback data currently pending in the AudioDecoder's internal queue.
+//
+// Specifically, if this calculation yields that X bytes of data are currently
+// pending in the AudioDecoder's queue, this means that the buffer which is
+// followed by (approximately) X bytes of data is (probably). While this
+// algorithm does not yield an exact result, the human ear cannot differentiate
+// the amount of delay this approximation can introduce.
+class BufferIdManager {
+ public:
+  using BufferId = int64_t;
+
+  // |audio_decoder| is expected to remain valid for the lifetime of this
+  // instance.
+  explicit BufferIdManager(CmaBackend::AudioDecoder* audio_decoder);
+  ~BufferIdManager();
+
+  // Sets the audio config to use for future buffer pushes. This |config| is
+  // used to calculate the number of bytes of data per microsecond of audio
+  // playback.
+  void SetAudioConfig(const AudioConfig& audio_config);
+
+  // Assigns the BufferId to use with the buffer for which it is called. This
+  // value is used to keep a running tally of the number of bytes of audio
+  // data being processed, as described in the class-level documentation. May
+  // not be called prior to the first call to SetAudioConfig().
+  BufferId AssignBufferId(size_t buffer_size_in_bytes);
+
+  // Returns the APPROXIMATE BufferId which is currently being rendered by the
+  // underlying CmaBackend. Note that, although this is not exact, the human
+  // ear cannot perceive variation  on the level introduced by this slight
+  // mismatch.
+  BufferId GetCurrentlyProcessingBuffer();
+
+ private:
+  // A wrapper around the buffer ID that acts for users like a queue.
+  class BufferIdQueue {
+   public:
+    BufferIdQueue();
+
+    BufferIdManager::BufferId Front();
+    BufferIdManager::BufferId Pop();
+
+   private:
+    // The next id to use, initialized to a random number upon creation.
+    // NOTE: A uint64_t is used rather than an int64_t to allow for buffer
+    // overflow and wrap-around-to-zero without crashing the runtime.
+    uint64_t next_id_;
+  };
+
+  struct BufferInfo {
+    // NOTE: Ctor added to support vector::emplace calls.
+    BufferInfo(BufferId buffer_id, double buffer_playback_time_in_microseconds);
+
+    // The ID of the current buffer.
+    BufferId id = -1;
+
+    // The duration of time in microseconds of playback which will be rendered
+    // by the CmaBackend when the associated buffer is processed (as number of
+    // bytes of data in this buffer divided by the number of bytes-per-second of
+    // audio playback). This must be tracked rather than the number of bytes in
+    // the source buffer to allow for changes to the audio config part way
+    // through playback.
+    double playback_time_in_microseconds = -1;
+  };
+
+  // Uses the provided AudioDecoder to calculate approximately how many buffers
+  // are remaining in the PushBuffer queue, removes all buffers expected to
+  // have already played out. This ensures that |buffer_infos_| size does not
+  // grow in an unbounded fashion.
+  void PruneBufferInfos();
+
+  // The total playback time of all buffers currently in |buffer_infos|.
+  double pending_playback_time_in_microseconds_ = 0;
+
+  // Number of bytes per second of media playback. This will change each time
+  // that SetAudioConfig() is called.
+  double bytes_per_microsecond_ = 0;
+
+  BufferIdQueue buffer_id_queue_;
+  std::queue<BufferInfo> buffer_infos_;
+  CmaBackend::AudioDecoder* const audio_decoder_;
+  SEQUENCE_CHECKER(sequence_checker_);
+  base::WeakPtrFactory<BufferIdManager> weak_factory_;
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_BUFFER_ID_MANAGER_H_
diff --git a/chromecast/media/cma/backend/proxy/buffer_id_manager_unittest.cc b/chromecast/media/cma/backend/proxy/buffer_id_manager_unittest.cc
new file mode 100644
index 0000000..f37e31a1
--- /dev/null
+++ b/chromecast/media/cma/backend/proxy/buffer_id_manager_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2020 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 "chromecast/media/cma/backend/proxy/buffer_id_manager.h"
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "chromecast/media/api/cma_backend.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+namespace {
+
+class MockAudioDecoder : public CmaBackend::AudioDecoder {
+ public:
+  ~MockAudioDecoder() override = default;
+
+  MOCK_METHOD1(SetDelegate, void(CmaBackend::Decoder::Delegate*));
+  MOCK_METHOD1(PushBuffer, BufferStatus(scoped_refptr<DecoderBufferBase>));
+  MOCK_METHOD1(SetConfig, bool(const AudioConfig&));
+  MOCK_METHOD1(SetVolume, bool(float));
+  MOCK_METHOD0(GetRenderingDelay, RenderingDelay());
+  MOCK_METHOD1(GetStatistics, void(Statistics*));
+  MOCK_METHOD0(RequiresDecryption, bool());
+  MOCK_METHOD1(SetObserver, void(Observer*));
+};
+
+}  // namespace
+
+class BufferIdManagerTest : public testing::Test {
+ public:
+  BufferIdManagerTest()
+      : id_manager_(std::make_unique<BufferIdManager>(&audio_decoder_)) {}
+  ~BufferIdManagerTest() override = default;
+
+ protected:
+  testing::StrictMock<MockAudioDecoder> audio_decoder_;
+  std::unique_ptr<BufferIdManager> id_manager_;
+};
+
+TEST_F(BufferIdManagerTest, TestDelayedFrames) {
+  AudioConfig config;
+  config.bytes_per_channel = 100;
+  config.channel_number = 20;
+  config.samples_per_second = 5000;
+  id_manager_->SetAudioConfig(config);
+
+  constexpr double kBytesPerMicrosecond = 10;
+  EXPECT_CALL(audio_decoder_, GetRenderingDelay())
+      .Times(3)
+      .WillRepeatedly(
+          testing::Return(MediaPipelineBackend::AudioDecoder::RenderingDelay(
+              1000 * kBytesPerMicrosecond, 0)));
+  BufferIdManager::BufferId i =
+      id_manager_->AssignBufferId(30 * kBytesPerMicrosecond);
+  BufferIdManager::BufferId j =
+      id_manager_->AssignBufferId(40 * kBytesPerMicrosecond);
+  BufferIdManager::BufferId k =
+      id_manager_->AssignBufferId(50 * kBytesPerMicrosecond);
+  EXPECT_EQ(i + 1, j);
+  EXPECT_EQ(j + 1, k);
+
+  EXPECT_CALL(audio_decoder_, GetRenderingDelay())
+      .WillOnce(testing::Return(
+          MediaPipelineBackend::AudioDecoder::RenderingDelay(150, 0)));
+  EXPECT_EQ(id_manager_->GetCurrentlyProcessingBuffer(), i);
+
+  EXPECT_CALL(audio_decoder_, GetRenderingDelay())
+      .WillOnce(testing::Return(
+          MediaPipelineBackend::AudioDecoder::RenderingDelay(100, 0)));
+  EXPECT_EQ(id_manager_->GetCurrentlyProcessingBuffer(), j);
+
+  EXPECT_CALL(audio_decoder_, GetRenderingDelay())
+      .WillOnce(testing::Return(
+          MediaPipelineBackend::AudioDecoder::RenderingDelay(60, 0)));
+  EXPECT_EQ(id_manager_->GetCurrentlyProcessingBuffer(), k);
+
+  EXPECT_CALL(audio_decoder_, GetRenderingDelay())
+      .WillOnce(testing::Return(
+          MediaPipelineBackend::AudioDecoder::RenderingDelay(0, 0)));
+  EXPECT_EQ(id_manager_->GetCurrentlyProcessingBuffer(), k);
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromeos/components/connectivity_diagnostics/connectivity_diagnostics_ui.cc b/chromeos/components/connectivity_diagnostics/connectivity_diagnostics_ui.cc
index a0a1619a..5a8d11af 100644
--- a/chromeos/components/connectivity_diagnostics/connectivity_diagnostics_ui.cc
+++ b/chromeos/components/connectivity_diagnostics/connectivity_diagnostics_ui.cc
@@ -21,22 +21,14 @@
 namespace chromeos {
 
 namespace {
-constexpr char kGeneratedPath[] =
-    "@out_folder@/gen/chromeos/components/connectivity_diagnostics/"
-    "resources/preprocessed/";
 
 // TODO(crbug/1051793): Replace with webui::SetUpWebUIDataSource() once it no
 // longer requires a dependency on //chrome/browser.
 void SetUpWebUIDataSource(content::WebUIDataSource* source,
                           base::span<const GritResourceMap> resources,
-                          const std::string& generated_path,
                           int default_resource) {
   for (const auto& resource : resources) {
-    std::string path = resource.name;
-    if (path.rfind(generated_path, 0) == 0)
-      path = path.substr(generated_path.size());
-
-    source->AddResourcePath(path, resource.value);
+    source->AddResourcePath(resource.name, resource.value);
   }
 
   source->SetDefaultResource(default_resource);
@@ -76,7 +68,7 @@
 
   const auto resources = base::make_span(kConnectivityDiagnosticsResources,
                                          kConnectivityDiagnosticsResourcesSize);
-  SetUpWebUIDataSource(source, resources, kGeneratedPath,
+  SetUpWebUIDataSource(source, resources,
                        IDR_CONNECTIVITY_DIAGNOSTICS_INDEX_HTML);
   source->AddLocalizedString("appTitle", IDS_CONNECTIVITY_DIAGNOSTICS_TITLE);
   source->AddLocalizedString("networkDevicesLabel",
diff --git a/chromeos/login/auth/auth_status_consumer.h b/chromeos/login/auth/auth_status_consumer.h
index d01a208..623ad1af 100644
--- a/chromeos/login/auth/auth_status_consumer.h
+++ b/chromeos/login/auth/auth_status_consumer.h
@@ -152,4 +152,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::AuthFailure;
+}
+
 #endif  // CHROMEOS_LOGIN_AUTH_AUTH_STATUS_CONSUMER_H_
diff --git a/chromeos/login/auth/login_performer.h b/chromeos/login/auth/login_performer.h
index 93ca64a89..e27a86e 100644
--- a/chromeos/login/auth/login_performer.h
+++ b/chromeos/login/auth/login_performer.h
@@ -220,4 +220,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace ash {
+using ::chromeos::LoginPerformer;
+}
+
 #endif  // CHROMEOS_LOGIN_AUTH_LOGIN_PERFORMER_H_
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h
index 25b362c..023469a 100644
--- a/chromeos/login/auth/user_context.h
+++ b/chromeos/login/auth/user_context.h
@@ -186,4 +186,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when the //chrome/browser/chromeos
+// source code migration is finished.
+namespace ash {
+using ::chromeos::UserContext;
+}
+
 #endif  // CHROMEOS_LOGIN_AUTH_USER_CONTEXT_H_
diff --git a/chromeos/network/network_handler.h b/chromeos/network/network_handler.h
index aa2cc223..36b44f0 100644
--- a/chromeos/network/network_handler.h
+++ b/chromeos/network/network_handler.h
@@ -135,4 +135,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to  ash/components/.
+namespace ash {
+using ::chromeos::NetworkHandler;
+}
+
 #endif  // CHROMEOS_NETWORK_NETWORK_HANDLER_H_
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index 4f9d087..d90f3859 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -142,6 +142,8 @@
     return GetIntegerValue(key, value, &priority_);
   } else if (key == shill::kOutOfCreditsProperty) {
     return GetBooleanValue(key, value, &cellular_out_of_credits_);
+  } else if (key == shill::kIccidProperty) {
+    return GetStringValue(key, value, &iccid_);
   } else if (key == kCellularEidProperty) {
     return GetStringValue(key, value, &eid_);
   } else if (key == shill::kProxyConfigProperty) {
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index 5891ff9b..acc1e826c 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -136,6 +136,7 @@
 
   // Cellular property accessors
   const std::string& eid() const { return eid_; }
+  const std::string& iccid() const { return iccid_; }
   const std::string& network_technology() const { return network_technology_; }
   const std::string& activation_type() const { return activation_type_; }
   const std::string& activation_state() const { return activation_state_; }
@@ -327,6 +328,7 @@
 
   // Cellular properties, used for icons, Connect, and Activation.
   std::string eid_;
+  std::string iccid_;
   std::string network_technology_;
   std::string activation_type_;
   std::string activation_state_;
diff --git a/chromeos/network/network_type_pattern.h b/chromeos/network/network_type_pattern.h
index 13d8da6c..debf392 100644
--- a/chromeos/network/network_type_pattern.h
+++ b/chromeos/network/network_type_pattern.h
@@ -75,4 +75,9 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when moved to ash/components/.
+namespace ash {
+using ::chromeos::NetworkTypePattern;
+}
+
 #endif  // CHROMEOS_NETWORK_NETWORK_TYPE_PATTERN_H_
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index a9d2040e..826f746 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -151,6 +151,21 @@
   return !redirect_logging;
 }
 
+libassistant::mojom::AndroidAppStatus ToMojomEnum(const AppStatus& app_status) {
+  switch (app_status) {
+    case AppStatus::kAvailable:
+      return libassistant::mojom::AndroidAppStatus::kAvailable;
+    case AppStatus::kUnavailable:
+      return libassistant::mojom::AndroidAppStatus::kUnavailable;
+    case AppStatus::kDisabled:
+      return libassistant::mojom::AndroidAppStatus::kDisabled;
+    case AppStatus::kUnknown:
+      return libassistant::mojom::AndroidAppStatus::kUnknown;
+    case AppStatus::kVersionMismatch:
+      return libassistant::mojom::AndroidAppStatus::kVersionMismatch;
+  }
+}
+
 libassistant::mojom::AndroidAppInfoPtr ToAndroidAppInfoPtr(
     const AndroidAppInfo& app_info) {
   auto result = libassistant::mojom::AndroidAppInfo::New();
@@ -158,6 +173,9 @@
   result->package_name = app_info.package_name;
   result->version = app_info.version;
   result->localized_app_name = app_info.localized_app_name;
+  result->intent = app_info.intent;
+  result->status = ToMojomEnum(app_info.status);
+  result->action = app_info.action;
 
   return result;
 }
diff --git a/chromeos/services/libassistant/public/mojom/android_app_info.mojom b/chromeos/services/libassistant/public/mojom/android_app_info.mojom
index c7b1953b..65ee591 100644
--- a/chromeos/services/libassistant/public/mojom/android_app_info.mojom
+++ b/chromeos/services/libassistant/public/mojom/android_app_info.mojom
@@ -14,6 +14,15 @@
 
   // Localized app name.
   string localized_app_name;
+
+  // Intent data to operate on.
+  string intent;
+
+  // Status of the app.
+  AndroidAppStatus status = kUnknown;
+
+  // The general action to be performed, such as ACTION_VIEW, ACTION_MAIN, etc.
+  string action;
 };
 
 // Models status of an app.
@@ -24,4 +33,3 @@
   kVersionMismatch,
   kDisabled,
 };
-
diff --git a/chromeos/services/libassistant/public/mojom/conversation_controller.mojom b/chromeos/services/libassistant/public/mojom/conversation_controller.mojom
index c367799..da52d1a 100644
--- a/chromeos/services/libassistant/public/mojom/conversation_controller.mojom
+++ b/chromeos/services/libassistant/public/mojom/conversation_controller.mojom
@@ -66,3 +66,12 @@
   // Raw data (non-encoded binary octets)
   array<uint8> screenshot_png;
 };
+
+// Models a device setting.
+struct DeviceSetting {
+  // Unique id to identify a specific setting.
+  string setting_id;
+
+  // True if the specific setting is supported.
+  bool is_supported;
+};
diff --git a/chromeos/services/libassistant/util.cc b/chromeos/services/libassistant/util.cc
index a6819546..af0f8c96 100644
--- a/chromeos/services/libassistant/util.cc
+++ b/chromeos/services/libassistant/util.cc
@@ -12,9 +12,20 @@
 #include "base/values.h"
 #include "build/util/webkit_version.h"
 #include "chromeos/assistant/internal/internal_constants.h"
+#include "chromeos/assistant/internal/util_headers.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/services/assistant/public/cpp/features.h"
 
+using chromeos::assistant::shared::ClientInteraction;
+using chromeos::assistant::shared::ClientOpResult;
+using chromeos::assistant::shared::GetDeviceSettingsResult;
+using chromeos::assistant::shared::Interaction;
+using chromeos::assistant::shared::Protobuf;
+using chromeos::assistant::shared::ProviderVerificationResult;
+using chromeos::assistant::shared::ResponseCode;
+using chromeos::assistant::shared::SettingInfo;
+using chromeos::assistant::shared::VerifyProviderClientOpResult;
+
 namespace chromeos {
 namespace libassistant {
 
@@ -44,6 +55,97 @@
   return home_dir;
 }
 
+ProviderVerificationResult::VerificationStatus GetProviderVerificationStatus(
+    libassistant::mojom::AndroidAppStatus status) {
+  switch (status) {
+    case libassistant::mojom::AndroidAppStatus::kUnknown:
+      return ProviderVerificationResult::UNKNOWN;
+    case libassistant::mojom::AndroidAppStatus::kAvailable:
+      return ProviderVerificationResult::AVAILABLE;
+    case libassistant::mojom::AndroidAppStatus::kUnavailable:
+      return ProviderVerificationResult::UNAVAILABLE;
+    case libassistant::mojom::AndroidAppStatus::kVersionMismatch:
+      return ProviderVerificationResult::VERSION_MISMATCH;
+    case libassistant::mojom::AndroidAppStatus::kDisabled:
+      return ProviderVerificationResult::DISABLED;
+  }
+}
+
+SettingInfo ToSettingInfo(bool is_supported) {
+  SettingInfo result;
+  result.set_available(is_supported);
+  result.set_setting_status(is_supported
+                                ? SettingInfo::AVAILABLE_AND_MODIFY_SUPPORTED
+                                : SettingInfo::UNAVAILABLE);
+  return result;
+}
+
+// Helper class used for constructing V1 interaction proto messages.
+class V1InteractionBuilder {
+ public:
+  V1InteractionBuilder() = default;
+  V1InteractionBuilder(V1InteractionBuilder&) = delete;
+  V1InteractionBuilder& operator=(V1InteractionBuilder&) = delete;
+  ~V1InteractionBuilder() = default;
+
+  V1InteractionBuilder& SetInResponseTo(int interaction_id) {
+    interaction_.set_in_response_to(interaction_id);
+    return *this;
+  }
+
+  V1InteractionBuilder& AddResult(
+      const std::string& key,
+      const google::protobuf::MessageLite& result_proto) {
+    auto* result = client_op_result()->mutable_results()->add_result();
+    result->set_key(key);
+    result->mutable_value()->set_protobuf_type(result_proto.GetTypeName());
+    result->mutable_value()->set_protobuf_data(
+        result_proto.SerializeAsString());
+    return *this;
+  }
+
+  V1InteractionBuilder& SetStatusCode(ResponseCode::Status status_code) {
+    ResponseCode* response_code = client_op_result()->mutable_response_code();
+    response_code->set_status_code(status_code);
+    return *this;
+  }
+
+  // Set the status code to |OK| (if true) or |NOT_FOUND| (if false).
+  V1InteractionBuilder& SetStatusCodeFromEntityFound(bool found) {
+    SetStatusCode(found ? ResponseCode::OK : ResponseCode::NOT_FOUND);
+    return *this;
+  }
+
+  V1InteractionBuilder& SetClientInputName(const std::string& name) {
+    auto* client_input = client_interaction()->mutable_client_input();
+    client_input->set_client_input_name(name);
+    return *this;
+  }
+
+  V1InteractionBuilder& AddClientInputParams(
+      const std::string& key,
+      const google::protobuf::MessageLite& params_proto) {
+    auto* client_input = client_interaction()->mutable_client_input();
+    Protobuf& value = (*client_input->mutable_params())[key];
+    value.set_protobuf_type(params_proto.GetTypeName());
+    value.set_protobuf_data(params_proto.SerializeAsString());
+    return *this;
+  }
+
+  std::string SerializeAsString() { return interaction_.SerializeAsString(); }
+
+ private:
+  ClientInteraction* client_interaction() {
+    return interaction_.mutable_from_client();
+  }
+
+  ClientOpResult* client_op_result() {
+    return client_interaction()->mutable_client_op_result();
+  }
+
+  Interaction interaction_;
+};
+
 }  // namespace
 
 base::FilePath GetBaseAssistantDir() {
@@ -159,5 +261,52 @@
   return json;
 }
 
+std::string CreateVerifyProviderResponseInteraction(
+    const int interaction_id,
+    const std::vector<libassistant::mojom::AndroidAppInfoPtr>& apps_info) {
+  // Construct verify provider result proto.
+  VerifyProviderClientOpResult result_proto;
+  bool any_provider_available = false;
+  for (const auto& android_app_info : apps_info) {
+    auto* provider_status = result_proto.add_provider_status();
+    provider_status->set_status(
+        GetProviderVerificationStatus(android_app_info->status));
+    auto* app_info =
+        provider_status->mutable_provider_info()->mutable_android_app_info();
+    app_info->set_package_name(android_app_info->package_name);
+    app_info->set_app_version(android_app_info->version);
+    app_info->set_localized_app_name(android_app_info->localized_app_name);
+    app_info->set_android_intent(android_app_info->intent);
+
+    if (android_app_info->status ==
+        libassistant::mojom::AndroidAppStatus::kAvailable)
+      any_provider_available = true;
+  }
+
+  // Construct response interaction.
+  return V1InteractionBuilder()
+      .SetInResponseTo(interaction_id)
+      .SetStatusCodeFromEntityFound(any_provider_available)
+      .AddResult(assistant::kResultKeyVerifyProvider, result_proto)
+      .SerializeAsString();
+}
+
+std::string CreateGetDeviceSettingInteraction(
+    int interaction_id,
+    const std::vector<libassistant::mojom::DeviceSettingPtr>& device_settings) {
+  GetDeviceSettingsResult result_proto;
+  for (const auto& setting : device_settings) {
+    (*result_proto.mutable_settings_info())[setting->setting_id] =
+        ToSettingInfo(setting->is_supported);
+  }
+
+  // Construct response interaction.
+  return V1InteractionBuilder()
+      .SetInResponseTo(interaction_id)
+      .SetStatusCode(ResponseCode::OK)
+      .AddResult(/*key=*/assistant::kResultKeyGetDeviceSettings, result_proto)
+      .SerializeAsString();
+}
+
 }  // namespace libassistant
 }  // namespace chromeos
diff --git a/chromeos/services/libassistant/util.h b/chromeos/services/libassistant/util.h
index d76e8ac..0add026d 100644
--- a/chromeos/services/libassistant/util.h
+++ b/chromeos/services/libassistant/util.h
@@ -6,7 +6,10 @@
 #define CHROMEOS_SERVICES_LIBASSISTANT_UTIL_H_
 
 #include <string>
+
 #include "base/optional.h"
+#include "chromeos/services/libassistant/public/mojom/android_app_info.mojom.h"
+#include "chromeos/services/libassistant/public/mojom/conversation_controller.mojom.h"
 
 namespace base {
 class FilePath;
@@ -24,6 +27,14 @@
 // Returns the path where all downloaded LibAssistant resources are stored.
 base::FilePath GetBaseAssistantDir();
 
+std::string CreateVerifyProviderResponseInteraction(
+    const int interaction_id,
+    const std::vector<libassistant::mojom::AndroidAppInfoPtr>& apps_info);
+
+std::string CreateGetDeviceSettingInteraction(
+    int interaction_id,
+    const std::vector<libassistant::mojom::DeviceSettingPtr>& device_settings);
+
 }  // namespace libassistant
 }  // namespace chromeos
 
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
index 1d8f1e4a..c452224 100644
--- a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
+++ b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
@@ -549,7 +549,7 @@
   bool infer_callback_done = false;
   recognizer->Recognize(
       std::move(query),
-      base::Bind(
+      base::BindOnce(
           [](bool* infer_callback_done,
              mojom::HandwritingRecognizerResultPtr result) {
             *infer_callback_done = true;
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h
index 0336104..b932ec3 100644
--- a/chromeos/settings/cros_settings_names.h
+++ b/chromeos/settings/cros_settings_names.h
@@ -280,4 +280,19 @@
 extern const char kDeviceShowLowDiskSpaceNotification[];
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove when migrated to ash/components/.
+namespace ash {
+using ::chromeos::kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled;
+using ::chromeos::kAccountsPrefDeviceLocalAccountAutoLoginDelay;
+using ::chromeos::kAccountsPrefDeviceLocalAccountAutoLoginId;
+using ::chromeos::kAccountsPrefDeviceLocalAccounts;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyArcKioskAction;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyArcKioskClass;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyArcKioskDisplayName;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyArcKioskPackage;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyId;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId;
+using ::chromeos::kAccountsPrefDeviceLocalAccountsKeyType;
+}  // namespace ash
+
 #endif  // CHROMEOS_SETTINGS_CROS_SETTINGS_NAMES_H_
diff --git a/codelabs/cpp101/codelab.md b/codelabs/cpp101/codelab.md
index ddac55c0..13cd52b7 100644
--- a/codelabs/cpp101/codelab.md
+++ b/codelabs/cpp101/codelab.md
@@ -205,9 +205,9 @@
 
 `base::SequencedTaskRunner` (which extends `base::TaskRunner`) is a commonly
 used abstraction which handles running tasks (which are instances
-of `base::Closure`) in sequential order. These tasks are not guaranteed to run
-on the same thread. The preferred way of posting to the current (virtual) thread
-is `base::SequencedTaskRunnerHandle::Get()`.
+of `base::OnceClosure`) in sequential order. These tasks are not guaranteed to
+run on the same thread. The preferred way of posting to the current (virtual)
+thread is `base::SequencedTaskRunnerHandle::Get()`.
 
 A task that can run on any thread and doesn’t have ordering or mutual exclusion
 requirements with other tasks should be posted using one of the
diff --git a/components/autofill/ios/browser/BUILD.gn b/components/autofill/ios/browser/BUILD.gn
index 30efed8..5d55496 100644
--- a/components/autofill/ios/browser/BUILD.gn
+++ b/components/autofill/ios/browser/BUILD.gn
@@ -41,12 +41,15 @@
     "//components/autofill/ios/form_util",
     "//components/prefs:prefs",
     "//components/prefs/ios",
+    "//components/ukm/ios:ukm_url_recorder",
     "//google_apis",
     "//ios/web/common",
     "//ios/web/public",
     "//ios/web/public/deprecated",
     "//ios/web/public/js_messaging",
     "//ios/web/public/security",
+    "//services/metrics/public/cpp:metrics_cpp",
+    "//services/metrics/public/cpp:ukm_builders",
     "//services/network/public/cpp",
     "//ui/accessibility",
     "//ui/gfx/geometry",
@@ -96,6 +99,7 @@
     "//ios/web/public/js_messaging",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
+    "//services/metrics/public/cpp:ukm_builders",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/components/autofill/ios/browser/DEPS b/components/autofill/ios/browser/DEPS
index cfaa9b0..c11a8a4 100644
--- a/components/autofill/ios/browser/DEPS
+++ b/components/autofill/ios/browser/DEPS
@@ -1,6 +1,8 @@
 include_rules = [
+  "+components/ukm/ios",
   "+ios/web/common",
   "+ios/web/public",
+  "+services/metrics/public",
   "+services/network/public/cpp",
   "+third_party/ocmock",
 ]
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index 4142961..422adbc 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -50,6 +50,7 @@
 #import "components/prefs/ios/pref_observer_bridge.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
+#include "components/ukm/ios/ukm_url_recorder.h"
 #include "ios/web/common/url_scheme_util.h"
 #include "ios/web/public/deprecated/url_verification_constants.h"
 #include "ios/web/public/js_messaging/web_frame.h"
@@ -58,6 +59,7 @@
 #import "ios/web/public/navigation/navigation_context.h"
 #import "ios/web/public/web_state.h"
 #import "ios/web/public/web_state_observer_bridge.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "ui/gfx/geometry/rect.h"
 #include "url/gurl.h"
 
@@ -107,35 +109,6 @@
   }
 }
 
-void UpdateFieldManagerWithFillingResults(
-    scoped_refptr<FieldDataManager> fieldDataManager,
-    NSString* jsonString,
-    size_t numFieldsInFormData) {
-  std::map<uint32_t, base::string16> fillingResults;
-  if (autofill::ExtractFillingResults(jsonString, &fillingResults)) {
-    for (auto& fillData : fillingResults) {
-      fieldDataManager->UpdateFieldDataMap(FieldRendererId(fillData.first),
-                                           fillData.second,
-                                           kAutofilledOnUserTrigger);
-    }
-  }
-  // TODO(crbug/1131038): Remove once the experiment is over.
-  UMA_HISTOGRAM_BOOLEAN("Autofill.FormFillSuccessIOS", !fillingResults.empty());
-}
-
-void UpdateFieldManagerForClearedIDs(
-    scoped_refptr<FieldDataManager> fieldDataManager,
-    NSString* jsonString) {
-  std::vector<uint32_t> clearingResults;
-  if (autofill::ExtractIDs(jsonString, &clearingResults)) {
-    for (auto uniqueID : clearingResults) {
-      fieldDataManager->UpdateFieldDataMap(FieldRendererId(uniqueID),
-                                           base::string16(),
-                                           kAutofilledOnUserTrigger);
-    }
-  }
-}
-
 }  // namespace
 
 @interface AutofillAgent () <CRWWebStateObserver,
@@ -426,6 +399,17 @@
   completion(_mostRecentSuggestions, self);
 }
 
+- (void)updateFieldManagerForClearedIDs:(NSString*)jsonString {
+  std::vector<uint32_t> clearingResults;
+  if (autofill::ExtractIDs(jsonString, &clearingResults)) {
+    for (auto uniqueID : clearingResults) {
+      _fieldDataManager->UpdateFieldDataMap(FieldRendererId(uniqueID),
+                                            base::string16(),
+                                            kAutofilledOnUserTrigger);
+    }
+  }
+}
+
 - (void)didSelectSuggestion:(FormSuggestion*)suggestion
                        form:(NSString*)formName
                uniqueFormID:(FormRendererId)uniqueFormID
@@ -472,8 +456,8 @@
                          AutofillAgent* strongSelf = weakSelf;
                          if (!strongSelf)
                            return;
-                         UpdateFieldManagerForClearedIDs(
-                             strongSelf->_fieldDataManager, jsonString);
+                         [strongSelf
+                             updateFieldManagerForClearedIDs:jsonString];
                          suggestionHandledCompletionCopy();
                        }];
 
@@ -941,6 +925,24 @@
         }];
 }
 
+- (void)updateFieldManagerWithFillingResults:(NSString*)jsonString {
+  std::map<uint32_t, base::string16> fillingResults;
+  if (autofill::ExtractFillingResults(jsonString, &fillingResults)) {
+    for (auto& fillData : fillingResults) {
+      _fieldDataManager->UpdateFieldDataMap(FieldRendererId(fillData.first),
+                                            fillData.second,
+                                            kAutofilledOnUserTrigger);
+    }
+  }
+  // TODO(crbug/1131038): Remove once the experiment is over.
+  UMA_HISTOGRAM_BOOLEAN("Autofill.FormFillSuccessIOS", !fillingResults.empty());
+
+  ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(_webState);
+  ukm::builders::Autofill_FormFillSuccessIOS(source_id)
+      .SetFormFillSuccess(!fillingResults.empty())
+      .Record(ukm::UkmRecorder::Get());
+}
+
 // Sends the the |data| to |frame| to actually fill the data.
 - (void)sendData:(std::unique_ptr<base::Value>)data
          toFrame:(web::WebFrame*)frame {
@@ -949,7 +951,6 @@
   SuggestionHandledCompletion suggestionHandledCompletionCopy =
       [_suggestionHandledCompletion copy];
   _suggestionHandledCompletion = nil;
-  size_t numFieldsInFormData = data->FindPath("fields")->DictSize();
   [_jsAutofillManager fillForm:std::move(data)
       forceFillFieldIdentifier:SysUTF16ToNSString(_pendingAutocompleteField)
         forceFillFieldUniqueID:_pendingAutocompleteFieldID
@@ -958,9 +959,7 @@
                AutofillAgent* strongSelf = weakSelf;
                if (!strongSelf)
                  return;
-               UpdateFieldManagerWithFillingResults(
-                   strongSelf->_fieldDataManager, jsonString,
-                   numFieldsInFormData);
+               [strongSelf updateFieldManagerWithFillingResults:jsonString];
                // It is possible that the fill was not initiated by selecting
                // a suggestion in this case the callback is nil.
                if (suggestionHandledCompletionCopy)
diff --git a/components/autofill/ios/browser/autofill_agent_unittests.mm b/components/autofill/ios/browser/autofill_agent_unittests.mm
index 8a24f8b8..2e1a8d3 100644
--- a/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -4,6 +4,7 @@
 
 #import "components/autofill/ios/browser/autofill_agent.h"
 
+#include "base/mac/bundle_locations.h"
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "base/test/scoped_feature_list.h"
@@ -18,11 +19,15 @@
 #import "components/autofill/ios/browser/js_autofill_manager.h"
 #include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
 #include "components/prefs/pref_service.h"
+#include "ios/web/public/js_messaging/web_frame_util.h"
 #include "ios/web/public/test/fakes/fake_browser_state.h"
+#include "ios/web/public/test/fakes/fake_web_client.h"
 #include "ios/web/public/test/fakes/fake_web_frame.h"
 #import "ios/web/public/test/fakes/fake_web_frames_manager.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #include "ios/web/public/test/web_task_environment.h"
+#import "ios/web/public/test/web_test_with_web_state.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -38,9 +43,14 @@
 using autofill::POPUP_ITEM_ID_CLEAR_FORM;
 using autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS;
 using autofill::FormRendererId;
+using autofill::FieldDataManager;
 using autofill::FieldRendererId;
 using base::test::ios::WaitUntilCondition;
 
+@interface AutofillAgent (Testing)
+- (void)updateFieldManagerWithFillingResults:(NSString*)jsonString;
+@end
+
 // Subclass of web::FakeWebFrame that allow to set a callback before any
 // JavaScript call. This callback can be used to check the state of the page.
 class FakeWebFrameCallback : public web::FakeWebFrame {
@@ -646,3 +656,23 @@
   RemoveWebFrame(main_frame->GetFrameId());
   RemoveWebFrame(iframe->GetFrameId());
 }
+
+TEST_F(AutofillAgentTests, UpdateFieldManagerWithFillingResults) {
+  auto test_recorder = std::make_unique<ukm::TestAutoSetUkmRecorder>();
+
+  [autofill_agent_ updateFieldManagerWithFillingResults:@"{\"1\":\"Val1\"}"];
+
+  // Check recorded FieldDataManager data.
+  UniqueIDDataTabHelper* uniqueIDDataTabHelper =
+      UniqueIDDataTabHelper::FromWebState(&fake_web_state_);
+  scoped_refptr<FieldDataManager> fieldDataManager =
+      uniqueIDDataTabHelper->GetFieldDataManager();
+  EXPECT_TRUE(fieldDataManager->WasAutofilledOnUserTrigger(FieldRendererId(1)));
+
+  // Check recorded UKM.
+  auto entries = test_recorder->GetEntriesByName(
+      ukm::builders::Autofill_FormFillSuccessIOS::kEntryName);
+  // Expect one recorded metric.
+  ASSERT_EQ(1u, entries.size());
+  test_recorder->ExpectEntryMetric(entries[0], "FormFillSuccess", true);
+}
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java
index bb2f036d..4ec537d 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java
@@ -38,6 +38,15 @@
     void cancel(Context context, int taskId);
 
     /**
+     * Checks if a task specified by the task ID is currently scheduled.
+     *
+     * @param context the current context.
+     * @param taskId the ID of the task to check. See {@link TaskIds} for a list.
+     */
+    @MainThread
+    boolean isScheduled(Context context, int taskId);
+
+    /**
      * Checks whether OS was upgraded and triggers rescheduling if it is necessary.
      * Rescheduling is necessary if type of background task scheduler delegate is different for a
      * new version of the OS.
diff --git a/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImpl.java b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImpl.java
index 40dc884c..6dd27c4 100644
--- a/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImpl.java
+++ b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImpl.java
@@ -148,6 +148,16 @@
     }
 
     @Override
+    public boolean isScheduled(Context context, int taskId) {
+        try (TraceEvent te = TraceEvent.scoped(
+                     "BackgroundTaskScheduler.isScheduled", Integer.toString(taskId))) {
+            ThreadUtils.assertOnUiThread();
+
+            return (BackgroundTaskSchedulerPrefs.getScheduledTask(taskId) != null);
+        }
+    }
+
+    @Override
     public void checkForOSUpgrade(Context context) {
         try (TraceEvent te = TraceEvent.scoped("BackgroundTaskScheduler.checkForOSUpgrade")) {
             ThreadUtils.assertOnUiThread();
diff --git a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplTest.java b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplTest.java
index c29abef..c9656fc 100644
--- a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplTest.java
+++ b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplTest.java
@@ -149,9 +149,23 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
+    public void testIsScheduled() {
+        BackgroundTaskSchedulerPrefs.addScheduledTask(mTask);
+        assertTrue(BackgroundTaskSchedulerFactoryInternal.getScheduler().isScheduled(
+                RuntimeEnvironment.application, TaskIds.TEST));
+
+        doNothing().when(mDelegate).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+        BackgroundTaskSchedulerFactoryInternal.getScheduler().cancel(
+                RuntimeEnvironment.application, TaskIds.TEST);
+        verify(mDelegate, times(1)).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+        assertFalse(BackgroundTaskSchedulerFactoryInternal.getScheduler().isScheduled(
+                RuntimeEnvironment.application, TaskIds.TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
     public void testCancelExactTask() {
         BackgroundTaskSchedulerPrefs.addScheduledTask(mExactTask);
-
         doNothing()
                 .when(mAlarmManagerDelegate)
                 .cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
diff --git a/components/exo/wayland/clients/blur.cc b/components/exo/wayland/clients/blur.cc
index d941feb..9538016 100644
--- a/components/exo/wayland/clients/blur.cc
+++ b/components/exo/wayland/clients/blur.cc
@@ -73,7 +73,7 @@
   // Draw background grid.
   SkPaint paint;
   paint.setBlendMode(SkBlendMode::kSrc);
-  canvas->drawImage(background_grid_image, 0, 0, &paint);
+  canvas->drawImage(background_grid_image, 0, 0, SkSamplingOptions(), &paint);
 
   // Draw rotated rectangles.
   SkScalar rect_size =
@@ -172,8 +172,8 @@
                         size.height() / content_surfaces.back()->height());
           SkPaint paint;
           paint.setBlendMode(SkBlendMode::kSrc);
-          paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
-          content_surfaces.back()->draw(canvas, 0, 0, &paint);
+          content_surfaces.back()->draw(
+              canvas, 0, 0, SkSamplingOptions(SkFilterMode::kLinear), &paint);
         }
 
         canvas->restore();
@@ -194,12 +194,12 @@
                     size.height() / blur_image->height());
       SkPaint paint;
       paint.setBlendMode(SkBlendMode::kSrc);
-      paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
+      SkSamplingOptions sampling(SkFilterMode::kLinear);
       // Simulate multi-texturing by adding foreground opacity.
       int alpha = (1.0 - kForegroundOpacity) * 255.0 + 0.5;
       paint.setColor(SkColorSetA(SK_ColorBLACK, alpha));
       canvas->drawImage(blurred_image, offset.x() - subset.x(),
-                        offset.y() - subset.y(), &paint);
+                        offset.y() - subset.y(), sampling, &paint);
       canvas->restore();
 
       // Restore blur surfaces for next frame.
diff --git a/components/favicon_base/favicon_util.cc b/components/favicon_base/favicon_util.cc
index 2458d92d..f1280aa7 100644
--- a/components/favicon_base/favicon_util.cc
+++ b/components/favicon_base/favicon_util.cc
@@ -16,6 +16,7 @@
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "ui/base/layout.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/favicon_size.h"
@@ -128,8 +129,9 @@
       bitmap.eraseARGB(0, 0, 0, 0);
 
     SkCanvas canvas(bitmap, SkSurfaceProps{});
-    canvas.drawBitmapRect(best_bitmap,
-                          SkRect::MakeIWH(desired_size, desired_size), nullptr);
+    canvas.drawImageRect(best_bitmap.asImage(),
+                         SkRect::MakeIWH(desired_size, desired_size),
+                         SkSamplingOptions());
     return bitmap;
   }
   return skia::ImageOperations::Resize(best_bitmap,
diff --git a/components/favicon_base/select_favicon_frames.cc b/components/favicon_base/select_favicon_frames.cc
index 6d482593..7aba4c2 100644
--- a/components/favicon_base/select_favicon_frames.cc
+++ b/components/favicon_base/select_favicon_frames.cc
@@ -16,6 +16,7 @@
 #include "components/favicon_base/favicon_util.h"
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia.h"
@@ -44,8 +45,9 @@
 
   {
     SkCanvas canvas(bitmap, SkSurfaceProps{});
-    canvas.drawBitmapRect(contents, SkRect::MakeIWH(desired_size, desired_size),
-                          nullptr);
+    canvas.drawImageRect(contents.asImage(),
+                         SkRect::MakeIWH(desired_size, desired_size),
+                         SkSamplingOptions());
   }
 
   return bitmap;
diff --git a/components/memories/DIR_METADATA b/components/memories/DIR_METADATA
new file mode 100644
index 0000000..88f25f6
--- /dev/null
+++ b/components/memories/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Memories"
+}
diff --git a/components/memories/OWNERS b/components/memories/OWNERS
new file mode 100644
index 0000000..edfcc666
--- /dev/null
+++ b/components/memories/OWNERS
@@ -0,0 +1,7 @@
+jdonnelly@chromium.org
+mahmadi@chromium.org
+manukh@chromium.org
+mcrouse@chromium.org
+robertogden@chromium.org
+sophiechang@chromium.org
+tommycli@chromium.org
diff --git a/components/memories/README.md b/components/memories/README.md
new file mode 100644
index 0000000..bacfdad
--- /dev/null
+++ b/components/memories/README.md
@@ -0,0 +1,6 @@
+# //components/memories
+
+Service implementation for Chrome Memories history clustering feature.
+
+This is implemented as a component to allow //components/omnibox to depend on
+this feature, as well as future iOS compatibility.
diff --git a/components/memories/browser/BUILD.gn b/components/memories/browser/BUILD.gn
new file mode 100644
index 0000000..f8f0c40
--- /dev/null
+++ b/components/memories/browser/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2021 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.
+
+static_library("browser") {
+  sources = [
+    "memories_service.cc",
+    "memories_service.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/keyed_service/core",
+  ]
+}
diff --git a/components/memories/browser/DEPS b/components/memories/browser/DEPS
new file mode 100644
index 0000000..f0bf3d9
--- /dev/null
+++ b/components/memories/browser/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/keyed_service/core",
+]
diff --git a/components/memories/browser/memories_service.cc b/components/memories/browser/memories_service.cc
new file mode 100644
index 0000000..e3b7789
--- /dev/null
+++ b/components/memories/browser/memories_service.cc
@@ -0,0 +1,13 @@
+// Copyright 2021 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/memories/browser/memories_service.h"
+
+namespace memories {
+
+MemoriesService::~MemoriesService() = default;
+
+void MemoriesService::Shutdown() {}
+
+}  // namespace memories
diff --git a/components/memories/browser/memories_service.h b/components/memories/browser/memories_service.h
new file mode 100644
index 0000000..86d6e510
--- /dev/null
+++ b/components/memories/browser/memories_service.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MEMORIES_BROWSER_MEMORIES_SERVICE_H_
+#define COMPONENTS_MEMORIES_BROWSER_MEMORIES_SERVICE_H_
+
+#include "base/macros.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace memories {
+
+// This Service is the API for UIs to fetch Chrome Memories.
+class MemoriesService : public KeyedService {
+ public:
+  MemoriesService() = default;
+  ~MemoriesService() override;
+
+  // KeyedService:
+  void Shutdown() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MemoriesService);
+};
+
+}  // namespace memories
+
+#endif  // COMPONENTS_MEMORIES_BROWSER_MEMORIES_SERVICE_H_
diff --git a/components/memories/common/BUILD.gn b/components/memories/common/BUILD.gn
new file mode 100644
index 0000000..00d4204
--- /dev/null
+++ b/components/memories/common/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2021 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.
+
+source_set("common") {
+  sources = [
+    "memories_features.cc",
+    "memories_features.h",
+  ]
+
+  public_deps = [ "//base" ]
+}
diff --git a/components/memories/common/memories_features.cc b/components/memories/common/memories_features.cc
new file mode 100644
index 0000000..a4a3cfc
--- /dev/null
+++ b/components/memories/common/memories_features.cc
@@ -0,0 +1,17 @@
+// Copyright 2021 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/memories/common/memories_features.h"
+
+#include "build/build_config.h"
+
+namespace memories {
+
+// Enables the Chrome Memories history clustering feature.
+const base::Feature kChromeMemories{
+    "ChromeMemories",
+    base::FEATURE_ENABLED_BY_DEFAULT,
+};
+
+}  // namespace memories
diff --git a/components/memories/common/memories_features.h b/components/memories/common/memories_features.h
new file mode 100644
index 0000000..39f9d46
--- /dev/null
+++ b/components/memories/common/memories_features.h
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MEMORIES_COMMON_MEMORIES_FEATURES_H_
+#define COMPONENTS_MEMORIES_COMMON_MEMORIES_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace memories {
+
+extern const base::Feature kChromeMemories;
+
+}  // namespace memories
+
+#endif  // COMPONENTS_MEMORIES_COMMON_MEMORIES_FEATURES_H_
diff --git a/components/messages/android/java/src/org/chromium/components/messages/SingleActionMessage.java b/components/messages/android/java/src/org/chromium/components/messages/SingleActionMessage.java
index a04845db..68ad0de 100644
--- a/components/messages/android/java/src/org/chromium/components/messages/SingleActionMessage.java
+++ b/components/messages/android/java/src/org/chromium/components/messages/SingleActionMessage.java
@@ -22,7 +22,7 @@
  */
 public class SingleActionMessage implements MessageStateHandler {
     private static final long DURATION = 10 * DateUtils.SECOND_IN_MILLIS;
-    private static final long DURATION_ON_A11Y = 20 * DateUtils.SECOND_IN_MILLIS;
+    private static final long DURATION_ON_A11Y = 30 * DateUtils.SECOND_IN_MILLIS;
 
     private MessageBannerCoordinator mMessageBanner;
     private MessageBannerView mView;
diff --git a/components/metrics/structured/BUILD.gn b/components/metrics/structured/BUILD.gn
index b5781c6..d6cea37e 100644
--- a/components/metrics/structured/BUILD.gn
+++ b/components/metrics/structured/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/python.gni")
 import("//testing/test.gni")
+import("//third_party/protobuf/proto_library.gni")
 
 # Structured metrics is subcomponent of UMA that gathers and reports structured
 # events with several attached metrics.
@@ -24,6 +25,7 @@
   public_deps = [ "//third_party/metrics_proto" ]
 
   deps = [
+    ":storage",
     ":structured_events",
     "//base",
     "//components/metrics",
@@ -32,6 +34,22 @@
   ]
 }
 
+proto_library("storage") {
+  # These protos are only used internally, so make them visible only to
+  # subdirectories.
+  visibility = [ "./*" ]
+  proto_in_dir = "//"
+  generate_python = false
+  sources = [ "storage.proto" ]
+
+  # This is required because metrics_proto/BUILD.gn sets proto_in_dir as ".",
+  # which means protos can't be referred to by absolute paths from within other
+  # protos.
+  import_dirs = [ "//third_party/metrics_proto" ]
+  proto_deps = [ "//third_party/metrics_proto" ]
+  link_deps = [ "//third_party/metrics_proto" ]
+}
+
 action("gen_structured_events") {
   script = "//tools/metrics/structured/gen_events.py"
 
diff --git a/components/metrics/structured/storage.proto b/components/metrics/structured/storage.proto
new file mode 100644
index 0000000..f00f632
--- /dev/null
+++ b/components/metrics/structured/storage.proto
@@ -0,0 +1,44 @@
+// Copyright 2021 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package metrics.structured;
+
+import "structured_data.proto";
+
+// These protos are used for storing key and event information for structured
+// metrics. All changes should be backwards-compatible. This file is manually
+// synced between chromium and platform2 so, if editing, please also update
+// the other.
+
+// All information about the key for a single project.
+message KeyProto {
+  // The key itself.
+  optional string key = 1;
+
+  // When the key was last rotated, in days since the unix epoch.
+  optional int64 last_rotation = 2;
+
+  // The maximum number of days between rotations.
+  optional int64 rotation_period = 3;
+}
+
+// Stores keys for all projects.
+message KeyDataProto {
+  // Maps the first 8 bytes of the MD5 hash of the project name to that
+  // project's key.
+  map<fixed64, KeyProto> keys = 1;
+}
+
+// On-device storage for events that have been recorded but not yet uploaded.
+message EventsProto {
+  // Events not associated with the UMA client_id.
+  repeated StructuredEventProto non_uma_events = 1;
+
+  // Events associated with the UMA client_id.
+  repeated StructuredEventProto uma_events = 2;
+}
diff --git a/components/paint_preview/common/serial_utils_unittest.cc b/components/paint_preview/common/serial_utils_unittest.cc
index f249210e..35410e9f 100644
--- a/components/paint_preview/common/serial_utils_unittest.cc
+++ b/components/paint_preview/common/serial_utils_unittest.cc
@@ -146,9 +146,9 @@
   canvas1.drawRect(SkRect::MakeWH(1, 4), paint);
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(40, 40));
-  canvas->drawBitmap(bitmap1, 0, 0);
-  canvas->drawBitmap(bitmap1, 0, 0);
-  canvas->drawBitmap(bitmap1, 0, 0);
+  canvas->drawImage(bitmap1.asImage(), 0, 0);
+  canvas->drawImage(bitmap1.asImage(), 0, 0);
+  canvas->drawImage(bitmap1.asImage(), 0, 0);
   auto pic = recorder.finishRecordingAsPicture();
 
   PictureSerializationContext picture_ctx;
@@ -194,8 +194,8 @@
   canvas2.drawRect(SkRect::MakeWH(20, 5), paint);
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(40, 40));
-  canvas->drawBitmap(bitmap1, 0, 0);
-  canvas->drawBitmap(bitmap2, 0, 0);
+  canvas->drawImage(bitmap1.asImage(), 0, 0);
+  canvas->drawImage(bitmap2.asImage(), 0, 0);
   auto pic = recorder.finishRecordingAsPicture();
 
   PictureSerializationContext picture_ctx;
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc
index b893c56..b25815fa 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -216,6 +216,12 @@
     return password || new_password;
   }
 
+  // Returns whether a new password fields without a corresponding confirmation
+  // password field was found.
+  bool MissesConfirmationPassword() const {
+    return new_password && !confirmation_password;
+  }
+
   void ClearAllPasswordFields() {
     password = nullptr;
     new_password = nullptr;
@@ -249,6 +255,34 @@
   return nullptr;
 }
 
+// Given a `new_password` field tries to find a matching confirmation_password
+// field in `processed_fields` that succeeds `new_password` and has matching
+// interactability and value.
+// Returns that field or nullptr if no such field could be found.
+const FormFieldData* FindConfirmationPasswordField(
+    const std::vector<ProcessedField>& processed_fields,
+    const FormFieldData& new_password) {
+  auto new_password_field = base::ranges::find(processed_fields, &new_password,
+                                               &ProcessedField::field);
+  if (new_password_field == processed_fields.end())
+    return nullptr;
+
+  // Find a processed field following `new_password_field` with matching
+  // interactability and value.
+  auto MatchesNewPasswordField = [new_password_field](
+                                     const ProcessedField& field) {
+    return MatchesInteractability(field, new_password_field->interactability) &&
+           GetFieldValue(*new_password_field->field) ==
+               GetFieldValue(*field.field);
+  };
+  auto confirmation_password_field =
+      std::find_if(std::next(new_password_field), processed_fields.end(),
+                   MatchesNewPasswordField);
+  return confirmation_password_field != processed_fields.end()
+             ? confirmation_password_field->field
+             : nullptr;
+}
+
 // Tries to parse |processed_fields| based on server |predictions|. Uses |mode|
 // to decide which of two username hints are relevant, if present.
 void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields,
@@ -1005,6 +1039,22 @@
         }
       }
     }
+
+    // If we're in saving mode and have found a new password but not a
+    // confirmation password field, try to infer the confirmation password field
+    // by trying to find a field that succeeds the new password field and has
+    // matching interactability and value. This should only have an effect if
+    // the new password field was found using server predictions or autocomplete
+    // attributes. In the case of local heuristics we already made use of the
+    // field's value to find a confirmation password field, and thus won't find
+    // it now if we didn't find it already.
+    if (mode == Mode::kSaving &&
+        significant_fields.MissesConfirmationPassword() &&
+        base::FeatureList::IsEnabled(
+            features::kInferConfirmationPasswordField)) {
+      significant_fields.confirmation_password = FindConfirmationPasswordField(
+          processed_fields, *significant_fields.new_password);
+    }
   }
 
   // Pass the "reliability" information to mark the new-password fields as
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
index 921f859e..5be0749 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -1227,6 +1227,92 @@
   });
 }
 
+TEST(FormParserTest, InferConfirmationPasswordField) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kInferConfirmationPasswordField);
+  CheckTestData({
+      {
+          .description_for_logging = "Infer confirmation password during "
+                                     "saving with server prediction.",
+          .fields =
+              {
+                  {
+                      .role = ElementRole::NEW_PASSWORD,
+                      .value = "pw",
+                      .form_control_type = "password",
+                      .prediction = {.type =
+                                         autofill::ACCOUNT_CREATION_PASSWORD},
+                  },
+                  {
+                      .role_saving = ElementRole::CONFIRMATION_PASSWORD,
+                      .value = "pw",
+                      .form_control_type = "password",
+                  },
+              },
+      },
+      {
+          .description_for_logging = "Infer confirmation password during "
+                                     "saving with auto-complete attribute.",
+          .fields =
+              {
+                  {
+                      .role = ElementRole::NEW_PASSWORD,
+                      .autocomplete_attribute = "new-password",
+                      .value = "pw",
+                      .form_control_type = "password",
+                  },
+                  {
+                      .role_filling = ElementRole::NONE,
+                      .role_saving = ElementRole::CONFIRMATION_PASSWORD,
+                      .autocomplete_attribute = "off",
+                      .value = "pw",
+                      .form_control_type = "password",
+                  },
+              },
+      },
+      {
+          .description_for_logging =
+              "Don't infer confirmation password during saving with "
+              "predictions and different passwords.",
+          .fields =
+              {
+                  {
+                      .role_filling = ElementRole::NEW_PASSWORD,
+                      .role_saving = ElementRole::CURRENT_PASSWORD,
+                      .value = "pw1",
+                      .form_control_type = "password",
+                      .prediction = {.type =
+                                         autofill::ACCOUNT_CREATION_PASSWORD},
+                  },
+                  {
+                      .role_saving = ElementRole::NEW_PASSWORD,
+                      .value = "pw2",
+                      .form_control_type = "password",
+                  },
+              },
+      },
+      {
+          .description_for_logging =
+              "Don't infer confirmation password during saving with "
+              "autocomplete attribute and different passwords.",
+          .fields =
+              {
+                  {
+                      .role = ElementRole::NEW_PASSWORD,
+                      .autocomplete_attribute = "new-password",
+                      .value = "pw1",
+                      .form_control_type = "password",
+                  },
+                  {
+                      .role = ElementRole::NONE,
+                      .value = "pw2",
+                      .form_control_type = "password",
+                  },
+              },
+      },
+  });
+}
+
 TEST(FormParserTest, ServerHints) {
   CheckTestData({
       {
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index 53b955c..882ad03d 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -65,6 +65,12 @@
 const base::Feature kFillOnAccountSelect = {"fill-on-account-select",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables finding a confirmation password field during saving by inspecting the
+// values of the fields. Used as a kill switch.
+// TODO(crbug.com/1164861): Remove once confirmed to be safe (around M92 or so).
+const base::Feature kInferConfirmationPasswordField = {
+    "InferConfirmationPasswordField", base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enables password change flow from leaked password dialog.
 const base::Feature kPasswordChange = {"PasswordChange",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 176dc24..3206067 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -27,6 +27,7 @@
 extern const base::Feature KEnablePasswordGenerationForClearTextFields;
 extern const base::Feature kFillingPasswordsFromAnyOrigin;
 extern const base::Feature kFillOnAccountSelect;
+extern const base::Feature kInferConfirmationPasswordField;
 extern const base::Feature kPasswordChange;
 extern const base::Feature kPasswordChangeInSettings;
 extern const base::Feature kPasswordImport;
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index 93c8fa7..6f6f66f 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -262,16 +262,26 @@
   sources = [ "//components/payments/core/journey_logger.h" ]
 }
 
+java_library("junit_test_support") {
+  sources = [
+    # TODO(crbug.com/1170916): Used to suppress the target non-emptiness
+    # assertion.
+    "junit/src/org/chromium/components/payments/EmptyTargetPlaceHolder.java",
+  ]
+}
+
 java_library("junit") {
   # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
   bypass_platform_checks = true
   testonly = true
   sources = [
+    "junit/src/org/chromium/components/payments/LegacyPaymentRequestServiceBuilder.java",
     "junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java",
     "junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java",
   ]
   deps = [
     ":java",
+    ":junit_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/EmptyTargetPlaceHolder.java b/components/payments/content/android/junit/src/org/chromium/components/payments/EmptyTargetPlaceHolder.java
new file mode 100644
index 0000000..dbb6ab8
--- /dev/null
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/EmptyTargetPlaceHolder.java
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.payments;
+
+/**
+ * TODO(crbug.com/1170916): Removed soon. This class is used to transition downstream dependencies.
+ */
+public class EmptyTargetPlaceHolder {}
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/LegacyPaymentRequestServiceBuilder.java b/components/payments/content/android/junit/src/org/chromium/components/payments/LegacyPaymentRequestServiceBuilder.java
new file mode 100644
index 0000000..c960db1
--- /dev/null
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/LegacyPaymentRequestServiceBuilder.java
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.payments;
+
+import org.chromium.payments.mojom.PaymentRequestClient;
+
+/**
+ * TODO(crbug.com/1170916): Removed soon. This class is a temporary replacement of
+ * PaymentRequestServiceBuilder, used to transition downstream dependencies.
+ */
+public class LegacyPaymentRequestServiceBuilder extends PaymentRequestServiceBuilder {
+    public LegacyPaymentRequestServiceBuilder(Runnable onClosedListener,
+            PaymentRequestClient client, PaymentAppService appService,
+            BrowserPaymentRequest browserPaymentRequest, JourneyLogger journeyLogger) {
+        super(onClosedListener, client, appService, browserPaymentRequest, journeyLogger);
+    }
+}
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java
index a8ba8ee..4af3b8b 100644
--- a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java
@@ -57,7 +57,7 @@
                 onClosedListener, client, appService, browserPaymentRequest, journeyLogger);
     }
 
-    private PaymentRequestServiceBuilder(Runnable onClosedListener, PaymentRequestClient client,
+    public PaymentRequestServiceBuilder(Runnable onClosedListener, PaymentRequestClient client,
             PaymentAppService appService, BrowserPaymentRequest browserPaymentRequest,
             JourneyLogger journeyLogger) {
         mDelegate = this;
diff --git a/components/payments/content/payment_app_unittest.cc b/components/payments/content/payment_app_unittest.cc
index 4ac6502b..78102c16 100644
--- a/components/payments/content/payment_app_unittest.cc
+++ b/components/payments/content/payment_app_unittest.cc
@@ -41,6 +41,12 @@
   kContactInformationAndShippingAddress,
 };
 
+static const RequiredPaymentOptions kRequiredPaymentOptionsValues[]{
+    RequiredPaymentOptions::kNone, RequiredPaymentOptions::kShippingAddress,
+    RequiredPaymentOptions::kContactInformation,
+    RequiredPaymentOptions::kPayerEmail,
+    RequiredPaymentOptions::kContactInformationAndShippingAddress};
+
 }  // namespace
 
 class PaymentAppTest : public testing::TestWithParam<RequiredPaymentOptions>,
@@ -181,15 +187,9 @@
   DISALLOW_COPY_AND_ASSIGN(PaymentAppTest);
 };
 
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    PaymentAppTest,
-    ::testing::Values(
-        RequiredPaymentOptions::kNone,
-        RequiredPaymentOptions::kShippingAddress,
-        RequiredPaymentOptions::kContactInformation,
-        RequiredPaymentOptions::kPayerEmail,
-        RequiredPaymentOptions::kContactInformationAndShippingAddress));
+INSTANTIATE_TEST_SUITE_P(All,
+                         PaymentAppTest,
+                         ::testing::ValuesIn(kRequiredPaymentOptionsValues));
 
 TEST_P(PaymentAppTest, SortApps) {
   std::vector<PaymentApp*> apps;
@@ -370,10 +370,21 @@
   }
 }
 
-TEST_P(PaymentAppTest, SortApps_DownRankJustInTimePaymentApp) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kDownRankJustInTimePaymentApp);
+class DownRankJustInTimePaymentAppTest : public PaymentAppTest {
+ public:
+  DownRankJustInTimePaymentAppTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kDownRankJustInTimePaymentApp);
+  }
 
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         DownRankJustInTimePaymentAppTest,
+                         ::testing::ValuesIn(kRequiredPaymentOptionsValues));
+
+TEST_P(DownRankJustInTimePaymentAppTest, SortApps) {
   std::vector<PaymentApp*> apps;
 
   // Add a card with no billing address.
diff --git a/components/policy/core/common/features.cc b/components/policy/core/common/features.cc
index 578216d..9d50fec 100644
--- a/components/policy/core/common/features.cc
+++ b/components/policy/core/common/features.cc
@@ -24,6 +24,9 @@
         "PolicyBlocklistThrottlePolicyLoadTimeout",
         base::TimeDelta::FromSeconds(20)};
 
+const base::Feature kUploadBrowserDeviceIdentifier{
+    "UploadBrowserDeviceIdentifier", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 
 }  // namespace policy
diff --git a/components/policy/core/common/features.h b/components/policy/core/common/features.h
index 7f33d39..aebdc02 100644
--- a/components/policy/core/common/features.h
+++ b/components/policy/core/common/features.h
@@ -30,6 +30,9 @@
 POLICY_EXPORT extern const base::FeatureParam<base::TimeDelta>
     kPolicyBlocklistThrottlePolicyLoadTimeout;
 
+// Update browser device identifier during enrollment and fetching policies.
+POLICY_EXPORT extern const base::Feature kUploadBrowserDeviceIdentifier;
+
 }  // namespace features
 }  // namespace policy
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 343c50f..2306d5f 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -4503,7 +4503,7 @@
       'id': 30,
       'caption': '''Kerberos delegation server whitelist''',
       'tags': [],
-      'desc': '''This policy is deprecated, please use the '<ph name="AUTH_NEGOCIATE_DELEGATE_ALLOWLIST_POLICY_NAME">AuthNegotiateDelegateAllowlist</ph>' policy instead.
+      'desc': '''This policy is deprecated, please use the '<ph name="AUTH_NEGOTIATE_DELEGATE_ALLOWLIST_POLICY_NAME">AuthNegotiateDelegateAllowlist</ph>' policy instead.
 
       Setting the policy assigns servers that <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> may delegate to. Separate multiple server names with commas. Wildcards, <ph name="WILDCARD_VALUE">*</ph>, are allowed.
 
@@ -21697,7 +21697,7 @@
 
       The <ph name="ENTERPRISE_CONNECTOR_CUSTOM_MESSAGES_FIELD">custom_messages</ph>, <ph name="ENTERPRISE_CONNECTOR_MESSAGE_FIELD">message</ph>, <ph name="ENTERPRISE_CONNECTOR_LEARN_MORE_URL_FIELD">learn_more_url</ph>, <ph name="ENTERPRISE_CONNECTOR_LANGUAGE_FIELD">language</ph> and <ph name="ENTERPRISE_CONNECTOR_TAG_FIELD">tag</ph> fields are used to configure a message to show the user when a warning is shown after a scan had a non-clean verdict. The message field contains the text to show the user and should have at most 200 characters. The learn_more_url field contains an admin-provided URL that will be clickable by the user to get more customer-provided information about why the action was blocked. The language field is optional and contains the language of the message. An empty language field or a value of 'default' indicates a message to be used when the user's language doesn't have a message. The tag field specifies for which type of scans the message is displayed. The custom_messages list can have zero or more entries, where each entry is required to have non-empty message and tag fields.
 
-      This policy can only be set from the Google Admin console.'''
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
     },
     {
       'name': 'OnFileAttachedEnterpriseConnector',
@@ -21832,7 +21832,7 @@
 
       The <ph name="ENTERPRISE_CONNECTOR_CUSTOM_MESSAGES_FIELD">custom_messages</ph>, <ph name="ENTERPRISE_CONNECTOR_MESSAGE_FIELD">message</ph>, <ph name="ENTERPRISE_CONNECTOR_LEARN_MORE_URL_FIELD">learn_more_url</ph>, <ph name="ENTERPRISE_CONNECTOR_LANGUAGE_FIELD">language</ph> and <ph name="ENTERPRISE_CONNECTOR_TAG_FIELD">tag</ph> fields are used to configure a message to show the user when a warning is shown after a scan had a non-clean verdict. The message field contains the text to show the user and should have at most 200 characters. The learn_more_url field contains an admin-provided URL that will be clickable by the user to get more customer-provided information about why the action was blocked. The language field is optional and contains the language of the message. An empty language field or a value of 'default' indicates a message to be used when the user's language doesn't have a message. The tag field specifies for which type of scans the message is displayed. The custom_messages list can have zero or more entries, where each entry is required to have non-empty message and tag fields.
 
-      This policy can only be set from the Google Admin console.'''
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
     },
     {
       'name': 'OnBulkDataEntryEnterpriseConnector',
@@ -21963,7 +21963,7 @@
 
       The <ph name="ENTERPRISE_CONNECTOR_CUSTOM_MESSAGES_FIELD">custom_messages</ph>, <ph name="ENTERPRISE_CONNECTOR_MESSAGE_FIELD">message</ph>, <ph name="ENTERPRISE_CONNECTOR_LEARN_MORE_URL_FIELD">learn_more_url</ph>, <ph name="ENTERPRISE_CONNECTOR_LANGUAGE_FIELD">language</ph> and <ph name="ENTERPRISE_CONNECTOR_TAG_FIELD">tag</ph> fields are used to configure a message to show the user when a warning is shown after a scan had a non-clean verdict. The message field contains the text to show the user and should have at most 200 characters. The learn_more_url field contains an admin-provided URL that will be clickable by the user to get more customer-provided information about why the action was blocked. The language field is optional and contains the language of the message. An empty language field or a value of 'default' indicates a message to be used when the user's language doesn't have a message. The tag field specifies for which type of scans the message is displayed. The custom_messages list can have zero or more entries, where each entry is required to have non-empty message and tag fields.
 
-      This policy can only be set from the Google Admin console.'''
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
     },
     {
       'name': 'OnSecurityEventEnterpriseConnector',
@@ -22000,7 +22000,7 @@
 
       The <ph name="ENTERPRISE_CONNECTOR_SERVICE_PROVIDER_FIELD">service_provider</ph> field identifies which reporting service provider the settings correspond to and the <ph name="ENTERPRISE_CONNECTOR_ENABLED_EVENT_NAMES_FIELD">enabled_event_names</ph> field identifies which events are enabled for this provider.
 
-      This policy can only be set from the Google Admin console.'''
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
     },
     {
       'name': 'EnterpriseRealTimeUrlCheckMode',
@@ -22042,7 +22042,7 @@
 
       If this policy is set to ‘Enabled’, URLs will be sent to be scanned in real time under enterprise ToS. It will result in Chrome sending URLs to Google Cloud or third parties of your choosing to check them in real time. The consumer version of Safe Browsing real time lookup will be switched off.
 
-      This policy can only be set from the Google Admin console.''',
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
     },
     {
       'name': 'RendererCodeIntegrityEnabled',
@@ -24463,7 +24463,92 @@
       When this policy is disabled, the <ph name="WEBXR_API_NAME">WebXR Device API</ph> will reject requests to create sessions with mode set to <ph name="WEBXR_AR_SESSION_ENUM_VALUE">"immersive-ar"</ph>. The existing <ph name="WEBXR_AR_SESSION_ENUM_VALUE">"immersive-ar"</ph> sessions (if any) will not be terminated.
 
       For more details about <ph name="WEBXR_AR_SESSION_ENUM_VALUE">"immersive-ar"</ph> sessions, please see <ph name="WEBXR_AR_MODULE_API_NAME">WebXR Augmented Reality Module</ph> specfication.'''
-    }
+    },
+    {
+      'name': 'SendDownloadToCloudEnterpriseConnector',
+      'owners': ['rogerta@chromium.org', 'mad@chromium.org', 'alicego@google.com'],
+      'type': 'dict',
+      'schema': {
+        'type': 'array',
+        'items': {
+          'type': 'object',
+          'properties': {
+            'service_provider': { 'type': 'string' },
+            'enterprise_id': { 'type': 'string' },
+            'enable': {
+              'type': 'array',
+              'items': {
+                'type': 'object',
+                'properties': {
+                  'url_list': {
+                    'type': 'array',
+                    'items': { 'type': 'string' },
+                  },
+                  'mime_types': {
+                    'type': 'array',
+                    'items': { 'type': 'string' },
+                  }
+                },
+              }
+            },
+            'disable': {
+              'type': 'array',
+              'items': {
+                'type': 'object',
+                'properties': {
+                  'url_list': {
+                    'type': 'array',
+                    'items': { 'type': 'string' },
+                  },
+                  'mime_types': {
+                    'type': 'array',
+                    'items': { 'type': 'string' },
+                  }
+                },
+              },
+            },
+          },
+        },
+      },
+      'example_value': [{
+        'service_provider': 'Google',
+        'enterprise_id': '1234567890',
+        'enable': [
+          {
+            'url_list': ['*'],
+            'mime_types': ['text/plain']
+          },
+          {
+            'url_list': ['*.them.com', '*.others.com'],
+            'mime_types': ['image/png']
+          },
+        ],
+        'disable': [
+          {
+            'url_list': ['*.us.com'],
+            'mime_types': ['application/zip']
+          },
+        ],
+      }],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+        'cloud_only': True,
+      },
+      'id': 822,
+      'future_on': ['chrome.*', 'chrome_os'],
+      'caption': '''Configuration policy for the <ph name="FILE_SYSTEM_ENTERPRISE_CONNECTOR">File System Enterprise Connector</ph> handling of downloaded files''',
+      'tags': [],
+      'desc': '''List of settings to be applied to the <ph name="FILE_SYSTEM_ENTERPRISE_CONNECTOR">File System Enterprise Connector</ph>, which triggers when a file is downloaded.
+
+      The <ph name="ENTERPRISE_CONNECTOR_URL_LIST_FIELD">url_list</ph>, <ph name="ENTERPRISE_CONNECTOR_MIME_TYPES_FIELD">mime_types</ph>, <ph name="ENTERPRISE_CONNECTOR_ENABLE_FIELD">enable</ph> and <ph name="ENTERPRISE_CONNECTOR_DISABLE_FIELD">disable</ph> fields are used to determine if the connector should send a file to the service provider when downloading from a web page. The web page URL must match a pattern associated to an 'enable' pattern and not associated to a 'disable' pattern.  The file's MIME type must also match a pattern associated to an 'enable' pattern and not associated to a 'disable' pattern.
+
+      The <ph name="ENTERPRISE_CONNECTOR_SERVICE_PROVIDER_FIELD">service_provider</ph> field identifies which analysis service provider the settings correspond to.
+
+      The <ph name="ENTERPRISE_CONNECTOR_ENTERPRISE_ID_FIELD">enterprise_id</ph> field identifies the enterprise with the service provider.  When the user is asked to sign in as part of setting up the <ph name="FILE_SYSTEM_ENTERPRISE_CONNECTOR">File System Enterprise Connector</ph>, only user accounts associated with this enterprise are permitted.
+
+      This policy can only be set from the <ph name="GOOGLE_ADMIN_CONSOLE_PRODUCT_NAME">Google Admin console</ph>.'''
+    },
   ],
 
   'messages': {
@@ -25389,6 +25474,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 821,
+  'highest_id_currently_used': 822,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/components/sessions/core/command_storage_manager.cc b/components/sessions/core/command_storage_manager.cc
index 99c4078..a8546d51 100644
--- a/components/sessions/core/command_storage_manager.cc
+++ b/components/sessions/core/command_storage_manager.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/sequenced_task_runner.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread.h"
@@ -25,11 +24,6 @@
 // backend.
 constexpr base::TimeDelta kSaveDelay = base::TimeDelta::FromMilliseconds(2500);
 
-scoped_refptr<base::SequencedTaskRunner> CreateDefaultBackendTaskRunner() {
-  return base::ThreadPool::CreateSequencedTaskRunner(
-      {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-}
-
 void AdaptGetLastSessionCommands(
     CommandStorageManager::GetCommandsCallback callback,
     CommandStorageBackend::ReadCommandsResult result) {
@@ -44,9 +38,11 @@
     CommandStorageManagerDelegate* delegate,
     bool use_marker,
     bool enable_crypto,
-    const std::vector<uint8_t>& decryption_key)
+    const std::vector<uint8_t>& decryption_key,
+    scoped_refptr<base::SequencedTaskRunner> backend_task_runner)
     : backend_(base::MakeRefCounted<CommandStorageBackend>(
-          CreateDefaultBackendTaskRunner(),
+          backend_task_runner ? backend_task_runner
+                              : CreateDefaultBackendTaskRunner(),
           path,
           type,
           use_marker,
@@ -59,6 +55,13 @@
 CommandStorageManager::~CommandStorageManager() = default;
 
 // static
+scoped_refptr<base::SequencedTaskRunner>
+CommandStorageManager::CreateDefaultBackendTaskRunner() {
+  return base::ThreadPool::CreateSequencedTaskRunner(
+      {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+}
+
+// static
 std::vector<uint8_t> CommandStorageManager::CreateCryptoKey() {
   std::vector<uint8_t> key(32);
   crypto::RandBytes(&(key.front()), key.size());
diff --git a/components/sessions/core/command_storage_manager.h b/components/sessions/core/command_storage_manager.h
index a7dbeeae..2321dcb8dd 100644
--- a/components/sessions/core/command_storage_manager.h
+++ b/components/sessions/core/command_storage_manager.h
@@ -14,12 +14,9 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
 #include "components/sessions/core/sessions_export.h"
 
-namespace base {
-class SequencedTaskRunner;
-}
-
 namespace sessions {
 class CommandStorageManagerDelegate;
 class SessionCommand;
@@ -59,16 +56,21 @@
   // standardize on that of `kOther`.
   //
   // See CommandStorageBackend for details on `use_marker`.
-  CommandStorageManager(SessionType type,
-                        const base::FilePath& path,
-                        CommandStorageManagerDelegate* delegate,
-                        bool use_marker = false,
-                        bool enable_crypto = false,
-                        const std::vector<uint8_t>& decryption_key = {});
+  CommandStorageManager(
+      SessionType type,
+      const base::FilePath& path,
+      CommandStorageManagerDelegate* delegate,
+      bool use_marker = false,
+      bool enable_crypto = false,
+      const std::vector<uint8_t>& decryption_key = {},
+      scoped_refptr<base::SequencedTaskRunner> backend_task_runner = nullptr);
   CommandStorageManager(const CommandStorageManager&) = delete;
   CommandStorageManager& operator=(const CommandStorageManager&) = delete;
   virtual ~CommandStorageManager();
 
+  static scoped_refptr<base::SequencedTaskRunner>
+  CreateDefaultBackendTaskRunner();
+
   // Helper to generate a new key.
   static std::vector<uint8_t> CreateCryptoKey();
 
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.cc b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
index bd7ffac4..70b9688 100644
--- a/components/viz/common/gpu/vulkan_in_process_context_provider.cc
+++ b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
@@ -108,6 +108,9 @@
     if (device) {
       if (std::strcmp("vkQueueSubmit", proc_name) == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(&gpu::QueueSubmitHook);
+      if (std::strcmp("vkCreateGraphicsPipelines", proc_name) == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            &gpu::CreateGraphicsPipelinesHook);
       return vkGetDeviceProcAddr(device, proc_name);
     }
     return vkGetInstanceProcAddr(instance, proc_name);
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 47ded9c..ca43fd2 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -1147,7 +1147,8 @@
   // will be rastered over the top. So we need to paint it here, unfiltered.
   if (backdrop_filter_bounds.has_value() || quad->ShouldDrawWithBlending()) {
     surface->getCanvas()->drawImageRect(
-        src_image, RectFToSkRect(src_image_rect), dest_rect, nullptr);
+        src_image, RectFToSkRect(src_image_rect), dest_rect,
+        SkSamplingOptions(), nullptr, SkCanvas::kStrict_SrcRectConstraint);
   }
 
   if (backdrop_filter_bounds.has_value()) {
@@ -1195,8 +1196,9 @@
   }
   // Now paint the pre-filtered image onto the canvas (possibly with mask
   // applied).
-  surface->getCanvas()->drawImageRect(filtered_image, subset, dest_rect,
-                                      &paint);
+  surface->getCanvas()->drawImageRect(filtered_image, SkRect::Make(subset),
+                                      dest_rect, SkSamplingOptions(), &paint,
+                                      SkCanvas::kStrict_SrcRectConstraint);
 
   if (backdrop_filter_bounds.has_value()) {
     surface->getCanvas()->restore();
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index 3efd33f..96706fda 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -468,9 +468,11 @@
     background_paint.setColor(quad->background_color);
     current_canvas_->drawRect(quad_rect, background_paint);
   }
-  current_paint_.setFilterQuality(
-      quad->nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality);
-  current_canvas_->drawImageRect(image, sk_uv_rect, quad_rect, &current_paint_);
+  SkSamplingOptions sampling(quad->nearest_neighbor ? SkFilterMode::kNearest
+                                                    : SkFilterMode::kLinear);
+  current_canvas_->drawImageRect(image, sk_uv_rect, quad_rect, sampling,
+                                 &current_paint_,
+                                 SkCanvas::kStrict_SrcRectConstraint);
   if (needs_layer)
     current_canvas_->restore();
 }
@@ -493,11 +495,11 @@
       QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
 
   SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect);
-  current_paint_.setFilterQuality(
-      quad->nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality);
-  current_canvas_->drawImageRect(lock.sk_image(), uv_rect,
-                                 gfx::RectFToSkRect(visible_quad_vertex_rect),
-                                 &current_paint_);
+  SkSamplingOptions sampling(quad->nearest_neighbor ? SkFilterMode::kNearest
+                                                    : SkFilterMode::kLinear);
+  current_canvas_->drawImageRect(
+      lock.sk_image(), uv_rect, gfx::RectFToSkRect(visible_quad_vertex_rect),
+      sampling, &current_paint_, SkCanvas::kStrict_SrcRectConstraint);
 }
 
 void SoftwareRenderer::DrawRenderPassQuad(
@@ -726,8 +728,8 @@
   cc::ScopedSubnormalFloatDisabler disabler;
   paint.setImageFilter(filter->makeWithLocalMatrix(local_matrix));
   surface->getCanvas()->translate(-canvas_offset.x(), -canvas_offset.y());
-  surface->getCanvas()->drawBitmap(to_filter, quad->rect.x(), quad->rect.y(),
-                                   &paint);
+  surface->getCanvas()->drawImage(to_filter.asImage(), quad->rect.x(),
+                                  quad->rect.y(), SkSamplingOptions(), &paint);
   return surface->makeImageSnapshot();
 }
 
@@ -892,7 +894,8 @@
   SkRect src_rect =
       SkRect::MakeXYWH(0, 0, backdrop_bitmap.width(), backdrop_bitmap.height());
   SkRect dst_rect = src_rect.makeOffset(image_offset.x(), image_offset.y());
-  canvas.drawImageRect(filtered_image, src_rect, dst_rect, &paint);
+  canvas.drawImageRect(filtered_image, src_rect, dst_rect, SkSamplingOptions(),
+                       &paint, SkCanvas::kStrict_SrcRectConstraint);
 
   return SkImage::MakeFromBitmap(bitmap)->makeShader(
       content_tile_mode, content_tile_mode, SkSamplingOptions(),
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
index cfdd7e4..2fcdc2c2 100644
--- a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
+++ b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
@@ -70,7 +70,7 @@
     context_state_->vk_context_provider()
         ->GetGrSecondaryCBDrawContext()
         ->getCanvas()
-        ->drawImage(sk_image, 0, 0, &paint);
+        ->drawImage(sk_image, 0, 0, SkSamplingOptions(), &paint);
     context_state_->vk_context_provider()
         ->GetGrSecondaryCBDrawContext()
         ->flush();
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 125ed2b..cee5b54a 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -588,8 +588,8 @@
       sk_sp<SkColorFilter> colorFilter = SkiaHelper::MakeOverdrawColorFilter();
       paint.setColorFilter(colorFilter);
       // TODO(xing.xu): move below to the thread where skia record happens.
-      scoped_output_device_paint_->GetCanvas()->drawImage(overdraw_image.get(),
-                                                          0, 0, &paint);
+      scoped_output_device_paint_->GetCanvas()->drawImage(
+          overdraw_image.get(), 0, 0, SkSamplingOptions(), &paint);
     }
 
     auto end_paint_semaphores =
@@ -901,13 +901,13 @@
                              request->scale_from().y());
     }
 
-    SkPaint paint;
-    paint.setFilterQuality(is_downscale_or_identity_in_both_dimensions
-                               ? kMedium_SkFilterQuality
-                               : kHigh_SkFilterQuality);
     dest_canvas->clipRect(
         SkRect::MakeXYWH(0, 0, src_rect.width(), src_rect.height()));
-    surface->draw(dest_canvas, -src_rect.x(), -src_rect.y(), &paint);
+    auto sampling =
+        is_downscale_or_identity_in_both_dimensions
+            ? SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)
+            : SkSamplingOptions({1.0f / 3, 1.0f / 3});
+    surface->draw(dest_canvas, -src_rect.x(), -src_rect.y(), sampling, nullptr);
 
     GrFlushInfo flush_info;
     flush_info.fNumSemaphores = end_semaphores.size();
diff --git a/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
index 3ed471b..8bbb8990 100644
--- a/content/browser/accessibility/accessibility_auralinux_browsertest.cc
+++ b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -1507,18 +1507,15 @@
       shell()->web_contents(), ui::kAXModeComplete,
       ax::mojom::Event::kTextSelectionChanged);
 
-  int length = atk_text_get_character_count(ATK_TEXT(heading));
-  for (int i = 0; i < length; i++) {
-    atk_text_set_caret_offset(ATK_TEXT(heading), i);
-
-    // We aren't getting kTextSelectionChanged or kDocumentSelectionChanged for
-    // the following offsets in the generated content. Recheck this after the
-    // crasher bug is fixed.
-    if (i == 1 || i == 6)
-      continue;
-
+  // Caret can't be set inside generated content, it will go to the closest
+  // allowed place. Ordered the targets so that the caret will always actually
+  // move somewhere between steps, and thus the waiter will always be satisfied.
+  std::vector<int> target_offset = {0, 3, 1, 4, 2, 4, 5, 4, 6};
+  std::vector<int> expect_offset = {2, 3, 2, 4, 2, 4, 2, 4, 2};
+  for (size_t i = 0; i < target_offset.size(); i++) {
+    atk_text_set_caret_offset(ATK_TEXT(heading), target_offset[i]);
     waiter.WaitForNotification();
-    ASSERT_EQ(i, atk_text_get_caret_offset(ATK_TEXT(heading)));
+    ASSERT_EQ(expect_offset[i], atk_text_get_caret_offset(ATK_TEXT(heading)));
   }
 
   g_object_unref(heading);
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 677b1e4..6f9309a 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -281,6 +281,10 @@
                      DumpAccessibilityTestHelper::TestPasses().size()),
     DumpAccessibilityTreeTestPassToString());
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSAltText) {
+  RunCSSTest(FILE_PATH_LITERAL("alt-text.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilityCSSBeforeAfterBlock) {
   RunCSSTest(FILE_PATH_LITERAL("before-after-block.html"));
@@ -305,6 +309,10 @@
   RunCSSTest(FILE_PATH_LITERAL("content-visibility-to-hidden.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSCounterText) {
+  RunCSSTest(FILE_PATH_LITERAL("counter-text.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSFontStyle) {
   RunCSSTest(FILE_PATH_LITERAL("font-style.html"));
 }
@@ -362,6 +370,10 @@
   RunCSSTest(FILE_PATH_LITERAL("text-overflow-ellipsis.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSFirstLetter) {
+  RunCSSTest(FILE_PATH_LITERAL("first-letter.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilityCSSInlinePositionRelative) {
   RunCSSTest(FILE_PATH_LITERAL("inline-position-relative.html"));
@@ -373,6 +385,11 @@
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilityCSSPseudoElements) {
+  RunCSSTest(FILE_PATH_LITERAL("pseudo-elements.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityCSSPseudoElementAlternativeText) {
   RunCSSTest(FILE_PATH_LITERAL("pseudo-element-alternative-text.html"));
 }
 
diff --git a/content/browser/android/synchronous_compositor_host.cc b/content/browser/android/synchronous_compositor_host.cc
index 4b6a995..a8387d3 100644
--- a/content/browser/android/synchronous_compositor_host.cc
+++ b/content/browser/android/synchronous_compositor_host.cc
@@ -407,7 +407,7 @@
     TRACE_EVENT0("browser", "DrawBitmap");
     canvas->save();
     canvas->resetMatrix();
-    canvas->drawBitmap(bitmap, 0, 0);
+    canvas->drawImage(bitmap.asImage(), 0, 0);
     canvas->restore();
   }
 
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index 5588e67..6be7f55 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -1615,14 +1615,7 @@
         // BrowsingInstances are registered in the process. Allow this for now,
         // to maintain legacy behavior, until we rule out all the ways it can
         // happen.
-        RenderProcessHostImpl* child_host = static_cast<RenderProcessHostImpl*>(
-            RenderProcessHost::FromID(child_id));
-        DCHECK(child_host);
-        size_t keep_alive_count = child_host->keep_alive_ref_count();
-        failure_reason = base::StringPrintf("No BIids, keep_alive_count = %zu",
-                                            keep_alive_count);
-        // This will fall through to the call to the call to
-        // LogCanAccessDataForOriginCrashKeys and log the failure reason.
+        return true;
       }
       for (auto browsing_instance_id :
            security_state->browsing_instance_ids()) {
diff --git a/content/browser/conversions/conversion_internals_ui.cc b/content/browser/conversions/conversion_internals_ui.cc
index 7a30675..649a3ee1 100644
--- a/content/browser/conversions/conversion_internals_ui.cc
+++ b/content/browser/conversions/conversion_internals_ui.cc
@@ -21,7 +21,7 @@
     : WebUIController(web_ui) {
   // Initialize the UI with no bindings. Mojo bindings will be separately
   // granted to frames within this WebContents.
-  web_ui->SetBindings(0);
+  web_ui->SetBindings(BINDINGS_POLICY_NONE);
   WebUIDataSource* source =
       WebUIDataSource::Create(kChromeUIConversionInternalsHost);
 
diff --git a/content/browser/form_controls_browsertest.cc b/content/browser/form_controls_browsertest.cc
index 139384e..98540357 100644
--- a/content/browser/form_controls_browsertest.cc
+++ b/content/browser/form_controls_browsertest.cc
@@ -137,7 +137,13 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, Checkbox) {
+// Disabled due to https://crbug.com/1172370
+#if defined(OS_ANDROID)
+#define MAYBE_Checkbox DISABLED_Checkbox
+#else
+#define MAYBE_Checkbox Checkbox
+#endif
+IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, MAYBE_Checkbox) {
   RunTest("form_controls_browsertest_checkbox",
           "<input type=checkbox>"
           "<input type=checkbox checked>"
@@ -151,7 +157,13 @@
           /* screenshot_height */ 40);
 }
 
-IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, Radio) {
+// Disabled due to https://crbug.com/1172370
+#if defined(OS_ANDROID)
+#define MAYBE_Radio DISABLED_Radio
+#else
+#define MAYBE_Radio Radio
+#endif
+IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, MAYBE_Radio) {
   RunTest("form_controls_browsertest_radio",
           "<input type=radio>"
           "<input type=radio checked>"
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
index b42b2774..1ab49fc3 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -223,7 +223,7 @@
                                          const Origin& origin,
                                          uint64_t connection_count) {
   web_ui()->CallJavascriptFunctionUnsafe(
-      "indexeddb.onForcedClose", base::Value(partition_path.value()),
+      "indexeddb.onForcedClose", base::Value(partition_path.AsUTF8Unsafe()),
       base::Value(origin.Serialize()),
       base::Value(static_cast<double>(connection_count)));
 }
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc
index 3b9cb6e7..a9f36e3 100644
--- a/content/browser/network_service_browsertest.cc
+++ b/content/browser/network_service_browsertest.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/browser/web_ui_controller_factory.h"
+#include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
@@ -59,7 +60,7 @@
       const GURL& url) override {
     std::string foo(url.path());
     if (url.path() == "/nobinding/")
-      web_ui->SetBindings(0);
+      web_ui->SetBindings(BINDINGS_POLICY_NONE);
     return HasWebUIScheme(url) ? std::make_unique<WebUIController>(web_ui)
                                : nullptr;
   }
diff --git a/content/browser/process_internals/process_internals_ui.cc b/content/browser/process_internals/process_internals_ui.cc
index 7df2499..8962166 100644
--- a/content/browser/process_internals/process_internals_ui.cc
+++ b/content/browser/process_internals/process_internals_ui.cc
@@ -29,7 +29,7 @@
     : WebUIController(web_ui) {
   // This WebUI does not require any process bindings, so disable it early in
   // initialization time.
-  web_ui->SetBindings(0);
+  web_ui->SetBindings(BINDINGS_POLICY_NONE);
 
   // Create a WebUIDataSource to serve the HTML/JS files to the WebUI.
   WebUIDataSource* source =
diff --git a/content/browser/renderer_host/dwrite_font_file_util_win.h b/content/browser/renderer_host/dwrite_font_file_util_win.h
index 809808c..6daa797 100644
--- a/content/browser/renderer_host/dwrite_font_file_util_win.h
+++ b/content/browser/renderer_host/dwrite_font_file_util_win.h
@@ -23,10 +23,10 @@
     MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xD002);
 
 HRESULT FontFilePathAndTtcIndex(IDWriteFontFace* font,
-                                base::string16& file_path,
+                                std::wstring& file_path,
                                 uint32_t& ttc_index);
 HRESULT FontFilePathAndTtcIndex(IDWriteFont* font,
-                                base::string16& file_path,
+                                std::wstring& file_path,
                                 uint32_t& ttc_index);
 HRESULT AddFilesForFont(IDWriteFont* font,
                         const base::string16& windows_fonts_path,
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
index d0c33c6f..9f64c0a 100644
--- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
+++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -295,7 +295,7 @@
   callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
       std::move(callback),
       blink::mojom::MapCharactersResult::New(
-          UINT32_MAX, L"", text.length(), 0.0,
+          UINT32_MAX, STRING16_LITERAL(""), text.length(), 0.0,
           blink::mojom::DWriteFontStyle::New(DWRITE_FONT_STYLE_NORMAL,
                                              DWRITE_FONT_STRETCH_NORMAL,
                                              DWRITE_FONT_WEIGHT_NORMAL)));
@@ -326,7 +326,7 @@
   }
 
   auto result = blink::mojom::MapCharactersResult::New(
-      UINT32_MAX, L"", text.length(), 0.0,
+      UINT32_MAX, STRING16_LITERAL(""), text.length(), 0.0,
       blink::mojom::DWriteFontStyle::New(DWRITE_FONT_STYLE_NORMAL,
                                          DWRITE_FONT_STRETCH_NORMAL,
                                          DWRITE_FONT_WEIGHT_NORMAL));
@@ -380,7 +380,7 @@
 
     // Found a matching family!
     result->family_index = index;
-    result->family_name = name.data();
+    result->family_name = base::as_u16cstr(name.data());
     std::move(callback).Run(std::move(result));
     return;
   }
@@ -470,14 +470,14 @@
   if (FAILED(hr))
     return;
 
-  base::string16 font_file_pathname;
+  std::wstring font_file_pathname;
   uint32_t ttc_index;
   if (FAILED(FontFilePathAndTtcIndex(first_font_face.Get(), font_file_pathname,
                                      ttc_index))) {
     return;
   }
 
-  base::FilePath path(base::UTF16ToWide(font_file_pathname));
+  base::FilePath path(font_file_pathname);
   std::move(callback).Run(path, ttc_index);
 }
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index d2df3d0..2734133 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7197,7 +7197,7 @@
 
   // Since this is new WebUI instance, this RenderFrameHostImpl should not
   // have had any bindings. Verify that and grant the required bindings.
-  DCHECK_EQ(0, GetEnabledBindings());
+  DCHECK_EQ(BINDINGS_POLICY_NONE, GetEnabledBindings());
   AllowBindings(web_ui_->GetBindings());
 
   return true;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 281e01d..fc77bac 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -245,7 +245,7 @@
                const SkBitmap& popup_image) {
               // Draw popup_image into main_image.
               SkCanvas canvas(main_image, SkSurfaceProps{});
-              canvas.drawBitmap(popup_image, offset.x(), offset.y());
+              canvas.drawImage(popup_image.asImage(), offset.x(), offset.y());
               std::move(final_callback).Run(main_image);
             },
             std::move(final_callback), offset, std::move(main_image));
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc
index 11f318d8..14f3999 100644
--- a/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -253,7 +253,7 @@
   args.push_back(GetVersionListValue(live_versions));
   args.push_back(GetRegistrationListValue(stored_registrations));
   args.push_back(std::make_unique<Value>(partition_id));
-  args.push_back(std::make_unique<Value>(context_path.value()));
+  args.push_back(std::make_unique<Value>(context_path.AsUTF8Unsafe()));
   internals->web_ui()->CallJavascriptFunctionUnsafe(
       "serviceworker.onPartitionData", ConvertToRawPtrVector(args));
 }
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc
index ee75cc4..401cd75 100644
--- a/content/browser/webui/shared_resources_data_source.cc
+++ b/content/browser/webui/shared_resources_data_source.cc
@@ -60,11 +60,6 @@
   std::map<std::string, std::string> aliases = {
     {"../../views/resources/default_100_percent/common/", "images/apps/"},
     {"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
-#if defined(OS_ANDROID)
-    // This is a temporary fix for `target_cpu = "arm64"`. See the bug for
-    // more context: crbug.com/1020284.
-    {"@out_folder@/android_clang_arm/gen/ui/webui/resources/", ""},
-#endif  // defined(OS_ANDROID)
   };
 
 #if !defined(OS_ANDROID)
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
index 4ae2c25..3db5fab0 100644
--- a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -144,7 +144,7 @@
   }
 
   uint32_t family_index = 0;
-  if (!GetFontProxy().FindFamily(name, &family_index)) {
+  if (!GetFontProxy().FindFamily(base::WideToUTF16(name), &family_index)) {
     LogFontProxyError(FIND_FAMILY_SEND_FAILED);
     return E_FAIL;
   }
@@ -362,9 +362,10 @@
   if (!GetFontProxy().GetFamilyNames(family_index, &pairs)) {
     return false;
   }
-  std::vector<std::pair<base::string16, base::string16>> strings;
+  std::vector<std::pair<std::wstring, std::wstring>> strings;
   for (auto& pair : pairs) {
-    strings.emplace_back(std::move(pair->first), std::move(pair->second));
+    strings.emplace_back(base::UTF16ToWide(pair->first),
+                         base::UTF16ToWide(pair->second));
   }
 
   HRESULT hr = mswr::MakeAndInitialize<DWriteLocalizedStrings>(
diff --git a/content/child/dwrite_font_proxy/font_fallback_win.cc b/content/child/dwrite_font_proxy/font_fallback_win.cc
index 8532bc4..e0229a5 100644
--- a/content/child/dwrite_font_proxy/font_fallback_win.cc
+++ b/content/child/dwrite_font_proxy/font_fallback_win.cc
@@ -173,7 +173,7 @@
                                  DWRITE_FONT_STRETCH base_stretch,
                                  IDWriteFont** font,
                                  uint32_t* mapped_length) {
-  std::map<base::string16, std::list<mswr::ComPtr<IDWriteFontFamily>>>::iterator
+  std::map<std::wstring, std::list<mswr::ComPtr<IDWriteFontFamily>>>::iterator
       it = fallback_family_cache_.find(MakeCacheKey(base_family_name, locale));
   if (it == fallback_family_cache_.end())
     return false;
diff --git a/content/common/content_navigation_policy.cc b/content/common/content_navigation_policy.cc
index 0391d599..a05e328 100644
--- a/content/common/content_navigation_policy.cc
+++ b/content/common/content_navigation_policy.cc
@@ -9,7 +9,6 @@
 #include "base/command_line.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/system/sys_info.h"
-#include "build/build_config.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 
@@ -22,21 +21,9 @@
   // It is important to check the base::FeatureList to avoid activating any
   // field trial groups if BFCache is disabled due to memory threshold.
   if (base::FeatureList::IsEnabled(features::kBackForwardCacheMemoryControl)) {
-    // On Android, BackForwardCache is only enabled for 2GB+ high memory
-    // devices. The default threshold value is set to 1700 MB to account for all
-    // 2GB devices which report lower RAM due to carveouts.
-    int default_memory_threshold_mb =
-#if defined(OS_ANDROID)
-        1700;
-#else
-        // Desktop has lower memory limitations compared to Android allowing us
-        // to enable BackForwardCache for all devices.
-        0;
-#endif
     int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
         features::kBackForwardCacheMemoryControl,
-        "memory_threshold_for_back_forward_cache_in_mb",
-        default_memory_threshold_mb);
+        "memory_threshold_for_back_forward_cache_in_mb", 0);
     return base::SysInfo::AmountOfPhysicalMemoryMB() > memory_threshold_mb;
   }
 
diff --git a/content/public/common/bindings_policy.h b/content/public/common/bindings_policy.h
index 688adba144..b77e4604 100644
--- a/content/public/common/bindings_policy.h
+++ b/content/public/common/bindings_policy.h
@@ -10,6 +10,7 @@
 // This enum specifies flag values for the types of JavaScript bindings exposed
 // to renderers.
 enum BindingsPolicy {
+  BINDINGS_POLICY_NONE = 0,
   // HTML-based UI bindings that allows the JS content to send JSON-encoded
   // data back to the browser process.
   // These bindings should not be exposed to normal web content.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 8ec7602..57ec986 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -68,17 +68,8 @@
                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable using the BackForwardCache.
-// BackForwardCache is enabled only on Android for the moment, as some
-// desktop-specific features (including extensions) are not compatible with
-// bfcache yet. Tracking bug for enabling bfcache on desktop:
-// https://crbug.com/1171298.
-#if defined(OS_ANDROID)
-const base::Feature kBackForwardCache{"BackForwardCache",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
-#else
 const base::Feature kBackForwardCache{"BackForwardCache",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
 
 // BackForwardCache is disabled on low memory devices. The threshold is defined
 // via a field trial param: "memory_threshold_for_back_forward_cache_in_mb"
@@ -87,16 +78,8 @@
 // "BackForwardCacheMemoryControls" is checked before "BackForwardCache". It
 // means the low memory devices will activate neither the control group nor the
 // experimental group of the BackForwardCache field trial.
-
-// BackForwardCacheMemoryControls is enabled only on Android to disable
-// BackForwardCache for lower memory devices due to memory limiations.
-#if defined(OS_ANDROID)
-const base::Feature kBackForwardCacheMemoryControl{
-    "BackForwardCacheMemoryControls", base::FEATURE_ENABLED_BY_DEFAULT};
-#else
 const base::Feature kBackForwardCacheMemoryControl{
     "BackForwardCacheMemoryControls", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
 
 // Block subresource requests whose URLs contain embedded credentials (e.g.
 // `https://user:pass@example.com/resource`).
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc
index 56a4316..a636000c 100644
--- a/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -307,8 +307,10 @@
     // We want to replace the contents of the bitmap rather than blend.
     SkPaint paint;
     paint.setBlendMode(SkBlendMode::kSrc);
-    dest_canvas->drawBitmapRect(
-        image_data_->GetMappedBitmap(), src_irect, dest_rect, &paint);
+    dest_canvas->drawImageRect(image_data_->GetMappedBitmap().asImage(),
+                               SkRect::Make(src_irect), dest_rect,
+                               SkSamplingOptions(), &paint,
+                               SkCanvas::kStrict_SrcRectConstraint);
   }
   return true;
 }
@@ -900,8 +902,9 @@
     // We want to replace the contents of the bitmap rather than blend.
     SkPaint paint;
     paint.setBlendMode(SkBlendMode::kSrc);
-    backing_canvas->drawBitmapRect(
-        image->GetMappedBitmap(), src_irect, dest_rect, &paint);
+    backing_canvas->drawImageRect(
+        image->GetMappedBitmap().asImage(), SkRect::Make(src_irect), dest_rect,
+        SkSamplingOptions(), &paint, SkCanvas::kStrict_SrcRectConstraint);
   }
 }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 42f62ff..e7ff202 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -939,7 +939,11 @@
 
   base::ReplaceFirstSubstringAfterOffset(&path, 0, alias_mapping[0],
                                          alias_mapping[1]);
+#if defined(OS_WIN)
+  request->SetUrl(blink::WebURL(GURL(base::WideToUTF8(path))));
+#else
   request->SetUrl(blink::WebURL(GURL(path)));
+#endif
 }
 
 // Packs all navigation timings sent by the browser to a blink understandable
diff --git a/content/test/data/accessibility/css/alt-text-expected-blink.txt b/content/test/data/accessibility/css/alt-text-expected-blink.txt
new file mode 100644
index 0000000..b412012
--- /dev/null
+++ b/content/test/data/accessibility/css/alt-text-expected-blink.txt
@@ -0,0 +1,52 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++genericContainer
+++++++++genericContainer ignored
+++++++++++staticText name='item1item2'
+++++++++++++inlineTextBox name='item1item2'
+++++++++++image
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++staticText name='code'
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++staticText ignored
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++image name='star'
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++image
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++staticText name='a list of items'
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++image
+++++++++genericContainer
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++genericContainer
+++++++++paragraph
+++++++++++staticText name='Some Text'
+++++++++++++inlineTextBox name='Some Text'
+++++++image name='alt'
+++++++genericContainer
+++++++++staticText name='DOM Text'
+++++++++++inlineTextBox name='DOM Text'
+++++++genericContainer
+++++++++staticText name='DOM Text'
+++++++++++inlineTextBox name='DOM Text'
diff --git a/content/test/data/accessibility/css/alt-text.html b/content/test/data/accessibility/css/alt-text.html
new file mode 100644
index 0000000..8131d3a
--- /dev/null
+++ b/content/test/data/accessibility/css/alt-text.html
@@ -0,0 +1,107 @@
+<style>
+#controlparent::before {
+  content:  "item1" "item2" url(bullet.png);
+}
+</style>
+
+<div id="controlparent">
+  <span id="controlchild">Some Text</span>
+</div>
+
+<style>
+#parent::before {
+  content:  "\25BA" / "code";
+}
+</style>
+<div id="parent">
+  <span id="child">Some Text</span>
+</div>
+
+<style>
+#parentempty::before {
+  content:  "\25BA" / "";
+}
+</style>
+
+<div id="parentempty">
+  <span id="childempty">Some Text</span>
+</div>
+
+<style>
+#imgparent::before {
+  content: url(bullet.png) / "star";
+}
+</style>
+
+<div id="imgparent"class="title">
+  <span id="imgchild">Some Text</span>
+</div>
+
+<style>
+#imgparentempty::before {
+  content: url(bullet.png) / "";
+}
+</style>
+
+<div id="imgparentempty"class="title">
+  <span id="imgchildempty">Some Text</span>
+</div>
+
+<style>
+#divlistparent::before {
+  content: "item1" "item2" url(bullet.png) / "a list of items";
+}
+</style>
+
+<div id="divlistparent" class="title">
+  <span id="divlistchild">Some Text</span>
+</div>
+
+<style>
+#emptylistparent::before {
+  content: url(bullet.png) "item1" "item2" url(bullet.png) / "";
+}
+</style>
+
+<div id="emptylistparent" class="title">
+  <span id="emptylistchild">Some Text</span>
+</div>
+
+<style>
+#firstletterchild::first-letter {
+  color: red;
+  content: "Foo" / "Bar";
+}
+</style>
+
+<div id="firstletterparent">
+  <p id="firstletterchild">Some Text</p>
+</div>
+
+<style>
+#divcontent {
+  content: url(bullet.png) / "alt";
+}
+</style>
+
+<div id="divcontent">Div text content</div>
+
+<!--- The following test cases are merely here to test that the addition of alt
+text support has not altered the default behaviour if the content property is
+incorrectly supplied -->
+
+<style>
+#divdoubleimage {
+  content: url(bullet.png) url(bullet.png) / "alt";
+}
+</style>
+
+<div id="divdoubleimage">DOM Text</div>
+
+<style>
+#divtextcontent {
+  content: "text content replacement" / "alt";
+}
+</style>
+
+<div id="divtextcontent">DOM Text</div>
diff --git a/content/test/data/accessibility/css/counter-text-expected-blink.txt b/content/test/data/accessibility/css/counter-text-expected-blink.txt
new file mode 100644
index 0000000..53a953c
--- /dev/null
+++ b/content/test/data/accessibility/css/counter-text-expected-blink.txt
@@ -0,0 +1,29 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++genericContainer
+++++++++list
+++++++++++listItem
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='1'
+++++++++++++++++inlineTextBox name='1'
+++++++++++++++staticText name=':'
+++++++++++++++++inlineTextBox name=':'
+++++++++++++staticText name='line1'
+++++++++++++++inlineTextBox name='line1'
+++++++++++listItem
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='2'
+++++++++++++++++inlineTextBox name='2'
+++++++++++++++staticText name=':'
+++++++++++++++++inlineTextBox name=':'
+++++++++++++staticText name='line2'
+++++++++++++++inlineTextBox name='line2'
+++++++++++listItem
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='3'
+++++++++++++++++inlineTextBox name='3'
+++++++++++++++staticText name=':'
+++++++++++++++++inlineTextBox name=':'
+++++++++++++staticText name='line3'
+++++++++++++++inlineTextBox name='line3'
diff --git a/content/test/data/accessibility/css/counter-text.html b/content/test/data/accessibility/css/counter-text.html
new file mode 100644
index 0000000..e1df1662
--- /dev/null
+++ b/content/test/data/accessibility/css/counter-text.html
@@ -0,0 +1,12 @@
+<style>
+ol li::before { content: counter(l1) ":"; counter-increment: l1;}
+ol li { list-style-type: decimial; display: block; }
+</style>
+
+<div id="container" style="counter-reset:l1;">
+<ol style="list-style-type:decimal">
+<li id="line1">line1
+<li id="line2">line2
+<li>line3
+</ol>
+</div>
diff --git a/content/test/data/accessibility/css/first-letter-expected-blink.txt b/content/test/data/accessibility/css/first-letter-expected-blink.txt
new file mode 100644
index 0000000..3540848f
--- /dev/null
+++ b/content/test/data/accessibility/css/first-letter-expected-blink.txt
@@ -0,0 +1,10 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++paragraph
+++++++++genericContainer ignored
+++++++++++genericContainer ignored
+++++++++++++staticText name='T'
+++++++++++++++inlineTextBox name='T'
+++++++++staticText name='his starts with a large T.'
+++++++++++inlineTextBox name='his starts with a large T.'
diff --git a/content/test/data/accessibility/css/first-letter.html b/content/test/data/accessibility/css/first-letter.html
new file mode 100644
index 0000000..a4b6895
--- /dev/null
+++ b/content/test/data/accessibility/css/first-letter.html
@@ -0,0 +1,5 @@
+<style type="text/css">
+p:first-letter { color: lime; font-size: xx-large; }
+p:before { color: red; content: 'T'; }
+</style>
+<p>his starts with a large T.
diff --git a/content/test/data/accessibility/css/next-on-line-check-failure-expected-blink.txt b/content/test/data/accessibility/css/next-on-line-check-failure-expected-blink.txt
index 525fa5b..387611d 100644
--- a/content/test/data/accessibility/css/next-on-line-check-failure-expected-blink.txt
+++ b/content/test/data/accessibility/css/next-on-line-check-failure-expected-blink.txt
@@ -2,5 +2,6 @@
 ++genericContainer ignored
 ++++genericContainer ignored
 ++++list
-++++++staticText name='0'
-++++++++inlineTextBox name='0'
+++++++genericContainer ignored
+++++++++staticText name='0'
+++++++++++inlineTextBox name='0'
diff --git a/content/test/data/accessibility/css/pseudo-elements-expected-auralinux.txt b/content/test/data/accessibility/css/pseudo-elements-expected-auralinux.txt
new file mode 100644
index 0000000..3d03565a
--- /dev/null
+++ b/content/test/data/accessibility/css/pseudo-elements-expected-auralinux.txt
@@ -0,0 +1,5 @@
+[document web]
+++[heading] name='Foo'
+++++[static] name='[ '
+++++[static] name='Foo'
+++++[static] name=' ]'
diff --git a/content/test/data/accessibility/css/pseudo-elements-expected-blink.txt b/content/test/data/accessibility/css/pseudo-elements-expected-blink.txt
new file mode 100644
index 0000000..e509658f
--- /dev/null
+++ b/content/test/data/accessibility/css/pseudo-elements-expected-blink.txt
@@ -0,0 +1,12 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++heading name='Foo'
+++++++++genericContainer ignored
+++++++++++staticText name='[ '
+++++++++++++inlineTextBox name='[ '
+++++++++staticText name='Foo'
+++++++++++inlineTextBox name='Foo'
+++++++++genericContainer ignored
+++++++++++staticText name=' ]'
+++++++++++++inlineTextBox name=' ]'
diff --git a/content/test/data/accessibility/css/pseudo-elements.html b/content/test/data/accessibility/css/pseudo-elements.html
new file mode 100644
index 0000000..377f891c
--- /dev/null
+++ b/content/test/data/accessibility/css/pseudo-elements.html
@@ -0,0 +1,5 @@
+<style>
+h1::before { content:"   [   "; }
+h1::after { content:"   ]   "; }
+</style>
+<h1 class="generated">Foo</h1>
diff --git a/content/test/data/accessibility/html/action-verbs-expected-blink.txt b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
index 56ac9cc..05f452d6 100644
--- a/content/test/data/accessibility/html/action-verbs-expected-blink.txt
+++ b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
@@ -26,7 +26,8 @@
 ++++++switch name='ARIA Switch' defaultActionVerb=check checkedState=false
 ++++++details
 ++++++++disclosureTriangle collapsed name='Summary' defaultActionVerb=press
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='Summary'
 ++++++++++++inlineTextBox name='Summary'
 ++++++popUpButton collapsed value='Pop-up button' defaultActionVerb=open haspopup=menu
diff --git a/content/test/data/accessibility/html/details-expected-blink.txt b/content/test/data/accessibility/html/details-expected-blink.txt
index 342636c1..a72cf5b4 100644
--- a/content/test/data/accessibility/html/details-expected-blink.txt
+++ b/content/test/data/accessibility/html/details-expected-blink.txt
@@ -3,12 +3,14 @@
 ++++genericContainer ignored
 ++++++details
 ++++++++disclosureTriangle collapsed name='details tag'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='details tag'
 ++++++++++++inlineTextBox name='details tag'
 ++++++details
 ++++++++disclosureTriangle name='details tag open'
-++++++++++staticText ignored name='â–¾ '
+++++++++++listMarker ignored name='â–¾ '
+++++++++++++staticText ignored name='â–¾ '
 ++++++++++staticText name='details tag open'
 ++++++++++++inlineTextBox name='details tag open'
 ++++++++paragraph
diff --git a/content/test/data/accessibility/html/generated-content-after-hidden-input-expected-blink.txt b/content/test/data/accessibility/html/generated-content-after-hidden-input-expected-blink.txt
index 755bb9e..a4753a2 100644
--- a/content/test/data/accessibility/html/generated-content-after-hidden-input-expected-blink.txt
+++ b/content/test/data/accessibility/html/generated-content-after-hidden-input-expected-blink.txt
@@ -3,5 +3,6 @@
 ++++genericContainer ignored
 ++++++paragraph
 ++++++++textField ignored invisible
-++++++++staticText name='*'
-++++++++++inlineTextBox name='*'
+++++++++genericContainer ignored
+++++++++++staticText name='*'
+++++++++++++inlineTextBox name='*'
diff --git a/content/test/data/accessibility/html/generated-content-in-empty-page-expected-blink.txt b/content/test/data/accessibility/html/generated-content-in-empty-page-expected-blink.txt
index 86b7513..ebf5f3c4 100644
--- a/content/test/data/accessibility/html/generated-content-in-empty-page-expected-blink.txt
+++ b/content/test/data/accessibility/html/generated-content-in-empty-page-expected-blink.txt
@@ -1,9 +1,11 @@
 rootWebArea
 ++genericContainer ignored
 ++++genericContainer ignored
-++++++staticText name='"'
-++++++++inlineTextBox name='"'
+++++++genericContainer ignored
+++++++++staticText name='"'
+++++++++++inlineTextBox name='"'
 ++++genericContainer
 ++++++genericContainer ignored
-++++++++staticText name='''
-++++++++++inlineTextBox name='''
\ No newline at end of file
+++++++++genericContainer ignored
+++++++++++staticText name='''
+++++++++++++inlineTextBox name='''
diff --git a/content/test/data/accessibility/html/landmark-expected-blink.txt b/content/test/data/accessibility/html/landmark-expected-blink.txt
index 5f94d36..f2b8083f 100644
--- a/content/test/data/accessibility/html/landmark-expected-blink.txt
+++ b/content/test/data/accessibility/html/landmark-expected-blink.txt
@@ -68,7 +68,8 @@
 ++++++++++++inlineTextBox name='This should NOT have banner role.'
 ++++++details
 ++++++++disclosureTriangle name='Details'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='Details'
 ++++++++++++inlineTextBox name='Details'
 ++++++group
@@ -116,7 +117,8 @@
 ++++++++++++++inlineTextBox name='This should NOT have banner role.'
 ++++++details
 ++++++++disclosureTriangle name='Details'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='Details'
 ++++++++++++inlineTextBox name='Details'
 ++++++group
@@ -163,7 +165,8 @@
 ++++++++++++inlineTextBox name='This should NOT have footer role.'
 ++++++details
 ++++++++disclosureTriangle name='Details'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='Details'
 ++++++++++++inlineTextBox name='Details'
 ++++++group
@@ -211,7 +214,8 @@
 ++++++++++++++inlineTextBox name='This should NOT have footer role.'
 ++++++details
 ++++++++disclosureTriangle name='Details'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='Details'
 ++++++++++++inlineTextBox name='Details'
 ++++++group
diff --git a/content/test/data/accessibility/html/q-expected-blink.txt b/content/test/data/accessibility/html/q-expected-blink.txt
index 2e5ecaf..6c9cedc4 100644
--- a/content/test/data/accessibility/html/q-expected-blink.txt
+++ b/content/test/data/accessibility/html/q-expected-blink.txt
@@ -5,12 +5,14 @@
 ++++++++staticText name='This is '
 ++++++++++inlineTextBox name='This is '
 ++++++++genericContainer ignored
-++++++++++staticText name='"'
-++++++++++++inlineTextBox name='"'
+++++++++++genericContainer ignored
+++++++++++++staticText name='"'
+++++++++++++++inlineTextBox name='"'
 ++++++++staticText name='Chromium Blink'
 ++++++++++inlineTextBox name='Chromium Blink'
 ++++++++genericContainer ignored
-++++++++++staticText name='"'
-++++++++++++inlineTextBox name='"'
+++++++++++genericContainer ignored
+++++++++++++staticText name='"'
+++++++++++++++inlineTextBox name='"'
 ++++++++staticText name=' based browser.'
 ++++++++++inlineTextBox name=' based browser.'
diff --git a/content/test/data/accessibility/html/summary-expected-blink.txt b/content/test/data/accessibility/html/summary-expected-blink.txt
index 9b624dda..294f7f3 100644
--- a/content/test/data/accessibility/html/summary-expected-blink.txt
+++ b/content/test/data/accessibility/html/summary-expected-blink.txt
@@ -3,6 +3,7 @@
 ++++genericContainer ignored
 ++++++details
 ++++++++disclosureTriangle collapsed name='details tag'
-++++++++++staticText ignored name='â–¸ '
+++++++++++listMarker ignored name='â–¸ '
+++++++++++++staticText ignored name='â–¸ '
 ++++++++++staticText name='details tag'
 ++++++++++++inlineTextBox name='details tag'
diff --git a/content/test/dwrite_font_fake_sender_win.cc b/content/test/dwrite_font_fake_sender_win.cc
index e916c00..d0caad8 100644
--- a/content/test/dwrite_font_fake_sender_win.cc
+++ b/content/test/dwrite_font_fake_sender_win.cc
@@ -15,11 +15,11 @@
 namespace content {
 
 void AddFamily(const base::FilePath& font_path,
-               const std::wstring& family_name,
+               const base::string16& family_name,
                const std::wstring& base_family_name,
                FakeFontCollection* collection) {
   collection->AddFont(family_name)
-      .AddFamilyName(L"en-us", family_name)
+      .AddFamilyName(STRING16_LITERAL("en-us"), family_name)
       .AddFilePath(font_path.Append(L"\\" + base_family_name + L".ttf"))
       .AddFilePath(font_path.Append(L"\\" + base_family_name + L"bd.ttf"))
       .AddFilePath(font_path.Append(L"\\" + base_family_name + L"bi.ttf"))
@@ -34,17 +34,20 @@
 base::RepeatingCallback<
     mojo::PendingRemote<blink::mojom::DWriteFontProxy>(void)>
 CreateFakeCollectionSender() {
-  std::vector<base::char16> font_path_chars;
+  std::vector<wchar_t> font_path_chars;
   font_path_chars.resize(MAX_PATH);
   SHGetSpecialFolderPath(nullptr /*hwndOwner - reserved*/,
                          font_path_chars.data(), CSIDL_FONTS,
                          FALSE /*fCreate*/);
-  base::FilePath font_path(base::string16(font_path_chars.data()));
+  base::FilePath font_path(std::wstring(font_path_chars.data()));
   std::unique_ptr<FakeFontCollection> fake_collection =
       std::make_unique<FakeFontCollection>();
-  AddFamily(font_path, L"Arial", L"arial", fake_collection.get());
-  AddFamily(font_path, L"Courier New", L"cour", fake_collection.get());
-  AddFamily(font_path, L"Times New Roman", L"times", fake_collection.get());
+  AddFamily(font_path, STRING16_LITERAL("Arial"), L"arial",
+            fake_collection.get());
+  AddFamily(font_path, STRING16_LITERAL("Courier New"), L"cour",
+            fake_collection.get());
+  AddFamily(font_path, STRING16_LITERAL("Times New Roman"), L"times",
+            fake_collection.get());
   return base::BindRepeating(&CreateFakeCollectionRemote,
                              std::move(fake_collection));
 }
diff --git a/device/vr/android/arcore/arcore_impl.cc b/device/vr/android/arcore/arcore_impl.cc
index c0cc152..1f902bc7 100644
--- a/device/vr/android/arcore/arcore_impl.cc
+++ b/device/vr/android/arcore/arcore_impl.cc
@@ -807,9 +807,8 @@
                           kOpaque_SkAlphaType),
         SkBitmap::kZeroPixels_AllocFlag);
     SkCanvas gray_canvas(canvas_bitmap);
-    SkPaint paint;
     sk_sp<SkImage> src_image = SkImage::MakeFromBitmap(src_bitmap);
-    gray_canvas.drawImage(src_image, 0, 0, &paint);
+    gray_canvas.drawImage(src_image, 0, 0);
     SkPixmap gray_pixmap;
     if (!gray_canvas.peekPixels(&gray_pixmap)) {
       DLOG(WARNING) << __func__ << ": failed to access grayscale bitmap";
diff --git a/docs/speed/benchmark/harnesses/desktop_ui.md b/docs/speed/benchmark/harnesses/desktop_ui.md
index 8e2060d9..63d3d90 100644
--- a/docs/speed/benchmark/harnesses/desktop_ui.md
+++ b/docs/speed/benchmark/harnesses/desktop_ui.md
@@ -2,7 +2,7 @@
 
 ## Overview
 
-Desktop UI Benchmark is used to measure and monitor Desktop UI performance.
+Desktop UI Benchmark is used to measure and monitor Desktop UI performance based on the [Telemetry](https://chromium.googlesource.com/catapult/+/HEAD/telemetry/README.md) framework.
 It captures important metrics such as
 
 * Initial load time
@@ -43,13 +43,15 @@
 There are 3 ways to add metrics to the benchmarking code
 
 1. Add UMA metrics to your code and include them in the [story definition](../../../../tools/perf/page_sets/desktop_ui/tab_search_story.py). The listed UMA metrics will show up on the result page automatically.
-2. Add C++ trace with name starts with "webui_metric:". Make sure your trace has category "browser" or add other categories that you use to the story definition. For example:
+2. Add C++ trace with name starts with "custom_metric:". For example:
    ```c++
    void Foo::DoWork() {
-     TRACE_EVENT0("browser", "webui_metric:Foo:DoWork");
+     TRACE_EVENT0("browser", "custom_metric:Foo:DoWork");
      ...
    }
    ```
+   This method requires 'customMetric' added to your story definition. If your story extends from [MultiTabStory](../../../../tools/perf/page_sets/desktop_ui/multitab_story.py) it's already been taken care of. Also make sure to enable the trace categories you want to add in your story definition.
+
 3. Add Javascript performance.mark() with names end with ":benchmark_begin" and ":benchmark_end". Time between performance.mark('<YOUR_METRIC_NAME>:benchmark_begin') and performance.mark('<YOUR_METRIC_NAME>:benchmark') will show up as YOUR_METRIC_NAME on the result page. For example:
    ```javascript
    function calc() {
@@ -67,12 +69,22 @@
      });
    }
    ```
+   This method requires 'customMetric' added to your story definition and enable the trace category 'blink.user_timing'. If your story extends from [MultiTabStory](../../../../tools/perf/page_sets/desktop_ui/multitab_story.py) it's already been taken care of.
 
-## Record new stories
+
+## Add new stories
 
 Add new stories to [here](../../../../tools/perf/page_sets/desktop_ui/desktop_ui_stories.py).
 Generally we want to put most of the user journeys in the main story so we only need to run 1 story to verify a CL in most cases. However, if the user journey may affect metrics of other user journeys, you should make it a separate story.
 
+- If your new stories don't need external network requests, you are done now.
+- If your new stories need external network requests and extend from MultiTabStory or other existing stories, add an item to [here](../../../../tools/perf/page_sets/data/desktop_ui.json) to reuse some of the existing recorded stories
+- If your new stories need external network requests that can't be reused from existing stories, follow the next section to record your own stories.
+
+Finally, run the new stories locally to make sure they work, then upload the CL and run a pinpoint job to make sure they work before starting code review.
+
+## Record new stories
+
 Use the following command to record a story
 ```
 tools/perf/record_wpr --browser-executable=out/Default/chrome desktop_ui --story-filter=<YOUR_STORY_NAME>
diff --git a/gpu/command_buffer/service/gr_cache_controller.cc b/gpu/command_buffer/service/gr_cache_controller.cc
index ef1f761..ee21020 100644
--- a/gpu/command_buffer/service/gr_cache_controller.cc
+++ b/gpu/command_buffer/service/gr_cache_controller.cc
@@ -77,6 +77,10 @@
     auto* api = gl::g_current_gl_context;
     api->glFlushFn();
   }
+
+  // Skia store VkPipeline cache only on demand. We do it when we're idle idle
+  // as it might take time.
+  context_state_->StoreVkPipelineCacheIfNeeded();
 }
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/gr_shader_cache.cc b/gpu/command_buffer/service/gr_shader_cache.cc
index 7cd7a87..ec87bb2 100644
--- a/gpu/command_buffer/service/gr_shader_cache.cc
+++ b/gpu/command_buffer/service/gr_shader_cache.cc
@@ -6,11 +6,15 @@
 
 #include <inttypes.h>
 
+#include "base/auto_reset.h"
 #include "base/base64.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/trace_event.h"
+#include "gpu/config/gpu_finch_features.h"
+#include "third_party/skia/include/gpu/GrDirectContext.h"
 
 namespace gpu {
 namespace raster {
@@ -24,12 +28,31 @@
   return SkData::MakeWithCopy(str.c_str(), str.length());
 }
 
+enum class VkPipelinePopulatedCacheEntryUsage {
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  kUsed = 0,
+  kOverwritten = 1,
+  kDiscardedTooLarge = 2,
+  kDiscardedHaveNewer = 3,
+  kEvicted = 4,
+  kMaxValue = kEvicted
+};
+
+void ReportPipelinePopulatedCacheEntryUsage(
+    VkPipelinePopulatedCacheEntryUsage usage) {
+  UMA_HISTOGRAM_ENUMERATION("GPU.Vulkan.PipelineCache.PopulatedCacheUsage",
+                            usage);
+}
+
 }  // namespace
 
 GrShaderCache::GrShaderCache(size_t max_cache_size_bytes, Client* client)
     : cache_size_limit_(max_cache_size_bytes),
       store_(Store::NO_AUTO_EVICT),
-      client_(client) {
+      client_(client),
+      enable_vk_pipeline_cache_(
+          base::FeatureList::IsEnabled(features::kEnableVkPipelineCache)) {
   if (base::ThreadTaskRunnerHandle::IsSet()) {
     base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
         this, "GrShaderCache", base::ThreadTaskRunnerHandle::Get());
@@ -47,9 +70,32 @@
 
   CacheKey cache_key(SkData::MakeWithoutCopy(key.data(), key.size()));
   auto it = store_.Get(cache_key);
+
+  if (IsVkPipelineCacheEntry(cache_key)) {
+    UMA_HISTOGRAM_BOOLEAN("GPU.Vulkan.PipelineCache.LoadCacheHit",
+                          it != store_.end());
+    if (it != store_.end() && it->second.prefetched_but_not_read) {
+      // This entry was loaded from the disk and skia used it.
+      ReportPipelinePopulatedCacheEntryUsage(
+          VkPipelinePopulatedCacheEntryUsage::kUsed);
+    }
+  }
+
   if (it == store_.end())
     return nullptr;
 
+  if (it->second.prefetched_but_not_read) {
+    it->second.prefetched_but_not_read = false;
+    // Skia just loaded shader that was loaded from the disk. We assume it
+    // happens during VkGraphicsPipeline creation and might alter the pipeline
+    // cache. We'll store it to disk later when we're idle.
+
+    // Note, there is no reliable way to check if this is VkGraphicsPipeline
+    // entry or not, so we don't distinguish here and will try to store pipeline
+    // cache even if we just loaded it. It should happen only once per GrContext
+    // creation.
+    need_store_pipeline_cache_ = true;
+  }
   WriteToDisk(it->first, &it->second);
   return it->second.data;
 }
@@ -58,40 +104,63 @@
   TRACE_EVENT0("gpu", "GrShaderCache::store");
   DCHECK_NE(current_client_id_, kInvalidClientId);
 
+  CacheKey cache_key(SkData::MakeWithCopy(key.data(), key.size()));
+  if (IsVkPipelineCacheEntry(cache_key)) {
+    auto size_in_kb = data.size() / 1024;
+    UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.Vulkan.PipelineCache.Size", size_in_kb, 32,
+                                10 * 1024, 100);
+  }
+
   if (data.size() > cache_size_limit_)
     return;
   EnforceLimits(data.size());
 
-  CacheKey cache_key(SkData::MakeWithCopy(key.data(), key.size()));
   auto existing_it = store_.Get(cache_key);
   if (existing_it != store_.end()) {
     // Skia may ignore the cached entry and regenerate a shader if it fails to
     // link, in which case replace the current version with the latest one.
-    EraseFromCache(existing_it);
+    EraseFromCache(existing_it, /*overwriting=*/true);
   }
 
   CacheData cache_data(SkData::MakeWithCopy(data.data(), data.size()));
   auto it = AddToCache(cache_key, std::move(cache_data));
 
   WriteToDisk(it->first, &it->second);
+
+  // Skia just stored new shader, we assume it happens during VkGraphicsPipeline
+  // creation and might alter the pipeline cache. We'll store it to disk later
+  // when we're idle.
+  need_store_pipeline_cache_ = true;
 }
 
 void GrShaderCache::PopulateCache(const std::string& key,
                                   const std::string& data) {
   TRACE_EVENT0("gpu", "GrShaderCache::PopulateCache");
-  if (data.length() > cache_size_limit_)
-    return;
 
-  EnforceLimits(data.size());
-
-  // If we already have this in the cache, skia may have populated it before it
-  // was loaded off the disk cache. Its better to keep the latest version
-  // generated version than overwriting it here.
   std::string decoded_key;
   base::Base64Decode(key, &decoded_key);
   CacheKey cache_key(MakeData(decoded_key));
-  if (store_.Get(cache_key) != store_.end())
+
+  if (data.length() > cache_size_limit_) {
+    if (IsVkPipelineCacheEntry(cache_key)) {
+      ReportPipelinePopulatedCacheEntryUsage(
+          VkPipelinePopulatedCacheEntryUsage::kDiscardedTooLarge);
+    }
     return;
+  }
+
+  EnforceLimits(data.size());
+
+  // If we already have this in the cache, skia may have stored it before it
+  // was loaded off the disk cache. Its better to keep the latest version
+  // generated version than overwriting it here.
+  if (store_.Get(cache_key) != store_.end()) {
+    if (IsVkPipelineCacheEntry(cache_key)) {
+      ReportPipelinePopulatedCacheEntryUsage(
+          VkPipelinePopulatedCacheEntryUsage::kDiscardedHaveNewer);
+    }
+    return;
+  }
 
   CacheData cache_data(MakeData(data));
   auto it = AddToCache(cache_key, std::move(cache_data));
@@ -99,6 +168,7 @@
   // This was loaded off the disk cache, no need to push this back for disk
   // write.
   it->second.pending_disk_write = false;
+  it->second.prefetched_but_not_read = true;
 }
 
 GrShaderCache::Store::iterator GrShaderCache::AddToCache(CacheKey key,
@@ -109,9 +179,16 @@
 }
 
 template <typename Iterator>
-void GrShaderCache::EraseFromCache(Iterator it) {
+void GrShaderCache::EraseFromCache(Iterator it, bool overwriting) {
   DCHECK_GE(curr_size_bytes_, it->second.data->size());
 
+  if (it->second.prefetched_but_not_read && IsVkPipelineCacheEntry(it->first)) {
+    // We're about to erase populated entry, it won't be used anymore.
+    ReportPipelinePopulatedCacheEntryUsage(
+        overwriting ? VkPipelinePopulatedCacheEntryUsage::kOverwritten
+                    : VkPipelinePopulatedCacheEntryUsage::kEvicted);
+  }
+
   curr_size_bytes_ -= it->second.data->size();
   store_.Erase(it);
 }
@@ -173,7 +250,32 @@
   DCHECK_LE(size_needed, cache_size_limit_);
 
   while (size_needed + curr_size_bytes_ > cache_size_limit_)
-    EraseFromCache(store_.rbegin());
+    EraseFromCache(store_.rbegin(), /*overwriting=*/false);
+}
+
+void GrShaderCache::StoreVkPipelineCacheIfNeeded(GrDirectContext* gr_context) {
+  if (enable_vk_pipeline_cache_ && need_store_pipeline_cache_) {
+    {
+      base::ScopedClosureRunner uma_runner(base::BindOnce(
+          [](base::Time time) {
+            UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+                "GPU.Vulkan.PipelineCache.StoreDuration",
+                base::Time::Now() - time, base::TimeDelta::FromMicroseconds(1),
+                base::TimeDelta::FromMicroseconds(5000), 50);
+          },
+          base::Time::Now()));
+      gr_context->storeVkPipelineCacheData();
+    }
+
+    need_store_pipeline_cache_ = false;
+  }
+}
+
+// This function is used only to facilitate debug metrics, this is not reliable
+// way and it should be removed when the feature is launched and we know how
+// cache is performing.
+bool GrShaderCache::IsVkPipelineCacheEntry(const CacheKey& key) {
+  return key.data->size() == 4;
 }
 
 GrShaderCache::ScopedCacheUse::ScopedCacheUse(GrShaderCache* cache,
diff --git a/gpu/command_buffer/service/gr_shader_cache.h b/gpu/command_buffer/service/gr_shader_cache.h
index a05cbed9..b2b38e6 100644
--- a/gpu/command_buffer/service/gr_shader_cache.h
+++ b/gpu/command_buffer/service/gr_shader_cache.h
@@ -13,6 +13,8 @@
 #include "gpu/gpu_gles2_export.h"
 #include "third_party/skia/include/gpu/GrContextOptions.h"
 
+class GrDirectContext;
+
 namespace gpu {
 namespace raster {
 
@@ -56,6 +58,8 @@
   size_t num_cache_entries() const { return store_.size(); }
   size_t curr_size_bytes_for_testing() const { return curr_size_bytes_; }
 
+  void StoreVkPipelineCacheIfNeeded(GrDirectContext* gr_context);
+
  private:
   static constexpr int32_t kInvalidClientId = 0;
 
@@ -83,7 +87,13 @@
     bool operator==(const CacheData& other) const;
 
     sk_sp<SkData> data;
+
+    // Indicates that this cache entry needs to be written to the disk.
     bool pending_disk_write = true;
+
+    // Indicates that this cache entry was loaded from the disk and hasn't been
+    // read yet.
+    bool prefetched_but_not_read = false;
   };
 
   struct CacheKeyHash {
@@ -96,10 +106,12 @@
 
   Store::iterator AddToCache(CacheKey key, CacheData data);
   template <typename Iterator>
-  void EraseFromCache(Iterator it);
+  void EraseFromCache(Iterator it, bool overwriting);
 
   void WriteToDisk(const CacheKey& key, CacheData* data);
 
+  bool IsVkPipelineCacheEntry(const CacheKey& key);
+
   size_t cache_size_limit_;
   size_t curr_size_bytes_ = 0u;
   Store store_;
@@ -109,6 +121,9 @@
 
   int32_t current_client_id_ = kInvalidClientId;
 
+  bool need_store_pipeline_cache_ = false;
+  const bool enable_vk_pipeline_cache_;
+
   DISALLOW_COPY_AND_ASSIGN(GrShaderCache);
 };
 
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 265d07b..d01ba78 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -2374,7 +2374,8 @@
     }
     paint.setBlendMode(SkBlendMode::kSrc);
     canvas->drawImageRect(source_image, gfx::RectToSkRect(source_rect),
-                          gfx::RectToSkRect(dest_rect), &paint);
+                          gfx::RectToSkRect(dest_rect), SkSamplingOptions(),
+                          &paint, SkCanvas::kStrict_SrcRectConstraint);
   }
 
   FlushAndSubmitIfNecessary(dest_scoped_access->surface(),
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index b3c77b9cd..a0ce85ff 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -13,12 +13,14 @@
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/command_buffer/service/context_state.h"
 #include "gpu/command_buffer/service/gl_context_virtual.h"
+#include "gpu/command_buffer/service/gr_shader_cache.h"
 #include "gpu/command_buffer/service/service_transfer_cache.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/skia_utils.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/config/skia_limits.h"
+#include "gpu/ipc/common/gpu_client_ids.h"
 #include "gpu/vulkan/buildflags.h"
 #include "skia/buildflags.h"
 #include "ui/gl/gl_bindings.h"
@@ -251,10 +253,11 @@
 bool SharedContextState::InitializeGrContext(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
-    GrContextOptions::PersistentCache* cache,
+    gpu::raster::GrShaderCache* cache,
     GpuProcessActivityFlags* activity_flags,
     gl::ProgressReporter* progress_reporter) {
   progress_reporter_ = progress_reporter;
+  gr_shader_cache_ = cache;
 
 #if defined(OS_MAC)
   if (metal_context_provider_)
@@ -659,6 +662,14 @@
     gr_context_->resetContext();
 }
 
+void SharedContextState::StoreVkPipelineCacheIfNeeded() {
+  if (gr_context_ && GrContextIsVulkan()) {
+    gpu::raster::GrShaderCache::ScopedCacheUse use(gr_shader_cache_,
+                                                   kDisplayCompositorClientId);
+    gr_shader_cache_->StoreVkPipelineCacheIfNeeded(gr_context_);
+  }
+}
+
 bool SharedContextState::initialized() const {
   return true;
 }
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h
index 2f2f12d..976ba8f 100644
--- a/gpu/command_buffer/service/shared_context_state.h
+++ b/gpu/command_buffer/service/shared_context_state.h
@@ -55,6 +55,7 @@
 }  // namespace gles2
 
 namespace raster {
+class GrShaderCache;
 class RasterDecoderTestBase;
 }  // namespace raster
 
@@ -83,7 +84,7 @@
 
   bool InitializeGrContext(const GpuPreferences& gpu_preferences,
                            const GpuDriverBugWorkarounds& workarounds,
-                           GrContextOptions::PersistentCache* cache,
+                           gpu::raster::GrShaderCache* cache,
                            GpuProcessActivityFlags* activity_flags = nullptr,
                            gl::ProgressReporter* progress_reporter = nullptr);
   bool GrContextIsGL() const {
@@ -116,6 +117,8 @@
 
   void PessimisticallyResetGrContext() const;
 
+  void StoreVkPipelineCacheIfNeeded();
+
   gl::GLShareGroup* share_group() { return share_group_.get(); }
   gl::GLContext* context() { return context_.get(); }
   gl::GLContext* real_context() { return real_context_.get(); }
@@ -328,6 +331,7 @@
   std::unique_ptr<ServiceTransferCache> transfer_cache_;
   uint64_t skia_gr_cache_size_ = 0;
   std::vector<uint8_t> scratch_deserialization_buffer_;
+  gpu::raster::GrShaderCache* gr_shader_cache_ = nullptr;
 
   // |need_context_state_reset| is set whenever Skia may have altered the
   // driver's GL state.
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index ee24d43..bc23f9d 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -178,6 +178,10 @@
 const base::Feature kEnableGrShaderCacheForVulkan{
     "EnableGrShaderCacheForVulkan", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enable persistent storage of VkPipelineCache data.
+const base::Feature kEnableVkPipelineCache{"EnableVkPipelineCache",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
 bool IsUsingVulkan() {
 #if defined(OS_ANDROID)
   // Force on if Vulkan feature is enabled from command line.
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index 06cb3730..39f2e44 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -60,6 +60,8 @@
 
 GPU_EXPORT extern const base::Feature kEnableGrShaderCacheForVulkan;
 
+GPU_EXPORT extern const base::Feature kEnableVkPipelineCache;
+
 GPU_EXPORT bool IsUsingVulkan();
 #if defined(OS_ANDROID)
 GPU_EXPORT bool IsAImageReaderEnabled();
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py
index 4ce93db..71e67a0 100755
--- a/gpu/vulkan/generate_bindings.py
+++ b/gpu/vulkan/generate_bindings.py
@@ -129,6 +129,7 @@
       'vkCreateDescriptorSetLayout',
       'vkCreateFence',
       'vkCreateFramebuffer',
+      'vkCreateGraphicsPipelines',
       'vkCreateImage',
       'vkCreateImageView',
       'vkCreateRenderPass',
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc
index d58f2e4..f1377f9 100644
--- a/gpu/vulkan/vulkan_function_pointers.cc
+++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -531,6 +531,14 @@
     return false;
   }
 
+  vkCreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(
+      vkGetDeviceProcAddr(vk_device, "vkCreateGraphicsPipelines"));
+  if (!vkCreateGraphicsPipelines) {
+    DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                  << "vkCreateGraphicsPipelines";
+    return false;
+  }
+
   vkCreateImage = reinterpret_cast<PFN_vkCreateImage>(
       vkGetDeviceProcAddr(vk_device, "vkCreateImage"));
   if (!vkCreateImage) {
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h
index a49de762..1ec6898e 100644
--- a/gpu/vulkan/vulkan_function_pointers.h
+++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -188,6 +188,7 @@
   VulkanFunction<PFN_vkCreateDescriptorSetLayout> vkCreateDescriptorSetLayout;
   VulkanFunction<PFN_vkCreateFence> vkCreateFence;
   VulkanFunction<PFN_vkCreateFramebuffer> vkCreateFramebuffer;
+  VulkanFunction<PFN_vkCreateGraphicsPipelines> vkCreateGraphicsPipelines;
   VulkanFunction<PFN_vkCreateImage> vkCreateImage;
   VulkanFunction<PFN_vkCreateImageView> vkCreateImageView;
   VulkanFunction<PFN_vkCreateRenderPass> vkCreateRenderPass;
@@ -700,6 +701,17 @@
   return gpu::GetVulkanFunctionPointers()->vkCreateFramebuffer(
       device, pCreateInfo, pAllocator, pFramebuffer);
 }
+ALWAYS_INLINE VkResult
+vkCreateGraphicsPipelines(VkDevice device,
+                          VkPipelineCache pipelineCache,
+                          uint32_t createInfoCount,
+                          const VkGraphicsPipelineCreateInfo* pCreateInfos,
+                          const VkAllocationCallbacks* pAllocator,
+                          VkPipeline* pPipelines) {
+  return gpu::GetVulkanFunctionPointers()->vkCreateGraphicsPipelines(
+      device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
+      pPipelines);
+}
 ALWAYS_INLINE VkResult vkCreateImage(VkDevice device,
                                      const VkImageCreateInfo* pCreateInfo,
                                      const VkAllocationCallbacks* pAllocator,
diff --git a/gpu/vulkan/vulkan_image.cc b/gpu/vulkan/vulkan_image.cc
index 9f70eaf..5db12a6 100644
--- a/gpu/vulkan/vulkan_image.cc
+++ b/gpu/vulkan/vulkan_image.cc
@@ -271,9 +271,12 @@
     return false;
   }
 
-  // If the |image_tiling_| is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
-  // The InitializeWithExternalMemoryAndModifiers() will get the layout.
-  if (image_tiling_ == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+  // Get subresource layout for images with VK_IMAGE_TILING_LINEAR.
+  // For images with VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the layout is
+  // initialized in InitializeWithExternalMemoryAndModifiers(). For
+  // VK_IMAGE_TILING_OPTIMAL the layout is not usable and
+  // vkGetImageSubresourceLayout() is illegal.
+  if (image_tiling_ != VK_IMAGE_TILING_LINEAR)
     return true;
 
   plane_count_ = 1;
diff --git a/gpu/vulkan/vulkan_util.cc b/gpu/vulkan/vulkan_util.cc
index d9345b8..9f6c9d7 100644
--- a/gpu/vulkan/vulkan_util.cc
+++ b/gpu/vulkan/vulkan_util.cc
@@ -113,6 +113,25 @@
   return vkQueueSubmit(queue, submitCount, pSubmits, fence);
 }
 
+VkResult CreateGraphicsPipelinesHook(
+    VkDevice device,
+    VkPipelineCache pipelineCache,
+    uint32_t createInfoCount,
+    const VkGraphicsPipelineCreateInfo* pCreateInfos,
+    const VkAllocationCallbacks* pAllocator,
+    VkPipeline* pPipelines) {
+  base::ScopedClosureRunner uma_runner(base::BindOnce(
+      [](base::Time time) {
+        UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+            "GPU.Vulkan.PipelineCache.vkCreateGraphicsPipelines",
+            base::Time::Now() - time, base::TimeDelta::FromMicroseconds(100),
+            base::TimeDelta::FromMicroseconds(50000), 50);
+      },
+      base::Time::Now()));
+  return vkCreateGraphicsPipelines(device, pipelineCache, createInfoCount,
+                                   pCreateInfos, pAllocator, pPipelines);
+}
+
 void RecordImportingVKSemaphoreIntoGL() {
   g_import_semaphore_into_gl_count++;
 }
diff --git a/gpu/vulkan/vulkan_util.h b/gpu/vulkan/vulkan_util.h
index a17f2cd7..8e512012 100644
--- a/gpu/vulkan/vulkan_util.h
+++ b/gpu/vulkan/vulkan_util.h
@@ -85,6 +85,15 @@
                                                VkFence fence);
 
 COMPONENT_EXPORT(VULKAN)
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateGraphicsPipelinesHook(VkDevice device,
+                            VkPipelineCache pipelineCache,
+                            uint32_t createInfoCount,
+                            const VkGraphicsPipelineCreateInfo* pCreateInfos,
+                            const VkAllocationCallbacks* pAllocator,
+                            VkPipeline* pPipelines);
+
+COMPONENT_EXPORT(VULKAN)
 VKAPI_ATTR void RecordImportingVKSemaphoreIntoGL();
 
 COMPONENT_EXPORT(VULKAN) void ReportUMAPerSwapBuffers();
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index a98a5d5..5213917 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -21747,7 +21747,7 @@
       }
     }
     builders {
-      name: "lacros-amd64-generic-rel"
+      name: "lacros-amd64-generic-binary-size-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builderless:1"
@@ -21805,6 +21805,64 @@
       }
     }
     builders {
+      name: "lacros-amd64-generic-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.gtests_local"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-angle-builder"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index d605882..73961405 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -346,6 +346,10 @@
     short_name: "lcr"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/lacros-amd64-generic-binary-size-rel"
+    category: "chromium.chromiumos|lacros|size"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-lacros-dbg"
     category: "chromium.chromiumos|lacros|x64"
     short_name: "dbg"
@@ -3715,6 +3719,10 @@
     short_name: "lcr"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/lacros-amd64-generic-binary-size-rel"
+    category: "lacros|size"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-lacros-dbg"
     category: "lacros|x64"
     short_name: "dbg"
diff --git a/infra/config/generated/luci-notify.cfg b/infra/config/generated/luci-notify.cfg
index a14fe5c..e33e466 100644
--- a/infra/config/generated/luci-notify.cfg
+++ b/infra/config/generated/luci-notify.cfg
@@ -2907,6 +2907,25 @@
   }
   builders {
     bucket: "ci"
+    name: "lacros-amd64-generic-binary-size-rel"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+  tree_closers {
+    tree_status_host: "chromium-status.appspot.com"
+    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
+  }
+}
+notifiers {
+  notifications {
+    on_occurrence: FAILURE
+    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
+    email {
+      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
+    }
+    template: "tree_closure_email_template"
+  }
+  builders {
+    bucket: "ci"
     name: "lacros-amd64-generic-rel"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index cef8fb09..63bdae45 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -5081,6 +5081,16 @@
   }
 }
 job {
+  id: "lacros-amd64-generic-binary-size-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "lacros-amd64-generic-binary-size-rel"
+  }
+}
+job {
   id: "lacros-amd64-generic-rel"
   realm: "ci"
   acl_sets: "ci"
@@ -6845,6 +6855,7 @@
   triggers: "ios13-sdk-device"
   triggers: "ios14-beta-simulator"
   triggers: "ios14-sdk-simulator"
+  triggers: "lacros-amd64-generic-binary-size-rel"
   triggers: "lacros-amd64-generic-rel"
   triggers: "linux-angle-builder"
   triggers: "linux-angle-chromium-builder"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 9fd2bb1..5446283 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -1656,12 +1656,10 @@
 )
 
 ci.chromiumos_builder(
-    name = "lacros-amd64-generic-rel",
+    name = "lacros-amd64-generic-binary-size-rel",
     console_view_entry = consoles.console_view_entry(
-        category = "lacros|x64",
-        short_name = "rel",
+        category = "lacros|size",
     ),
-    cq_mirrors_console_view = "mirrors",
     main_console_view = "main",
     properties = {
         # The format of these properties is defined at archive/properties.proto
@@ -1693,6 +1691,16 @@
 )
 
 ci.chromiumos_builder(
+    name = "lacros-amd64-generic-rel",
+    console_view_entry = consoles.console_view_entry(
+        category = "lacros|x64",
+        short_name = "rel",
+    ),
+    cq_mirrors_console_view = "mirrors",
+    main_console_view = "main",
+)
+
+ci.chromiumos_builder(
     name = "linux-chromeos-dbg",
     branch_selector = branches.STANDARD_MILESTONE,
     console_view_entry = consoles.console_view_entry(
diff --git a/ios/chrome/browser/policy/BUILD.gn b/ios/chrome/browser/policy/BUILD.gn
index 540de7e..cb53050 100644
--- a/ios/chrome/browser/policy/BUILD.gn
+++ b/ios/chrome/browser/policy/BUILD.gn
@@ -77,6 +77,20 @@
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
+source_set("policy_util") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "policy_util.h",
+    "policy_util.mm",
+  ]
+  deps = [
+    ":feature_flags",
+    "//base",
+    "//components/prefs",
+    "//ios/chrome/browser:pref_names",
+  ]
+}
+
 source_set("feature_flags") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
diff --git a/ios/chrome/browser/policy/policy_util.h b/ios/chrome/browser/policy/policy_util.h
new file mode 100644
index 0000000..461008e
--- /dev/null
+++ b/ios/chrome/browser/policy/policy_util.h
@@ -0,0 +1,30 @@
+// Copyright 2021 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_POLICY_POLICY_UTIL_H_
+#define IOS_CHROME_BROWSER_POLICY_POLICY_UTIL_H_
+
+class PrefService;
+
+// The enum class for IncognitoModeAvalibility pref value, explains the meaning
+// of each value.
+enum class IncognitoModePrefs {
+  // Incognito mode enabled. Users may open pages in both Incognito mode and
+  // normal mode (usually the default behaviour).
+  kEnabled = 0,
+  // Incognito mode disabled. Users may not open pages in Incognito mode.
+  // Only normal mode is available for browsing.
+  kDisabled,
+  // Incognito mode forced. Users may open pages *ONLY* in Incognito mode.
+  // Normal mode is not available for browsing.
+  kForced,
+};
+
+// Returns true if incognito mode is disabled by enterprise policy.
+bool IsIncognitoModeDisabled(PrefService* pref_service);
+
+// Returns true if incognito mode is forced by enterprise policy.
+bool IsIncognitoModeForced(PrefService* pref_service);
+
+#endif  // IOS_CHROME_BROWSER_POLICY_POLICY_UTIL_H_
diff --git a/ios/chrome/browser/prefs/prefs_util.mm b/ios/chrome/browser/policy/policy_util.mm
similarity index 86%
rename from ios/chrome/browser/prefs/prefs_util.mm
rename to ios/chrome/browser/policy/policy_util.mm
index 3c71f01..6e917ef7 100644
--- a/ios/chrome/browser/prefs/prefs_util.mm
+++ b/ios/chrome/browser/policy/policy_util.mm
@@ -1,13 +1,12 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/prefs/prefs_util.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 
 #include "components/prefs/pref_service.h"
 #include "ios/chrome/browser/policy/policy_features.h"
 #include "ios/chrome/browser/pref_names.h"
-#include "ios/chrome/browser/prefs/browser_prefs.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn
index 0c048eda..e664dcda 100644
--- a/ios/chrome/browser/prefs/BUILD.gn
+++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -29,8 +29,6 @@
   sources = [
     "browser_prefs.h",
     "browser_prefs.mm",
-    "prefs_util.h",
-    "prefs_util.mm",
   ]
   deps = [
     "//components/autofill/core/browser",
@@ -80,7 +78,7 @@
     "//ios/chrome/browser/memory",
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/net",
-    "//ios/chrome/browser/policy:feature_flags",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/prerender:prerender_pref",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/ui/authentication",
diff --git a/ios/chrome/browser/prefs/browser_prefs.h b/ios/chrome/browser/prefs/browser_prefs.h
index d6496d6..c318f19 100644
--- a/ios/chrome/browser/prefs/browser_prefs.h
+++ b/ios/chrome/browser/prefs/browser_prefs.h
@@ -12,18 +12,6 @@
 class PrefRegistrySyncable;
 }
 
-enum class IncognitoModePrefs {
-  // Incognito mode enabled. Users may open pages in both Incognito mode and
-  // normal mode (usually the default behaviour).
-  kEnabled = 0,
-  // Incognito mode disabled. Users may not open pages in Incognito mode.
-  // Only normal mode is available for browsing.
-  kDisabled,
-  // Incognito mode forced. Users may open pages *ONLY* in Incognito mode.
-  // Normal mode is not available for browsing.
-  kForced,
-};
-
 // Registers all prefs that will be used via the local state PrefService.
 void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
 
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 7088c2d..a5d594d9 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -60,6 +60,7 @@
 #import "ios/chrome/browser/memory/memory_debugger_manager.h"
 #import "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h"
 #include "ios/chrome/browser/notification_promo.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/prerender/prerender_pref.h"
 #import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h"
diff --git a/ios/chrome/browser/prefs/prefs_util.h b/ios/chrome/browser/prefs/prefs_util.h
deleted file mode 100644
index 0b8f59c..0000000
--- a/ios/chrome/browser/prefs/prefs_util.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020 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_PREFS_PREFS_UTIL_H_
-#define IOS_CHROME_BROWSER_PREFS_PREFS_UTIL_H_
-
-class PrefService;
-
-// Returns true if incognito mode is disabled by enterprise policy.
-bool IsIncognitoModeDisabled(PrefService* pref_service);
-
-// Returns true if incognito mode is forced by enterprise policy.
-bool IsIncognitoModeForced(PrefService* pref_service);
-
-#endif  // IOS_CHROME_BROWSER_PREFS_PREFS_UTIL_H_
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index 0c35c72c..b735fee3 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -24,7 +24,7 @@
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/history",
     "//ios/chrome/browser/main:public",
-    "//ios/chrome/browser/prefs:browser_prefs",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui/activity_services",
     "//ios/chrome/browser/ui/alert_coordinator",
@@ -92,7 +92,7 @@
     "//ios/chrome/browser/drag_and_drop",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/metrics:metrics_internal",
-    "//ios/chrome/browser/prefs:browser_prefs",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/alert_coordinator",
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm
index 2c3d56e..5634b4c 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.mm
+++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -11,7 +11,7 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
 #import "ios/chrome/browser/main/browser.h"
-#import "ios/chrome/browser/prefs/prefs_util.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
 #import "ios/chrome/browser/ui/activity_services/activity_params.h"
 #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
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 cf68c46f..34d465c 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -19,7 +19,7 @@
 #import "ios/chrome/browser/drag_and_drop/table_view_url_drag_drop_handler.h"
 #import "ios/chrome/browser/main/browser.h"
 #import "ios/chrome/browser/metrics/new_tab_page_uma.h"
-#import "ios/chrome/browser/prefs/prefs_util.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn
index ee0c6c0..bbcb960 100644
--- a/ios/chrome/browser/ui/main/BUILD.gn
+++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -108,7 +108,7 @@
     "//ios/chrome/browser/main",
     "//ios/chrome/browser/ntp:features",
     "//ios/chrome/browser/policy",
-    "//ios/chrome/browser/prefs:browser_prefs",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/screenshot",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/snapshots",
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 075b4a6..9d685ae 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -52,8 +52,8 @@
 #import "ios/chrome/browser/main/browser_list_factory.h"
 #import "ios/chrome/browser/main/browser_util.h"
 #include "ios/chrome/browser/ntp/features.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/policy/policy_watcher_browser_agent.h"
-#import "ios/chrome/browser/prefs/prefs_util.h"
 #include "ios/chrome/browser/screenshot/screenshot_delegate.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
index d6e35a9..05de291 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -62,11 +62,6 @@
 @property(nonatomic, strong)
     NSLayoutConstraint* contentSuggestionsHeightConstraint;
 
-// Constraint to determine the Y position of the contained ContentSuggestions
-// view.
-@property(nonatomic, strong)
-    NSLayoutConstraint* contentSuggestionsTopConstraint;
-
 // Array of constraints used to pin the fake Omnibox header into the top of the
 // view.
 @property(nonatomic, strong)
@@ -125,11 +120,8 @@
                                          .discoverFeed];
   [self.discoverFeedWrapperViewController.discoverFeed
       addChildViewController:self.contentSuggestionsViewController];
-  // Add contentSuggestionsView to
-  // discoverFeedWrapperViewController.discoverFeed.view so its width is not
-  // restrained by the width of
-  // discoverFeedWrapperViewController.discoverFeed.feedCollectionView.
-  [containerView addSubview:contentSuggestionsView];
+  [self.discoverFeedWrapperViewController.feedCollectionView
+      addSubview:contentSuggestionsView];
   [self.contentSuggestionsViewController
       didMoveToParentViewController:self.discoverFeedWrapperViewController
                                         .discoverFeed];
@@ -137,12 +129,10 @@
   self.contentSuggestionsHeightConstraint = [contentSuggestionsView.heightAnchor
       constraintEqualToConstant:self.contentSuggestionsViewController
                                     .collectionView.contentSize.height];
-  self.contentSuggestionsTopConstraint =
-      [containerView.safeAreaLayoutGuide.topAnchor
-          constraintEqualToAnchor:contentSuggestionsView.topAnchor];
 
   [NSLayoutConstraint activateConstraints:@[
-    self.contentSuggestionsTopConstraint,
+    [self.discoverFeedWrapperViewController.feedCollectionView.topAnchor
+        constraintEqualToAnchor:contentSuggestionsView.bottomAnchor],
     [containerView.safeAreaLayoutGuide.leadingAnchor
         constraintEqualToAnchor:contentSuggestionsView.leadingAnchor],
     [containerView.safeAreaLayoutGuide.trailingAnchor
@@ -282,10 +272,6 @@
     return;
   }
 
-  // Scroll up the contentSuggestions view along the scrolling of the feed.
-  self.contentSuggestionsTopConstraint.constant =
-      scrollView.contentOffset.y + [self adjustedContentSuggestionsHeight];
-
   [self.overscrollActionsController scrollViewDidScroll:scrollView];
   [self.headerSynchronizer updateFakeOmniboxOnCollectionScroll];
   self.scrolledToTop =
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn
index 399002d0..1f5ee56 100644
--- a/ios/chrome/browser/ui/popup_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -63,7 +63,7 @@
     "//ios/chrome/browser/overlays/public/web_content_area",
     "//ios/chrome/browser/policy",
     "//ios/chrome/browser/policy:feature_flags",
-    "//ios/chrome/browser/prefs:browser_prefs",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/search_engines",
     "//ios/chrome/browser/translate",
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 60cd408..e6405ca 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -32,7 +32,7 @@
 #import "ios/chrome/browser/overlays/public/web_content_area/http_auth_overlay.h"
 #include "ios/chrome/browser/policy/browser_policy_connector_ios.h"
 #include "ios/chrome/browser/policy/policy_features.h"
-#import "ios/chrome/browser/prefs/prefs_util.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/search_engines/search_engines_util.h"
 #import "ios/chrome/browser/translate/chrome_ios_translate_client.h"
 #import "ios/chrome/browser/ui/activity_services/canonical_url_retriever.h"
diff --git a/ios/chrome/browser/ui/settings/privacy/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
index 5c41334..4c1de3f 100644
--- a/ios/chrome/browser/ui/settings/privacy/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
@@ -24,7 +24,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browsing_data:feature_flags",
     "//ios/chrome/browser/main:public",
-    "//ios/chrome/browser/prefs:browser_prefs",
+    "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm
index 4f491aa..809cd114 100644
--- a/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm
@@ -18,8 +18,8 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/browsing_data/browsing_data_features.h"
 #import "ios/chrome/browser/main/browser.h"
+#import "ios/chrome/browser/policy/policy_util.h"
 #include "ios/chrome/browser/pref_names.h"
-#import "ios/chrome/browser/prefs/prefs_util.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h"
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index eff5f33..8fa45bc 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -63,8 +63,6 @@
   "public/cwv_preferences.h",
   "public/cwv_preview_element_info.h",
   "public/cwv_script_command.h",
-  "public/cwv_scroll_view.h",
-  "public/cwv_scroll_view_delegate.h",
   "public/cwv_ssl_status.h",
   "public/cwv_sync_controller.h",
   "public/cwv_sync_controller_data_source.h",
@@ -142,8 +140,6 @@
     "internal/cwv_preview_element_info_internal.h",
     "internal/cwv_script_command.mm",
     "internal/cwv_script_command_internal.h",
-    "internal/cwv_scroll_view.mm",
-    "internal/cwv_scroll_view_internal.h",
     "internal/cwv_ssl_status.mm",
     "internal/cwv_ssl_status_internal.h",
     "internal/cwv_user_content_controller.mm",
@@ -333,35 +329,10 @@
   ]
 }
 
-# Two umbrella headers may be generated:
-# - One that matches ios_web_view_output_name, e.g. CronetChromeWebView.h
-# - Another that is hardcoded as ChromeWebView.h
-#
-# This is needed to fix the issue where the generated .modulemap points to a
-# non-existent umbrella header.
-#
-# TODO(crbug.com/1084855): Remove :web_view_umbrella_header_old after all
-# clients migrate off of it.
-if (ios_web_view_generate_extra_umbrella_header) {
-  action("web_view_umbrella_header") {
-    script = "//build/config/ios/generate_umbrella_header.py"
-
-    full_header_path = target_gen_dir + "/" + ios_web_view_output_name + ".h"
-    outputs = [ full_header_path ]
-
-    args = [
-      "--output-path",
-      rebase_path(full_header_path, root_build_dir),
-    ]
-
-    args += rebase_path(ios_web_view_public_headers, root_build_dir)
-  }
-}
-
-action("web_view_umbrella_header_old") {
+action("web_view_umbrella_header") {
   script = "//build/config/ios/generate_umbrella_header.py"
 
-  full_header_path = target_gen_dir + "/ChromeWebView.h"
+  full_header_path = target_gen_dir + "/" + ios_web_view_output_name + ".h"
   outputs = [ full_header_path ]
 
   args = [
@@ -380,10 +351,7 @@
   output_name = ios_web_view_output_name
   info_plist_target = ":info_plist"
 
-  public_headers = get_target_outputs(":web_view_umbrella_header_old")
-  if (ios_web_view_generate_extra_umbrella_header) {
-    public_headers += get_target_outputs(":web_view_umbrella_header")
-  }
+  public_headers = get_target_outputs(":web_view_umbrella_header")
   public_headers += ios_web_view_public_headers
   if (ios_web_view_include_cronet) {
     public_headers += [ "//components/cronet/ios/Cronet.h" ]
@@ -403,10 +371,7 @@
     "//ios/web/public/init",
     "//testing/gtest:ios_coverage_utils",
   ]
-  deps += [ ":web_view_umbrella_header_old" ]
-  if (ios_web_view_generate_extra_umbrella_header) {
-    deps += [ ":web_view_umbrella_header" ]
-  }
+  deps += [ ":web_view_umbrella_header" ]
   if (ios_web_view_include_cronet) {
     deps += [ "//components/cronet/ios:cronet_sources" ]
   }
@@ -450,7 +415,6 @@
     "internal/cwv_html_element_unittest.mm",
     "internal/cwv_preferences_unittest.mm",
     "internal/cwv_preview_element_info_unittest.mm",
-    "internal/cwv_scroll_view_unittest.mm",
     "internal/cwv_ssl_status_unittest.mm",
     "internal/cwv_web_view_configuration_unittest.mm",
     "internal/metrics/cwv_metrics_provider_unittest.mm",
diff --git a/ios/web_view/features.gni b/ios/web_view/features.gni
index 772ba8f1..6d731811 100644
--- a/ios/web_view/features.gni
+++ b/ios/web_view/features.gni
@@ -9,14 +9,3 @@
   # Controls the output name of the built framework.
   ios_web_view_output_name = "ChromeWebView"
 }
-
-declare_args() {
-  # If ios_web_view_output_name is overriden, e.g. to CronetChromeWebView, we
-  # need to generate an extra umbrella header to match the output name of the
-  # framework bundle.
-  #
-  # TODO(crbug.com/1084855): Remove this after all clients migrate to the
-  # umbrella header that matches the framework.
-  ios_web_view_generate_extra_umbrella_header =
-      ios_web_view_output_name != "ChromeWebView"
-}
diff --git a/ios/web_view/internal/cwv_scroll_view.mm b/ios/web_view/internal/cwv_scroll_view.mm
deleted file mode 100644
index 6158a28..0000000
--- a/ios/web_view/internal/cwv_scroll_view.mm
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web_view/public/cwv_scroll_view.h"
-
-#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
-#import "ios/web_view/internal/cwv_scroll_view_internal.h"
-#import "ios/web_view/public/cwv_scroll_view_delegate.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface CWVScrollView ()<CRWWebViewScrollViewProxyObserver>
-
-// For KVO compliance, redefines the property as readwrite and calls its setter
-// when the value changes, instead of defining a getter which directly calls
-// _proxy.contentSize.
-@property(nonatomic, readwrite) CGSize contentSize;
-
-@end
-
-@implementation CWVScrollView
-
-@synthesize contentSize = _contentSize;
-@synthesize contentOffset = _contentOffset;
-@synthesize delegate = _delegate;
-@synthesize proxy = _proxy;
-
-- (void)setProxy:(nullable CRWWebViewScrollViewProxy*)proxy {
-  [_proxy removeObserver:self];
-  _proxy = proxy;
-  self.contentSize = _proxy.contentSize;
-  [self updateContentOffset];
-  [_proxy addObserver:self];
-}
-
-- (void)setContentOffset:(CGPoint)contentOffset {
-  _proxy.contentOffset = contentOffset;
-  [self updateContentOffset];
-}
-
-- (UIEdgeInsets)scrollIndicatorInsets {
-  return _proxy.scrollIndicatorInsets;
-}
-
-- (void)setScrollIndicatorInsets:(UIEdgeInsets)scrollIndicatorInsets {
-  _proxy.scrollIndicatorInsets = scrollIndicatorInsets;
-}
-
-- (CGRect)bounds {
-  return {_proxy.contentOffset, _proxy.frame.size};
-}
-
-- (BOOL)isDecelerating {
-  return _proxy.decelerating;
-}
-
-- (BOOL)isDragging {
-  return _proxy.dragging;
-}
-
-- (BOOL)isTracking {
-  return _proxy.tracking;
-}
-
-- (BOOL)scrollsToTop {
-  return _proxy.scrollsToTop;
-}
-
-- (void)setScrollsToTop:(BOOL)scrollsToTop {
-  _proxy.scrollsToTop = scrollsToTop;
-}
-
-- (BOOL)bounces {
-  return _proxy.bounces;
-}
-
-- (void)setBounces:(BOOL)bounces {
-  _proxy.bounces = bounces;
-}
-
-- (UIScrollViewContentInsetAdjustmentBehavior)contentInsetAdjustmentBehavior
-    API_AVAILABLE(ios(11.0)) {
-  return _proxy.contentInsetAdjustmentBehavior;
-}
-
-- (void)setContentInsetAdjustmentBehavior:
-    (UIScrollViewContentInsetAdjustmentBehavior)contentInsetAdjustmentBehavior
-    API_AVAILABLE(ios(11.0)) {
-  _proxy.contentInsetAdjustmentBehavior = contentInsetAdjustmentBehavior;
-}
-
-- (UIPanGestureRecognizer*)panGestureRecognizer {
-  return _proxy.panGestureRecognizer;
-}
-
-- (NSArray<__kindof UIView*>*)subviews {
-  return _proxy.subviews;
-}
-
-- (UIEdgeInsets)contentInset {
-  return _proxy.contentInset;
-}
-
-- (void)setContentInset:(UIEdgeInsets)contentInset {
-  _proxy.contentInset = contentInset;
-}
-
-- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated {
-  [_proxy setContentOffset:contentOffset animated:animated];
-  [self updateContentOffset];
-}
-
-- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer {
-  [_proxy addGestureRecognizer:gestureRecognizer];
-}
-
-- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer {
-  [_proxy removeGestureRecognizer:gestureRecognizer];
-}
-
-#pragma mark - NSObject
-
-- (void)dealloc {
-  // Removes |self| from |_proxy|'s observers. Otherwise |_proxy| will keep a
-  // dangling pointer to |self| and cause SEGV later.
-  [_proxy removeObserver:self];
-}
-
-#pragma mark - CRWWebViewScrollViewObserver
-
-- (void)webViewScrollViewWillBeginDragging:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  SEL selector = @selector(scrollViewWillBeginDragging:);
-  if ([_delegate respondsToSelector:selector]) {
-    [_delegate scrollViewWillBeginDragging:self];
-  }
-}
-- (void)webViewScrollViewWillEndDragging:
-            (CRWWebViewScrollViewProxy*)webViewScrollViewProxy
-                            withVelocity:(CGPoint)velocity
-                     targetContentOffset:(inout CGPoint*)targetContentOffset {
-  SEL selector =
-      @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:);
-  if ([_delegate respondsToSelector:selector]) {
-    [_delegate scrollViewWillEndDragging:self
-                            withVelocity:velocity
-                     targetContentOffset:targetContentOffset];
-  }
-}
-
-- (void)webViewScrollViewDidScroll:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  [self updateContentOffset];
-  SEL selector = @selector(scrollViewDidScroll:);
-  if ([_delegate respondsToSelector:selector]) {
-    [_delegate scrollViewDidScroll:self];
-  }
-}
-
-- (void)webViewScrollViewDidEndDecelerating:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  SEL selector = @selector(scrollViewDidEndDecelerating:);
-  if ([_delegate respondsToSelector:selector]) {
-    [_delegate scrollViewDidEndDecelerating:self];
-  }
-}
-
-- (void)webViewScrollViewWillBeginZooming:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  SEL selector = @selector(scrollViewWillBeginZooming:);
-  if ([_delegate respondsToSelector:selector]) {
-    [_delegate scrollViewWillBeginZooming:self];
-  }
-}
-
-- (BOOL)webViewScrollViewShouldScrollToTop:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  if ([_delegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) {
-    return [_delegate scrollViewShouldScrollToTop:self];
-  }
-  return YES;
-}
-
-- (void)webViewScrollViewDidResetContentSize:
-    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
-  self.contentSize = _proxy.contentSize;
-}
-
-- (void)updateContentOffset {
-  [self willChangeValueForKey:@"contentOffset"];
-  _contentOffset = _proxy.contentOffset;
-  [self didChangeValueForKey:@"contentOffset"];
-}
-
-+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
-  if ([key isEqualToString:@"contentOffset"]) {
-    return NO;
-  }
-  return [super automaticallyNotifiesObserversForKey:key];
-}
-
-@end
diff --git a/ios/web_view/internal/cwv_scroll_view_internal.h b/ios/web_view/internal/cwv_scroll_view_internal.h
deleted file mode 100644
index 3c91d71..0000000
--- a/ios/web_view/internal/cwv_scroll_view_internal.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_
-#define IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_
-
-#import <Foundation/Foundation.h>
-
-#import "ios/web_view/public/cwv_scroll_view.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@class CRWWebViewScrollViewProxy;
-
-@interface CWVScrollView ()
-
-// Operations to this scroll view are delegated to this proxy.
-@property(nonatomic, weak, readwrite) CRWWebViewScrollViewProxy* proxy;
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif  // IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_
diff --git a/ios/web_view/internal/cwv_scroll_view_unittest.mm b/ios/web_view/internal/cwv_scroll_view_unittest.mm
deleted file mode 100644
index bc65ae6..0000000
--- a/ios/web_view/internal/cwv_scroll_view_unittest.mm
+++ /dev/null
@@ -1,71 +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.
-
-#import "ios/web_view/internal/cwv_scroll_view_internal.h"
-
-#import <UIKit/UIKit.h>
-
-#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
-#import "ios/web_view/public/cwv_scroll_view_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace ios_web_view {
-
-class CWVScrollViewTest : public PlatformTest {
- protected:
-  CWVScrollViewTest() {
-    scroll_view_ = [[CWVScrollView alloc] init];
-
-    scroll_view_proxy_ = [[CRWWebViewScrollViewProxy alloc] init];
-    scroll_view_.proxy = scroll_view_proxy_;
-
-    ui_scroll_view_ = [[UIScrollView alloc] init];
-    [scroll_view_proxy_ setScrollView:ui_scroll_view_];
-  }
-
-  CWVScrollView* scroll_view_;
-  UIScrollView* ui_scroll_view_;
-  CRWWebViewScrollViewProxy* scroll_view_proxy_;
-};
-
-// Tests CWVScrollView delegate callbacks.
-TEST_F(CWVScrollViewTest, DelegateCallbacks) {
-  id delegate = OCMProtocolMock(@protocol(CWVScrollViewDelegate));
-  scroll_view_.delegate = delegate;
-
-  [[delegate expect] scrollViewWillBeginDragging:scroll_view_];
-  [ui_scroll_view_.delegate scrollViewWillBeginDragging:ui_scroll_view_];
-
-  CGPoint targetContentOffset;
-  [[delegate expect] scrollViewWillEndDragging:scroll_view_
-                                  withVelocity:CGPointZero
-                           targetContentOffset:&targetContentOffset];
-  [ui_scroll_view_.delegate scrollViewWillEndDragging:ui_scroll_view_
-                                         withVelocity:CGPointZero
-                                  targetContentOffset:&targetContentOffset];
-
-  [[delegate expect] scrollViewDidScroll:scroll_view_];
-  [ui_scroll_view_.delegate scrollViewDidScroll:ui_scroll_view_];
-
-  [[delegate expect] scrollViewDidEndDecelerating:scroll_view_];
-  [ui_scroll_view_.delegate scrollViewDidEndDecelerating:ui_scroll_view_];
-
-  [[delegate expect] scrollViewShouldScrollToTop:scroll_view_];
-  [ui_scroll_view_.delegate scrollViewShouldScrollToTop:ui_scroll_view_];
-
-  [[delegate expect] scrollViewWillBeginZooming:scroll_view_];
-  [ui_scroll_view_.delegate scrollViewWillBeginZooming:ui_scroll_view_
-                                              withView:nil];
-
-  [delegate verify];
-}
-
-}  // namespace ios_web_view
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm
index eeb140e..269ad0e 100644
--- a/ios/web_view/internal/cwv_web_view.mm
+++ b/ios/web_view/internal/cwv_web_view.mm
@@ -48,7 +48,6 @@
 #import "ios/web_view/internal/cwv_html_element_internal.h"
 #import "ios/web_view/internal/cwv_navigation_action_internal.h"
 #import "ios/web_view/internal/cwv_script_command_internal.h"
-#import "ios/web_view/internal/cwv_scroll_view_internal.h"
 #import "ios/web_view/internal/cwv_ssl_status_internal.h"
 #import "ios/web_view/internal/cwv_web_view_configuration_internal.h"
 #import "ios/web_view/internal/language/web_view_url_language_histogram_factory.h"
@@ -177,7 +176,6 @@
 @synthesize title = _title;
 @synthesize translationController = _translationController;
 @synthesize UIDelegate = _UIDelegate;
-@synthesize legacyScrollView = _legacyScrollView;
 @synthesize visibleURL = _visibleURL;
 @synthesize visibleSSLStatus = _visibleSSLStatus;
 
@@ -243,7 +241,6 @@
   if (self) {
     _configuration = configuration;
     [_configuration registerWebView:self];
-    _legacyScrollView = [[CWVScrollView alloc] init];
 
     [self resetWebStateWithSessionStorage:nil
                           WKConfiguration:wkConfiguration
@@ -820,8 +817,6 @@
   _webState->GetWebViewProxy().allowsBackForwardNavigationGestures =
       allowsBackForwardNavigationGestures;
 
-  _legacyScrollView.proxy = _webState.get()->GetWebViewProxy().scrollViewProxy;
-
   if (_translationController) {
     id<CWVTranslationControllerDelegate> delegate =
         _translationController.delegate;
diff --git a/ios/web_view/public/cwv_scroll_view.h b/ios/web_view/public/cwv_scroll_view.h
deleted file mode 100644
index 9935172..0000000
--- a/ios/web_view/public/cwv_scroll_view.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_
-#define IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_
-
-#import <CoreGraphics/CoreGraphics.h>
-#import <Foundation/Foundation.h>
-#import <UIKit/UIKit.h>
-
-#import "cwv_export.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol CWVScrollViewDelegate;
-
-// Scroll view inside the web view. This is not a subclass of UIScrollView
-// because the underlying //ios/web API only exposes a proxy object of the
-// scroll view, not the raw UIScrollView.
-//
-// These methods are forwarded to the internal UIScrollView. Please see the
-// <UIKit/UIScrollView.h> documentation for details about the following methods.
-CWV_EXPORT
-@interface CWVScrollView : NSObject
-
-// Not KVO compliant.
-@property(nonatomic, readonly) CGRect bounds;
-@property(nonatomic) UIEdgeInsets scrollIndicatorInsets;
-@property(nonatomic, weak) id<CWVScrollViewDelegate> delegate;
-@property(nonatomic, readonly, getter=isDecelerating) BOOL decelerating;
-@property(nonatomic, readonly, getter=isDragging) BOOL dragging;
-@property(nonatomic, readonly, getter=isTracking) BOOL tracking;
-@property(nonatomic) BOOL scrollsToTop;
-@property(nonatomic) BOOL bounces;
-@property(nonatomic)
-    UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior
-        API_AVAILABLE(ios(11.0));
-@property(nonatomic, readonly) UIPanGestureRecognizer* panGestureRecognizer;
-@property(nonatomic, readonly, copy) NSArray<__kindof UIView*>* subviews;
-
-// KVO compliant.
-@property(nonatomic) CGPoint contentOffset;
-@property(nonatomic, readonly) CGSize contentSize;
-
-// Be careful when using this property. There's a bug with the
-// underlying WKWebView where the web view does not respect contentInsets
-// properly when laying out content and calculating innerHeight for Javascript.
-// Content is laid out based on the entire height of the web view rather than
-// the height between the top and bottom insets.
-// https://bugs.webkit.org/show_bug.cgi?id=134230
-// rdar://23584409 (not available on Open Radar)
-//
-// Not KVO compliant.
-@property(nonatomic) UIEdgeInsets contentInset;
-
-- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
-- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;
-- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif  // IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_
diff --git a/ios/web_view/public/cwv_scroll_view_delegate.h b/ios/web_view/public/cwv_scroll_view_delegate.h
deleted file mode 100644
index 31122b1..0000000
--- a/ios/web_view/public/cwv_scroll_view_delegate.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_
-#define IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_
-
-#import <CoreGraphics/CoreGraphics.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@class CWVScrollView;
-
-// Delegete for CWVScrollView.
-//
-// These methods are forwarded from the internal UIScrollViewDelegate. Please
-// see the <UIKit/UIScrollViewDelegate.h> documentation for details about the
-// following methods.
-@protocol CWVScrollViewDelegate<NSObject>
-@optional
-- (void)scrollViewWillBeginDragging:(CWVScrollView*)scrollView;
-- (void)scrollViewWillEndDragging:(CWVScrollView*)scrollView
-                     withVelocity:(CGPoint)velocity
-              targetContentOffset:(inout CGPoint*)targetContentOffset;
-- (void)scrollViewDidScroll:(CWVScrollView*)scrollView;
-- (void)scrollViewDidEndDecelerating:(CWVScrollView*)scrollView;
-- (BOOL)scrollViewShouldScrollToTop:(CWVScrollView*)scrollView;
-
-// The equivalent in UIScrollViewDelegate also takes a parameter (UIView*)view,
-// but CWVScrollViewDelegate doesn't expose it for flexibility of future
-// implementation.
-- (void)scrollViewWillBeginZooming:(CWVScrollView*)webViewScrollViewProxy;
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif  // IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_
diff --git a/ios/web_view/public/cwv_web_view.h b/ios/web_view/public/cwv_web_view.h
index b29b718..318eef8 100644
--- a/ios/web_view/public/cwv_web_view.h
+++ b/ios/web_view/public/cwv_web_view.h
@@ -16,7 +16,6 @@
 @class CWVBackForwardList;
 @class CWVBackForwardListItem;
 @class CWVScriptCommand;
-@class CWVScrollView;
 @class CWVTranslationController;
 @class CWVWebViewConfiguration;
 @protocol CWVNavigationDelegate;
@@ -115,14 +114,6 @@
 // It is reset on state restoration.
 @property(nonatomic, readonly) UIScrollView* scrollView;
 
-// DEPRECATED: Use |scrollView| instead.
-//
-// The old implementation of the scroll view associated with the web view.
-//
-// TODO(crbug.com/1023250): Delete this once clients migrate to the new
-// |scrollView|.
-@property(nonatomic, readonly) CWVScrollView* legacyScrollView;
-
 // A Boolean value indicating whether horizontal swipe gestures will trigger
 // back-forward list navigations.
 @property(nonatomic) BOOL allowsBackForwardNavigationGestures;
diff --git a/ios/web_view/test/scroll_view_kvo_inttest.mm b/ios/web_view/test/scroll_view_kvo_inttest.mm
index 04aa56c..c83e0034 100644
--- a/ios/web_view/test/scroll_view_kvo_inttest.mm
+++ b/ios/web_view/test/scroll_view_kvo_inttest.mm
@@ -17,11 +17,11 @@
 
 namespace ios_web_view {
 
-// Tests that the KVO compliant properties of CWVScrollView correctly report
+// Tests that the KVO compliant properties of UIScrollView correctly report
 // changes.
 typedef ios_web_view::WebViewInttestBase ScrollViewKvoTest;
 
-// Tests that CWVScrollView correctly reports |contentOffset| state.
+// Tests that UIScrollView correctly reports |contentOffset| state.
 TEST_F(ScrollViewKvoTest, contentOffset) {
   Observer* offset_observer = [[Observer alloc] init];
   [offset_observer setObservedObject:web_view_.scrollView
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index ff824b70..a94bf3d2 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -348,7 +348,7 @@
 
 #if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
 template <>
-struct ParamTraits<std::wstring> {
+struct COMPONENT_EXPORT(IPC) ParamTraits<std::wstring> {
   typedef std::wstring param_type;
   static void Write(base::Pickle* m, const param_type& p) {
     m->WriteString16(base::AsStringPiece16(p));
@@ -356,7 +356,7 @@
   static bool Read(const base::Pickle* m,
                    base::PickleIterator* iter,
                    param_type* r);
-  COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
+  static void Log(const param_type& p, std::string* l);
 };
 #endif
 
diff --git a/media/midi/midi_manager_winrt.h b/media/midi/midi_manager_winrt.h
index e059dbc0..accf60f 100644
--- a/media/midi/midi_manager_winrt.h
+++ b/media/midi/midi_manager_winrt.h
@@ -35,7 +35,7 @@
   template <typename InterfaceType,
             typename RuntimeType,
             typename StaticsInterfaceType,
-            base::char16 const* runtime_class_id>
+            wchar_t const* runtime_class_id>
   class MidiPortManager;
 
   // Callbacks on kComTaskRunner.
diff --git a/media/renderers/video_frame_yuv_converter.cc b/media/renderers/video_frame_yuv_converter.cc
index c553a1dc..1aef7ffc 100644
--- a/media/renderers/video_frame_yuv_converter.cc
+++ b/media/renderers/video_frame_yuv_converter.cc
@@ -132,7 +132,9 @@
                          visible_rect.width(), visible_rect.height());
     const SkRect dst_rect =
         SkRect::MakeWH(visible_rect.width(), visible_rect.height());
-    surface->getCanvas()->drawImageRect(image, src_rect, dst_rect, nullptr);
+    surface->getCanvas()->drawImageRect(image, src_rect, dst_rect,
+                                        SkSamplingOptions(), nullptr,
+                                        SkCanvas::kStrict_SrcRectConstraint);
   }
 
   surface->flushAndSubmit();
diff --git a/net/BUILD.gn b/net/BUILD.gn
index e6861b5..850860a 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -867,7 +867,6 @@
       "quic/platform/impl/quic_containers_impl.h",
       "quic/platform/impl/quic_error_code_wrappers_impl.h",
       "quic/platform/impl/quic_estimate_memory_usage_impl.h",
-      "quic/platform/impl/quic_export_impl.h",
       "quic/platform/impl/quic_file_utils_impl.h",
       "quic/platform/impl/quic_flag_utils_impl.h",
       "quic/platform/impl/quic_flags_impl.cc",
@@ -944,7 +943,6 @@
       "quic/quic_transport_client.h",
       "quic/quic_transport_error.cc",
       "quic/quic_transport_error.h",
-      "quiche/common/platform/impl/quiche_export_impl.h",
       "quiche/common/platform/impl/quiche_flag_utils_impl.h",
       "quiche/common/platform/impl/quiche_flags_impl.cc",
       "quiche/common/platform/impl/quiche_flags_impl.h",
@@ -5034,6 +5032,18 @@
   dict = "data/fuzzer_dictionaries/net_get_domain_and_registry_fuzzer.dict"
 }
 
+fuzzer_test("net_base_schemeful_site_fuzzer") {
+  sources = [ "base/schemeful_site_fuzzer.cc" ]
+  deps = [
+    ":net_fuzzer_test_support",
+    "//base",
+    "//net",
+    "//testing/libfuzzer/proto:url_proto",
+    "//testing/libfuzzer/proto:url_proto_converter",
+    "//third_party/libprotobuf-mutator",
+  ]
+}
+
 fuzzer_test("net_cert_ct_decode_signed_certificate_timestamp_fuzzer") {
   sources = [ "cert/decode_signed_certificate_timestamp_fuzzer.cc" ]
   deps = [
diff --git a/net/base/schemeful_site.cc b/net/base/schemeful_site.cc
index d3a8d49b..412de23 100644
--- a/net/base/schemeful_site.cc
+++ b/net/base/schemeful_site.cc
@@ -39,20 +39,6 @@
   if (IsStandardSchemeWithNetworkHost(origin.scheme())) {
     registerable_domain = GetDomainAndRegistry(
         origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-
-    // Create a crash dump if the registerable domain is not safe.
-    // TODO(https://crbug.com/1157010): Remove once we have enough information
-    // to verify whether or not this is what's causing issue 1157010.
-    url::CanonHostInfo host_info;
-    if (!registerable_domain.empty() &&
-        registerable_domain !=
-            CanonicalizeHost(registerable_domain, &host_info)) {
-      static base::debug::CrashKeyString* crash_key_string =
-          base::debug::AllocateCrashKeyString(
-              "schemeful_site_bad_origin", base::debug::CrashKeySize::Size256);
-      url::debug::ScopedOriginCrashKey crash_key(crash_key_string, &origin);
-      base::debug::DumpWithoutCrashing();
-    }
   }
 
   // If origin's host's registrable domain is null, then return (origin's
diff --git a/net/base/schemeful_site.h b/net/base/schemeful_site.h
index 42559c02..cb127e0 100644
--- a/net/base/schemeful_site.h
+++ b/net/base/schemeful_site.h
@@ -107,6 +107,12 @@
   // `site_as_origin_` in order to verify behavior.
   const url::Origin& GetInternalOriginForTesting() const;
 
+  // Testing-only function which allows access to the private
+  // `registrable_domain_or_host` method.
+  std::string registrable_domain_or_host_for_testing() const {
+    return registrable_domain_or_host();
+  }
+
   bool operator==(const SchemefulSite& other) const;
 
   bool operator!=(const SchemefulSite& other) const;
diff --git a/net/base/schemeful_site_fuzzer.cc b/net/base/schemeful_site_fuzzer.cc
new file mode 100644
index 0000000..8d0f862
--- /dev/null
+++ b/net/base/schemeful_site_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 "net/base/schemeful_site.h"
+
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+
+#include "testing/libfuzzer/proto/lpm_interface.h"
+#include "testing/libfuzzer/proto/url.pb.h"
+#include "testing/libfuzzer/proto/url_proto_converter.h"
+#include "url/gurl.h"
+
+namespace {
+void RunAssertions(const net::SchemefulSite& site) {
+  if (site.has_registrable_domain_or_host()) {
+    CHECK_NE(site.registrable_domain_or_host_for_testing().front(), '.');
+  }
+}
+}  // namespace
+
+DEFINE_PROTO_FUZZER(const url_proto::Url& url_message) {
+  std::string native_input = url_proto::Convert(url_message);
+
+  if (getenv("LPM_DUMP_NATIVE_INPUT"))
+    std::cout << native_input << std::endl;
+
+  net::SchemefulSite site((GURL(native_input)));
+
+  RunAssertions(site);
+}
diff --git a/net/quiche/common/platform/impl/quiche_export_impl.h b/net/quiche/common/platform/impl/quiche_export_impl.h
deleted file mode 100644
index 3e9d531..0000000
--- a/net/quiche/common/platform/impl/quiche_export_impl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2019 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 NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
-#define NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
-
-#include "net/base/net_export.h"
-
-// These macros are documented in:
-// net/third_party/quiche/src/common/platform/api/quiche_export.h
-
-#define QUICHE_EXPORT NET_EXPORT
-#define QUICHE_EXPORT_PRIVATE NET_EXPORT_PRIVATE
-#define QUICHE_NO_EXPORT
-
-#endif  // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
diff --git a/net/quiche/common/platform/impl/quiche_logging_impl.h b/net/quiche/common/platform/impl/quiche_logging_impl.h
index 0d1d111b..bc435ff2 100644
--- a/net/quiche/common/platform/impl/quiche_logging_impl.h
+++ b/net/quiche/common/platform/impl/quiche_logging_impl.h
@@ -77,6 +77,22 @@
 
 #define QUICHE_PLOG_IMPL(severity) DVLOG(1)
 
+#define QUICHE_CHECK_IMPL(condition) CHECK(condition)
+#define QUICHE_CHECK_EQ_IMPL(val1, val2) CHECK_EQ(val1, val2)
+#define QUICHE_CHECK_NE_IMPL(val1, val2) CHECK_NE(val1, val2)
+#define QUICHE_CHECK_LE_IMPL(val1, val2) CHECK_LE(val1, val2)
+#define QUICHE_CHECK_LT_IMPL(val1, val2) CHECK_LT(val1, val2)
+#define QUICHE_CHECK_GE_IMPL(val1, val2) CHECK_GE(val1, val2)
+#define QUICHE_CHECK_GT_IMPL(val1, val2) CHECK_GT(val1, val2)
+
+#define QUICHE_DCHECK_IMPL(condition) DCHECK(condition)
+#define QUICHE_DCHECK_EQ_IMPL(val1, val2) DCHECK_EQ(val1, val2)
+#define QUICHE_DCHECK_NE_IMPL(val1, val2) DCHECK_NE(val1, val2)
+#define QUICHE_DCHECK_LE_IMPL(val1, val2) DCHECK_LE(val1, val2)
+#define QUICHE_DCHECK_LT_IMPL(val1, val2) DCHECK_LT(val1, val2)
+#define QUICHE_DCHECK_GE_IMPL(val1, val2) DCHECK_GE(val1, val2)
+#define QUICHE_DCHECK_GT_IMPL(val1, val2) DCHECK_GT(val1, val2)
+
 namespace quic {
 template <typename T>
 NET_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index 4eb361f..7c25cc3 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -32,7 +32,6 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/spdy/spdy_session.h"
 #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h"
 #include "net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h"
 
 namespace net {
@@ -538,7 +537,6 @@
       num_active_sessions++;
   }
   total_size +=
-      base::trace_event::EstimateMemoryUsage(spdy::ObtainHpackHuffmanTable()) +
       base::trace_event::EstimateMemoryUsage(spdy::ObtainHpackStaticTable()) +
       base::trace_event::EstimateMemoryUsage(push_promise_index_);
   base::trace_event::MemoryAllocatorDump* dump =
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn
index 38423f0..52b949e 100644
--- a/net/third_party/quiche/BUILD.gn
+++ b/net/third_party/quiche/BUILD.gn
@@ -29,6 +29,7 @@
 
 source_set("quiche") {
   sources = [
+    "overrides/quiche_platform_impl/quiche_export_impl.h",
     "src/quic/core/quic_error_codes.cc",
     "src/quic/core/quic_error_codes.h",
   ]
@@ -589,8 +590,6 @@
       "src/spdy/core/hpack/hpack_entry.h",
       "src/spdy/core/hpack/hpack_header_table.cc",
       "src/spdy/core/hpack/hpack_header_table.h",
-      "src/spdy/core/hpack/hpack_huffman_table.cc",
-      "src/spdy/core/hpack/hpack_huffman_table.h",
       "src/spdy/core/hpack/hpack_output_stream.cc",
       "src/spdy/core/hpack/hpack_output_stream.h",
       "src/spdy/core/hpack/hpack_static_table.cc",
@@ -1427,7 +1426,6 @@
     "src/spdy/core/hpack/hpack_encoder_test.cc",
     "src/spdy/core/hpack/hpack_entry_test.cc",
     "src/spdy/core/hpack/hpack_header_table_test.cc",
-    "src/spdy/core/hpack/hpack_huffman_table_test.cc",
     "src/spdy/core/hpack/hpack_output_stream_test.cc",
     "src/spdy/core/hpack/hpack_round_trip_test.cc",
     "src/spdy/core/hpack/hpack_static_table_test.cc",
diff --git a/net/third_party/quiche/overrides/quiche_platform_impl/quiche_export_impl.h b/net/third_party/quiche/overrides/quiche_platform_impl/quiche_export_impl.h
new file mode 100644
index 0000000..ff8af25
--- /dev/null
+++ b/net/third_party/quiche/overrides/quiche_platform_impl/quiche_export_impl.h
@@ -0,0 +1,17 @@
+// Copyright 2019 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 NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
+#define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
+
+#include "net/base/net_export.h"
+
+// These macros are documented in:
+// net/third_party/quiche/src/common/platform/api/quiche_export.h
+
+#define QUICHE_EXPORT_IMPL NET_EXPORT
+#define QUICHE_EXPORT_PRIVATE_IMPL NET_EXPORT_PRIVATE
+#define QUICHE_NO_EXPORT_IMPL
+
+#endif  // NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_EXPORT_IMPL_H_
diff --git a/pdf/ppapi_migration/graphics.cc b/pdf/ppapi_migration/graphics.cc
index 482de5c4..aaf1efb 100644
--- a/pdf/ppapi_migration/graphics.cc
+++ b/pdf/ppapi_migration/graphics.cc
@@ -104,8 +104,9 @@
 
 void SkiaGraphics::PaintImage(const Image& image, const gfx::Rect& src_rect) {
   SkRect skia_rect = RectToSkRect(src_rect);
-  skia_graphics_->getCanvas()->drawBitmapRect(image.skia_image(), skia_rect,
-                                              skia_rect, nullptr);
+  skia_graphics_->getCanvas()->drawImageRect(
+      image.skia_image().asImage(), skia_rect, skia_rect, SkSamplingOptions(),
+      nullptr, SkCanvas::kStrict_SrcRectConstraint);
 }
 
 void SkiaGraphics::Scroll(const gfx::Rect& clip, const gfx::Vector2d& amount) {
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc
index 74aaafc7..f1825ff 100644
--- a/printing/backend/print_backend_win.cc
+++ b/printing/backend/print_backend_win.cc
@@ -259,7 +259,7 @@
     return false;
   const wchar_t* name = info_5.get()->pPrinterName;
   const wchar_t* port = info_5.get()->pPortName;
-  DCHECK_EQ(name, base::UTF8ToUTF16(printer_name));
+  DCHECK_EQ(name, base::UTF8ToWide(printer_name));
 
   PrinterSemanticCapsAndDefaults caps;
 
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 1489ac00..32367592 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -384,7 +384,8 @@
     return OnError();
 
   ReleaseContext();
-  context_ = CreateDC(L"WINSPOOL", device_name.c_str(), nullptr, dev_mode);
+  context_ =
+      CreateDC(L"WINSPOOL", base::as_wcstr(device_name), nullptr, dev_mode);
   if (!context_)
     return OnError();
 
diff --git a/remoting/host/security_key/security_key_ipc_server_unittest.cc b/remoting/host/security_key/security_key_ipc_server_unittest.cc
index 0eee35e..156e66a8 100644
--- a/remoting/host/security_key/security_key_ipc_server_unittest.cc
+++ b/remoting/host/security_key/security_key_ipc_server_unittest.cc
@@ -492,7 +492,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Create a fake client and connect to the IPC server channel.
-  FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
+  FakeSecurityKeyIpcClient fake_ipc_client(base::BindRepeating(
       &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
   ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(server_name));
   WaitForOperationComplete();
diff --git a/rlz/test/rlz_test_helpers.cc b/rlz/test/rlz_test_helpers.cc
index d64d437..d3d57b2 100644
--- a/rlz/test/rlz_test_helpers.cc
+++ b/rlz/test/rlz_test_helpers.cc
@@ -84,7 +84,7 @@
   }
 
   // Next write values recursively.
-  for (std::map<base::string16, RegistryKeyData>::const_iterator iter =
+  for (std::map<std::wstring, RegistryKeyData>::const_iterator iter =
            data.keys.begin();
        iter != data.keys.end(); ++iter) {
     base::win::RegKey key(dest->Handle(), iter->first.c_str(), KEY_ALL_ACCESS);
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc
index 4cea399..0584ae9 100644
--- a/services/device/hid/hid_service_win.cc
+++ b/services/device/hid/hid_service_win.cc
@@ -100,16 +100,16 @@
   if (property_type != DEVPROP_TYPE_STRING_LIST)
     return base::nullopt;
 
-  base::string16 buffer16;
+  std::wstring bufferw;
   if (!SetupDiGetDeviceProperty(
           device_info_set, &device_info_data, &property_key, &property_type,
-          reinterpret_cast<PBYTE>(base::WriteInto(&buffer16, required_size)),
+          reinterpret_cast<PBYTE>(base::WriteInto(&bufferw, required_size)),
           required_size, /*RequiredSize=*/nullptr, /*Flags=*/0)) {
     HID_PLOG(DEBUG) << "SetupDiGetDeviceProperty failed";
     return base::nullopt;
   }
 
-  return base::SplitString(buffer16, base::WStringPiece(L"\0", 1),
+  return base::SplitString(bufferw, base::WStringPiece(L"\0", 1),
                            base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 }
 
diff --git a/services/image_annotation/public/cpp/image_processor.cc b/services/image_annotation/public/cpp/image_processor.cc
index a1567f6b..7167140 100644
--- a/services/image_annotation/public/cpp/image_processor.cc
+++ b/services/image_annotation/public/cpp/image_processor.cc
@@ -10,6 +10,7 @@
 #include "base/task_runner_util.h"
 #include "services/image_annotation/image_annotation_metrics.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 
 namespace image_annotation {
@@ -28,7 +29,7 @@
   // Use a canvas to scale the source image onto the new bitmap.
   SkCanvas canvas(dest, SkSurfaceProps{});
   canvas.scale(scale, scale);
-  canvas.drawBitmap(source, 0, 0, nullptr /* paint */);
+  canvas.drawImage(source.asImage(), 0, 0);
 
   return dest;
 }
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index c7e46b57..17e4053 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -214,14 +214,6 @@
 #define SK_DISABLE_REDUCE_OPLIST_SPLITTING
 #endif
 
-#ifndef SK_SUPPORT_LEGACY_DRAWBITMAP
-#define SK_SUPPORT_LEGACY_DRAWBITMAP
-#endif
-
-#ifndef SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
-#define SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
-#endif
-
 // Max. verb count for paths rendered by the edge-AA tessellating path renderer.
 #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 100
 
@@ -254,6 +246,10 @@
 #define SK_SUPPORT_LEGACY_CONVEXITY_DIRECTION_CHANGE
 #endif
 
+#ifndef SK_USE_LEGACY_VK_ALLOCATOR_USAGE_NAMES
+#define SK_USE_LEGACY_VK_ALLOCATOR_USAGE_NAMES
+#endif
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc b/skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc
index f9def0a..1328ef1 100644
--- a/skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc
+++ b/skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc
@@ -8,6 +8,7 @@
 #include "base/test/test_discardable_memory_allocator.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
 
 namespace {
@@ -44,7 +45,7 @@
 
     // This call shouldn't crash or cause ASAN to flag any memory issues
     // If nothing bad happens within this call, everything is fine
-    canvas->drawBitmap(bitmap, 0, 0, &paint);
+    canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
 
     LOG(INFO) << "Filter DAG rendered successfully";
     canvas->restore();
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html
index 54ea3ad..052efcc 100644
--- a/styleguide/c++/c++11.html
+++ b/styleguide/c++/c++11.html
@@ -184,7 +184,7 @@
 <td><code>std::function</code></td>
 <td>Wraps a standard polymorphic function</td>
 <td><a href="http://en.cppreference.com/w/cpp/utility/functional/function">std::function</a></td>
-<td>Use <code>base::Callback</code> instead. Compared to <code>std::function</code>, <code>base::Callback</code> directly supports Chromium's refcounting classes and weak pointers and deals with additional thread safety concerns. <a href="https://groups.google.com/a/chromium.org/forum/#!topic/cxx/SoEj7oIDNuA">Discussion thread</a></td>
+<td>Use <code>base::&lcub;Once,Repeating&rcub;Callback</code> instead. Compared to <code>std::function</code>, <code>base::&lcub;Once,Repeating&rcub;Callback</code> directly supports Chromium's refcounting classes and weak pointers and deals with additional thread safety concerns. <a href="https://groups.google.com/a/chromium.org/forum/#!topic/cxx/SoEj7oIDNuA">Discussion thread</a></td>
 </tr>
 
 <tr>
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index c51bda3..c7b7f6d 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -242,12 +242,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=87",
+          "--client-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
@@ -257,11 +257,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -270,8 +270,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -321,12 +321,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=89",
+          "--client-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
@@ -336,11 +336,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -349,8 +349,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -481,10 +481,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=87",
+          "--impl-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
@@ -494,11 +494,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -507,8 +507,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -560,10 +560,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=89",
+          "--impl-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
@@ -573,11 +573,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -586,8 +586,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -720,12 +720,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=87",
+          "--client-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
@@ -735,11 +735,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -748,8 +748,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -799,12 +799,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=89",
+          "--client-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
@@ -814,11 +814,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -827,8 +827,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -959,10 +959,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=87",
+          "--impl-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
@@ -972,11 +972,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -985,8 +985,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1038,10 +1038,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=89",
+          "--impl-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
@@ -1051,11 +1051,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -1064,8 +1064,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1261,12 +1261,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=87",
+          "--client-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
@@ -1276,11 +1276,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -1289,8 +1289,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1340,12 +1340,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=89",
+          "--client-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
@@ -1355,11 +1355,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -1368,8 +1368,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1500,10 +1500,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=87",
+          "--impl-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
@@ -1513,11 +1513,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -1526,8 +1526,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1579,10 +1579,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=89",
+          "--impl-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
@@ -1592,11 +1592,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -1605,8 +1605,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1802,12 +1802,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=87",
+          "--client-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
@@ -1817,11 +1817,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -1830,8 +1830,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -1881,12 +1881,12 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=89",
+          "--client-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
@@ -1896,11 +1896,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -1909,8 +1909,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -2041,10 +2041,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M87/out/Release",
+          "../../weblayer_instrumentation_test_M89/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=87",
+          "--impl-version=89",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
@@ -2054,11 +2054,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Tests For 89.0.4389.29",
         "resultdb": {
           "enable": true
         },
@@ -2067,8 +2067,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.152"
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.29"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -2120,10 +2120,10 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
+          "../../weblayer_instrumentation_test_M87/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=89",
+          "--impl-version=87",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
@@ -2133,11 +2133,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25"
+            "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 89.0.4389.25",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.152",
         "resultdb": {
           "enable": true
         },
@@ -2146,8 +2146,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.25"
+              "location": "weblayer_instrumentation_test_M87",
+              "revision": "version:87.0.4280.152"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index b8a90f4..1308bdf 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1255,6 +1255,11 @@
       }
     ]
   },
+  "lacros-amd64-generic-binary-size-rel": {
+    "additional_compile_targets": [
+      "chrome"
+    ]
+  },
   "lacros-amd64-generic-rel": {
     "additional_compile_targets": [
       "chrome"
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 5f25cc6..ef31b8d 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -3546,8 +3546,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3565,8 +3564,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3587,8 +3585,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3607,8 +3604,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3626,8 +3622,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3645,8 +3640,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3664,8 +3658,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3683,8 +3676,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3702,8 +3694,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3721,8 +3712,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3741,8 +3731,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3760,8 +3749,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3779,8 +3767,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3801,8 +3788,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3820,8 +3806,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3839,8 +3824,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3858,8 +3842,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3877,8 +3860,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3896,8 +3878,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3915,8 +3896,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3934,8 +3914,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3954,8 +3933,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3973,8 +3951,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3992,8 +3969,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4011,8 +3987,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4030,8 +4005,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4049,8 +4023,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4068,8 +4041,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4087,8 +4059,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4106,8 +4077,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4125,8 +4095,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4144,8 +4113,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4163,8 +4131,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4182,8 +4149,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4201,8 +4167,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4220,8 +4185,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4239,8 +4203,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4258,8 +4221,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4277,8 +4239,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4296,8 +4257,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4315,8 +4275,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4334,8 +4293,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -4354,8 +4312,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4373,8 +4330,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4392,8 +4348,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4411,8 +4366,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4430,8 +4384,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4449,8 +4402,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4468,8 +4420,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4487,8 +4438,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4506,8 +4456,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4525,8 +4474,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4544,8 +4492,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4563,8 +4510,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4582,8 +4528,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4601,8 +4546,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4620,8 +4564,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4639,8 +4582,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4658,8 +4600,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4677,8 +4618,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4696,8 +4636,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4715,8 +4654,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4734,8 +4672,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4753,8 +4690,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4772,8 +4708,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4791,8 +4726,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4810,8 +4744,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4829,8 +4762,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4851,8 +4783,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4870,8 +4801,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4889,8 +4819,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4908,8 +4837,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4927,8 +4855,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4946,8 +4873,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4965,8 +4891,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4984,8 +4909,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5003,8 +4927,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5023,8 +4946,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5042,8 +4964,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5068,8 +4989,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5097,7 +5017,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -5120,8 +5040,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5140,8 +5059,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5165,8 +5083,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5189,8 +5106,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5213,8 +5129,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5236,8 +5151,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5256,8 +5170,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5279,8 +5192,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5302,8 +5214,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5325,8 +5236,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "idempotent": false,
@@ -5353,8 +5263,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "idempotent": false,
@@ -5380,8 +5289,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "none",
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13.6|Mac-10.15"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index ed5bc207..ad0b655 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -533,6 +533,13 @@
       },
     },
   },
+  'mac_10.13_or_10.15': {
+    'swarming': {
+      'dimensions': {
+        'os': 'Mac-10.13.6|Mac-10.15',
+      },
+    },
+  },
   'mac_10.14': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 9c65a7a..90de6db 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -320,13 +320,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=89',
     ],
-    'identifier': 'Implementation Tests For 89.0.4389.25',
+    'identifier': 'Implementation Library Tests For 89.0.4389.29',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M89',
-          'revision': 'version:89.0.4389.25',
+          'revision': 'version:89.0.4389.29',
         }
       ],
     },
@@ -392,13 +392,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=89',
     ],
-    'identifier': 'Implementation Tests For 89.0.4389.25',
+    'identifier': 'Implementation Library Tests For 89.0.4389.29',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M89',
-          'revision': 'version:89.0.4389.25',
+          'revision': 'version:89.0.4389.29',
         }
       ],
     },
@@ -464,13 +464,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--client-version=89',
     ],
-    'identifier': 'Client Tests For 89.0.4389.25',
+    'identifier': 'Client Library Tests For 89.0.4389.29',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M89',
-          'revision': 'version:89.0.4389.25',
+          'revision': 'version:89.0.4389.29',
         }
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 6eed4565..f3a49bf 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1626,6 +1626,11 @@
         },
         'os_type': 'chromeos',
       },
+      'lacros-amd64-generic-binary-size-rel': {
+        'additional_compile_targets': [
+          'chrome',
+        ],
+      },
       'lacros-amd64-generic-rel': {
         'additional_compile_targets': [
           'chrome',
@@ -5053,8 +5058,7 @@
       'Mac10.13 Tests': {
         'mixins': [
             'isolate_profile_data',
-            'mac_10.13',
-            'no_gpu',
+            'mac_10.13_or_10.15',
         ],
         'test_suites': {
           'gtest_tests': 'chromium_mac_gtests_no_nacl',
diff --git a/testing/libfuzzer/fuzzers/skia_image_filter_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/skia_image_filter_proto_fuzzer.cc
index 62e10c08..f4aac2a 100644
--- a/testing/libfuzzer/fuzzers/skia_image_filter_proto_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/skia_image_filter_proto_fuzzer.cc
@@ -19,6 +19,7 @@
 #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
 
 protobuf_mutator::protobuf::LogSilencer log_silencer;
@@ -66,6 +67,6 @@
   canvas.save();
   canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(kBitmapSize),
                                    SkIntToScalar(kBitmapSize)));
-  canvas.drawBitmap(bitmap, 0, 0, &paint);
+  canvas.drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
   canvas.restore();
 }
diff --git a/testing/trigger_scripts/base_test_triggerer.py b/testing/trigger_scripts/base_test_triggerer.py
index 0728e5e..8b18452a 100755
--- a/testing/trigger_scripts/base_test_triggerer.py
+++ b/testing/trigger_scripts/base_test_triggerer.py
@@ -36,25 +36,16 @@
 
 def _convert_to_go_swarming_args(args):
   go_args = []
-  map_flags = {'--dimension', '--env', '--env-prefix', '--named-cache'}
   i = 0
   while i < len(args):
     current_arg = args[i]
     if current_arg == '--swarming':
       current_arg = '--server'
-    elif current_arg == '--resultdb':
-      current_arg = '--enable-resultdb'
     go_args.append(current_arg)
     i += 1
-    if current_arg in map_flags:
+    if current_arg == '--dimension':
       go_args.append('{}={}'.format(args[i], args[i + 1]))
       i += 2
-    elif current_arg == '--cipd-package':
-      # https://source.chromium.org/chromium/infra/infra/+/master:luci/client/swarming.py;l=1175-1177;drc=67e502dbf7a2a863c95e0d54fa486413d24d57a5
-      path, name, version = args[i].split(':', 2)
-      # https://source.chromium.org/chromium/infra/infra/+/master:go/src/go.chromium.org/luci/client/cmd/swarming/lib/trigger.go;l=458-465;drc=ef40d3f3503c2cc7bb0f3f6807b14a39bafb6ce4
-      go_args.append('{}:{}={}'.format(path, name, version))
-      i += 1
   return go_args
 
 
@@ -94,7 +85,7 @@
         respectively.
 
     The arguments are structured like this:
-    <args to swarming.py trigger> -- <args to bot running isolate>
+    <args to swarming trigger> -- <args to bot running isolate>
     This means we have to add arguments to specific locations in the argument
     list, to either affect the trigger command, or what the bot runs.
 
@@ -102,11 +93,9 @@
     bot_args = ['--dump-json', temp_file]
     if total_shards > 1:
       bot_args.append('--env')
-      bot_args.append('GTEST_SHARD_INDEX')
-      bot_args.append(str(shard_index))
+      bot_args.append('GTEST_SHARD_INDEX=%s'%shard_index)
       bot_args.append('--env')
-      bot_args.append('GTEST_TOTAL_SHARDS')
-      bot_args.append(str(total_shards))
+      bot_args.append('GTEST_TOTAL_SHARDS=%s'%total_shards)
     if self._bot_configs:
       for key, val in sorted(self._bot_configs[bot_index].iteritems()):
         bot_args.append('--dimension')
diff --git a/testing/trigger_scripts/base_test_triggerer_unittest.py b/testing/trigger_scripts/base_test_triggerer_unittest.py
index a93eabd1..f741bf1 100755
--- a/testing/trigger_scripts/base_test_triggerer_unittest.py
+++ b/testing/trigger_scripts/base_test_triggerer_unittest.py
@@ -23,14 +23,14 @@
   def test_convert_to_go_swarming_args(self):
     args = [
         '--swarming', 'x.apphost.com', '--dimension', 'pool', 'ci',
-        '--dimension', 'os', 'linux', '--env', 'FOO', 'foo', '--hello',
-        '--cipd-package', 'path:name:123', '--scalar', '42',
-        '--resultdb'
+        '--dimension', 'os', 'linux', '-env', 'FOO=foo', '--hello',
+        '-cipd-package', 'path:name=123', '--scalar', '42',
+        '--enable-resultdb'
     ]
     go_args = base_test_triggerer._convert_to_go_swarming_args(args)
     expected = [
         '--server', 'x.apphost.com', '--dimension', 'pool=ci', '--dimension',
-        'os=linux', '--env', 'FOO=foo', '--hello', '--cipd-package',
+        'os=linux', '-env', 'FOO=foo', '--hello', '-cipd-package',
         'path:name=123', '--scalar', '42', '--enable-resultdb'
     ]
     self.assertEquals(go_args, expected)
@@ -42,13 +42,6 @@
             '--dimension',
             'key',
         ], IndexError),
-        # expected format: --env key value
-        ([
-            '--env',
-            'key',
-        ], IndexError),
-        # expected format: --cipd-package path:name:version
-        (['--cipd-package', 'path:name'], ValueError),
     ]
     for args, ex in invalid_args:
       self.assertRaises(ex, base_test_triggerer._convert_to_go_swarming_args,
diff --git a/testing/trigger_scripts/perf_device_trigger_unittest.py b/testing/trigger_scripts/perf_device_trigger_unittest.py
index 629214df..b2fe947 100755
--- a/testing/trigger_scripts/perf_device_trigger_unittest.py
+++ b/testing/trigger_scripts/perf_device_trigger_unittest.py
@@ -170,7 +170,10 @@
       if not 'trigger' in run:
         continue
       bot_id = run[(run.index('id') + 1)]
-      shard = int(run[(run.index('GTEST_SHARD_INDEX') + 1)])
+
+      g = 'GTEST_SHARD_INDEX='
+      shard = [int(r[len(g):]) for r in run if r.startswith(g)][0]
+
       triggered_map[shard] = bot_id
     return triggered_map
 
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index e7538fb..b4ba66202 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -659,9 +659,10 @@
 // Enable throttling of fetch() requests from service workers in the
 // installing state.  The limit of 3 was chosen to match the limit
 // in background main frames.  In addition, trials showed that this
-// did not cause excessive install delays or timeouts.
+// did not cause excessive timeouts and resulted in a net improvement
+// in successful install rate on some platforms.
 const base::Feature kThrottleInstallingServiceWorker{
-    "ThrottleInstallingServiceWorker", base::FEATURE_DISABLED_BY_DEFAULT};
+    "ThrottleInstallingServiceWorker", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::FeatureParam<int> kInstallingServiceWorkerOutstandingThrottledLimit{
     &kThrottleInstallingServiceWorker, "limit", 3};
 
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 47d7048..bc6f08d9 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -378,7 +378,8 @@
   }
 
   if (context_->CreationAttributes().desynchronized) {
-    CreateLayer();
+    if (!CreateLayer())
+      return nullptr;
     SetNeedsUnbufferedInputEvents(true);
     frame_dispatcher_ = std::make_unique<CanvasResourceDispatcher>(
         nullptr,
@@ -1522,20 +1523,23 @@
   return String();
 }
 
-void HTMLCanvasElement::CreateLayer() {
+bool HTMLCanvasElement::CreateLayer() {
   DCHECK(!surface_layer_bridge_);
   LocalFrame* frame = GetDocument().GetFrame();
   // We do not design transferControlToOffscreen() for frame-less HTML canvas.
-  if (frame) {
-    surface_layer_bridge_ = std::make_unique<::blink::SurfaceLayerBridge>(
-        frame->GetPage()->GetChromeClient().GetFrameSinkId(frame),
-        ::blink::SurfaceLayerBridge::ContainsVideo::kNo, this,
-        base::NullCallback());
-    // Creates a placeholder layer first before Surface is created.
-    surface_layer_bridge_->CreateSolidColorLayer();
-    // This may cause the canvas to be composited.
-    SetNeedsCompositingUpdate();
-  }
+  if (!frame)
+    return false;
+
+  surface_layer_bridge_ = std::make_unique<::blink::SurfaceLayerBridge>(
+      frame->GetPage()->GetChromeClient().GetFrameSinkId(frame),
+      ::blink::SurfaceLayerBridge::ContainsVideo::kNo, this,
+      base::NullCallback());
+  // Creates a placeholder layer first before Surface is created.
+  surface_layer_bridge_->CreateSolidColorLayer();
+  // This may cause the canvas to be composited.
+  SetNeedsCompositingUpdate();
+
+  return true;
 }
 
 void HTMLCanvasElement::OnWebLayerUpdated() {
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
index fd9674e..c0d2761 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -266,7 +266,7 @@
   ::blink::SurfaceLayerBridge* SurfaceLayerBridge() const {
     return surface_layer_bridge_.get();
   }
-  void CreateLayer();
+  bool CreateLayer();
 
   void DetachContext() override { context_ = nullptr; }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 39857e0f..63903de8 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -135,8 +135,8 @@
         end_if_delayed_forbidden_(0),
         should_complete_(0),
         should_attempt_to_end_on_eof_(0),
-        needs_viewport_update_(false),
-        needs_link_header_dispatch_(true) {}
+        needs_link_header_dispatch_(true),
+        have_seen_first_byte_(false) {}
 
   void Trace(Visitor* v) const {}
 
@@ -161,13 +161,10 @@
   bool NeedsLinkHeaderPreloadsDispatch() const {
     return needs_link_header_dispatch_;
   }
-  bool NeedsViewportUpdate() const { return needs_viewport_update_; }
-  void SetNeedsViewportUpdate() { needs_viewport_update_ = true; }
   void DispatchedLinkHeaderPreloads() { needs_link_header_dispatch_ = false; }
-  void UpdatedViewport() {
-    needs_viewport_update_ = false;
-    needs_link_header_dispatch_ = true;
-  }
+
+  bool HaveSeenFirstByte() const { return have_seen_first_byte_; }
+  void SetHaveSeenFirstByte() { have_seen_first_byte_ = true; }
 
   // Keeps track of whether Document::Finish has been called whilst parsing
   // asynchronously. ShouldAttemptToEndOnEOF() means that the parser should
@@ -233,8 +230,8 @@
   // Set to non-zero if Document::Finish has been called and we're operating
   // asynchronously.
   int should_attempt_to_end_on_eof_;
-  bool needs_viewport_update_;
   bool needs_link_header_dispatch_;
+  bool have_seen_first_byte_;
 };
 
 class EndIfDelayedForbiddenScope {
@@ -1316,15 +1313,17 @@
   }
   if (preload_scanner_ && preloader_) {
     preload_scanner_->AppendToEnd(source);
-    if (!task_runner_state_->IsSynchronous() || IsPaused()) {
-      // Should scan and preload if the parser's paused and operating
-      // synchronously, or if the parser's operating in an asynchronous
-      // mode.
+    if (task_runner_state_->GetMode() == kAllowDeferredParsing &&
+        (IsPaused() || !task_runner_state_->HaveSeenFirstByte())) {
+      // Should scan and preload if the parser's paused waiting for a resource,
+      // or if we're starting a document for the first time (we want to at least
+      // prefetch anything that's in the <head> section).
       ScanAndPreload(preload_scanner_.get());
     }
   }
 
   input_.AppendToEnd(source);
+  task_runner_state_->SetHaveSeenFirstByte();
 
   if (InPumpSession()) {
     // We've gotten data off the network in a nested write. We don't want to
@@ -1755,16 +1754,12 @@
   PreloadRequestStream requests =
       scanner->Scan(GetDocument()->ValidBaseElementURL(), &viewport_description,
                     seen_csp_meta_tag);
-  if (viewport_description.has_value()) {
-    task_runner_state_->SetNeedsViewportUpdate();
-  }
   // Make sure that the viewport is up-to-date, so that the correct viewport
   // dimensions will be fed to the background parser and preload scanner.
   if (GetDocument()->Loader() &&
       task_runner_state_->GetMode() == kAllowDeferredParsing) {
-    if (task_runner_state_->NeedsViewportUpdate()) {
+    if (viewport_description.has_value()) {
       GetDocument()->GetStyleEngine().UpdateViewport();
-      task_runner_state_->UpdatedViewport();
     }
     if (task_runner_state_->NeedsLinkHeaderPreloadsDispatch()) {
       if (GetDocument()->Loader()->GetPrefetchedSignedExchangeManager()) {
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.h b/third_party/blink/renderer/core/html/parser/html_document_parser.h
index 5571490..97ebb88 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -241,7 +241,7 @@
   std::unique_ptr<HTMLPreloadScanner> CreatePreloadScanner(
       TokenPreloadScanner::ScannerType);
 
-  // Let the given HTMLPreloadScanner scan the input it has, and then preloads
+  // Let the given HTMLPreloadScanner scan the input it has, and then preload
   // resources using the resulting PreloadRequests and |preloader_|.
   void ScanAndPreload(HTMLPreloadScanner*);
   void FetchQueuedPreloads();
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index 229ac7e..8b9c486 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -327,9 +327,8 @@
       CreateLayerAfterStyleChange();
     }
   } else if (Layer() && Layer()->Parent()) {
-    // Either a transform wasn't specified or the object doesn't support
-    // transforms, so just null out the bit.
-    SetHasTransformRelatedProperty(false);
+    // Either reflection wasn't specified or the object doesn't support
+    // reflection, so just null out the bit.
     SetHasReflection(false);
     Layer()->UpdateFilters(old_style, StyleRef());
     Layer()->UpdateBackdropFilters(old_style, StyleRef());
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 40021a3..5f487f2b2 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1628,7 +1628,7 @@
   }
 
   // Not returning StyleRef().HasTransformRelatedProperty() because some objects
-  // ignore the transform-related styles (e.g. LayoutInline, LayoutSVGBlock).
+  // ignore the transform-related styles (e.g., LayoutInline).
   bool HasTransformRelatedProperty() const {
     NOT_DESTROYED();
     return bitfields_.HasTransformRelatedProperty();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
index d6955a8..91a9779 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
@@ -119,6 +119,11 @@
   NOT_DESTROYED();
   LayoutBlock::StyleDidChange(diff, old_style);
 
+  // |HasTransformRelatedProperty| is used for compositing so ensure it was
+  // correctly set by the call to |StyleDidChange|.
+  DCHECK_EQ(HasTransformRelatedProperty(),
+            StyleRef().HasTransformRelatedProperty());
+
   transform_uses_reference_box_ =
       TransformHelper::DependsOnReferenceBox(StyleRef());
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index 1f08d55..fba14ab 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -146,6 +146,8 @@
       SetNeedsTransformUpdate();
   }
 
+  SetHasTransformRelatedProperty(StyleRef().HasTransformRelatedProperty());
+
   SVGResources::UpdateClipPathFilterMask(*GetElement(), old_style, StyleRef());
 
   if (!Parent())
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 36ace737..3382e4b 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -201,9 +201,31 @@
   reasons &= ~CompositingReason::kWillChangeOther;
   if (style.HasBackdropFilter())
     reasons |= CompositingReason::kBackdropFilter;
+  // Though SVG doesn't support 3D transforms, they are frequently used as a
+  // compositing trigger for historical reasons.
+  reasons |= CompositingReasonsFor3DTransform(object);
   return reasons;
 }
 
+CompositingReasons
+CompositingReasonFinder::PotentialCompositingReasonsFor3DTransform(
+    const ComputedStyle& style) {
+  // Don't composite "trivial" 3D transforms such as translateZ(0).
+  if (Platform::Current()->IsLowEndDevice()) {
+    return style.HasNonTrivial3DTransformOperation()
+               ? CompositingReason::k3DTransform
+               : CompositingReason::kNone;
+  }
+
+  if (style.Has3DTransformOperation()) {
+    return style.HasNonTrivial3DTransformOperation()
+               ? CompositingReason::k3DTransform
+               : CompositingReason::kTrivial3DTransform;
+  }
+
+  return CompositingReason::kNone;
+}
+
 CompositingReasons CompositingReasonFinder::CompositingReasonsFor3DTransform(
     const LayoutObject& layout_object) {
   // Note that we ask the layoutObject if it has a transform, because the
@@ -211,21 +233,7 @@
   // doesn't support them.
   if (!layout_object.HasTransformRelatedProperty())
     return CompositingReason::kNone;
-
-  // Don't composite "trivial" 3D transforms such as translateZ(0).
-  if (Platform::Current()->IsLowEndDevice()) {
-    return layout_object.StyleRef().HasNonTrivial3DTransformOperation()
-               ? CompositingReason::k3DTransform
-               : CompositingReason::kNone;
-  }
-
-  if (layout_object.StyleRef().Has3DTransformOperation()) {
-    return layout_object.StyleRef().HasNonTrivial3DTransformOperation()
-               ? CompositingReason::k3DTransform
-               : CompositingReason::kTrivial3DTransform;
-  }
-
-  return CompositingReason::kNone;
+  return PotentialCompositingReasonsFor3DTransform(layout_object.StyleRef());
 }
 
 CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
index 14bd321..db490daa 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
@@ -39,6 +39,11 @@
   static CompositingReasons CompositingReasonsForAnimation(const LayoutObject&);
   static CompositingReasons CompositingReasonsForWillChange(
       const ComputedStyle&);
+  // Some LayoutObject types do not support transforms (see:
+  // |LayoutObject::HasTransformRelatedProperty|) so this can return reasons
+  // that the LayoutObject does not end up using.
+  static CompositingReasons PotentialCompositingReasonsFor3DTransform(
+      const ComputedStyle&);
   static CompositingReasons CompositingReasonsFor3DTransform(
       const LayoutObject&);
   static bool RequiresCompositingForRootScroller(const PaintLayer&);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index 93ece6f..3ff7187d 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -86,6 +86,10 @@
     return frame->GetFrame()->GetDocument()->getElementById(id);
   }
 
+  LayoutObject* GetLayoutObjectById(const AtomicString& id) {
+    return GetElementById(id)->GetLayoutObject();
+  }
+
   void UpdateAllLifecyclePhases() {
     WebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
         DocumentUpdateReason::kTest);
@@ -263,6 +267,117 @@
   EXPECT_TRUE(transform_node->will_change_transform);
 }
 
+TEST_P(CompositingTest, Compositing3DTransformOnSVGModelObject) {
+  ScopedCompositeSVGForTest enable_feature(true);
+  InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
+    <!doctype html>
+    <svg width="200" height="200">
+      <rect id="target" fill="blue" width="100" height="100"></rect>
+    </svg>
+  )HTML");
+  UpdateAllLifecyclePhases();
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Adding a 3D transform should trigger compositing.
+  auto* target_element = GetElementById("target");
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate3d(0, 0, 1px)");
+  UpdateAllLifecyclePhases();
+  // |HasTransformRelatedProperty| is used in |CompositingReasonsFor3DTransform|
+  // and must be set correctly.
+  ASSERT_TRUE(GetLayoutObjectById("target")->HasTransformRelatedProperty());
+  EXPECT_TRUE(CcLayerByDOMElementId("target"));
+
+  // Removing a 3D transform removes the compositing trigger.
+  target_element->setAttribute(html_names::kStyleAttr, "transform: none");
+  UpdateAllLifecyclePhases();
+  // |HasTransformRelatedProperty| is used in |CompositingReasonsFor3DTransform|
+  // and must be set correctly.
+  ASSERT_FALSE(GetLayoutObjectById("target")->HasTransformRelatedProperty());
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Adding a 2D transform should not trigger compositing.
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate(1px, 0)");
+  UpdateAllLifecyclePhases();
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Switching from a 2D to a 3D transform should trigger compositing.
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate3d(0, 0, 1px)");
+  UpdateAllLifecyclePhases();
+  EXPECT_TRUE(CcLayerByDOMElementId("target"));
+}
+
+TEST_P(CompositingTest, Compositing3DTransformOnSVGBlock) {
+  ScopedCompositeSVGForTest enable_feature(true);
+  InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
+    <!doctype html>
+    <svg width="200" height="200">
+      <text id="target" x="50" y="50">text</text>
+    </svg>
+  )HTML");
+  UpdateAllLifecyclePhases();
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Adding a 3D transform should trigger compositing.
+  auto* target_element = GetElementById("target");
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate3d(0, 0, 1px)");
+  UpdateAllLifecyclePhases();
+  // |HasTransformRelatedProperty| is used in |CompositingReasonsFor3DTransform|
+  // and must be set correctly.
+  ASSERT_TRUE(GetLayoutObjectById("target")->HasTransformRelatedProperty());
+  EXPECT_TRUE(CcLayerByDOMElementId("target"));
+
+  // Removing a 3D transform removes the compositing trigger.
+  target_element->setAttribute(html_names::kStyleAttr, "transform: none");
+  UpdateAllLifecyclePhases();
+  // |HasTransformRelatedProperty| is used in |CompositingReasonsFor3DTransform|
+  // and must be set correctly.
+  ASSERT_FALSE(GetLayoutObjectById("target")->HasTransformRelatedProperty());
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Adding a 2D transform should not trigger compositing.
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate(1px, 0)");
+  UpdateAllLifecyclePhases();
+  EXPECT_FALSE(CcLayerByDOMElementId("target"));
+
+  // Switching from a 2D to a 3D transform should trigger compositing.
+  target_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate3d(0, 0, 1px)");
+  UpdateAllLifecyclePhases();
+  EXPECT_TRUE(CcLayerByDOMElementId("target"));
+}
+
+// Inlines do not support the transform property and should not be composited
+// due to 3D transforms.
+TEST_P(CompositingTest, NotCompositing3DTransformOnSVGInline) {
+  ScopedCompositeSVGForTest enable_feature(true);
+  InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
+    <!doctype html>
+    <svg width="200" height="200">
+      <text x="50" y="50">
+        text
+        <tspan id="inline">tspan</tspan>
+      </text>
+    </svg>
+  )HTML");
+  UpdateAllLifecyclePhases();
+  EXPECT_FALSE(CcLayerByDOMElementId("inline"));
+
+  // Adding a 3D transform to an inline should not trigger compositing.
+  auto* inline_element = GetElementById("inline");
+  inline_element->setAttribute(html_names::kStyleAttr,
+                               "transform: translate3d(0, 0, 1px)");
+  UpdateAllLifecyclePhases();
+  // |HasTransformRelatedProperty| is used in |CompositingReasonsFor3DTransform|
+  // and must be set correctly.
+  ASSERT_FALSE(GetLayoutObjectById("inline")->HasTransformRelatedProperty());
+  EXPECT_FALSE(CcLayerByDOMElementId("inline"));
+}
+
 TEST_P(CompositingTest, PaintPropertiesWhenCompositingSVG) {
   ScopedCompositeSVGForTest enable_feature(true);
   InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 54171d7..34d2fd1 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h"
 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
+#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
 #include "third_party/blink/renderer/core/style/applied_text_decoration.h"
 #include "third_party/blink/renderer/core/style/border_edge.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
@@ -909,6 +910,17 @@
   return ComputedStyleBase::DiffNeedsVisualRectUpdate(*this, other);
 }
 
+bool ComputedStyle::PotentialCompositingReasonsFor3DTransformChanged(
+    const ComputedStyle& other) const {
+  // Compositing reasons for 3D transforms depend on the LayoutObject type (see:
+  // |LayoutObject::HasTransformRelatedProperty|)) This will return true for
+  // some LayoutObjects that end up not supporting transforms.
+  return CompositingReasonFinder::PotentialCompositingReasonsFor3DTransform(
+             *this) !=
+         CompositingReasonFinder::PotentialCompositingReasonsFor3DTransform(
+             other);
+}
+
 void ComputedStyle::UpdatePropertySpecificDifferences(
     const ComputedStyle& other,
     StyleDifference& diff) const {
@@ -959,7 +971,8 @@
       IsOverflowVisibleAlongBothAxes() !=
           other.IsOverflowVisibleAlongBothAxes() ||
       WillChangeProperties() != other.WillChangeProperties() ||
-      !BackdropFilterDataEquivalent(other)) {
+      !BackdropFilterDataEquivalent(other) ||
+      PotentialCompositingReasonsFor3DTransformChanged(other)) {
     diff.SetCompositingReasonsChanged();
   }
 }
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index f7bcd125..997ecdc 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2922,6 +2922,8 @@
   bool DiffNeedsVisualRectUpdate(const ComputedStyle& other) const;
   CORE_EXPORT void UpdatePropertySpecificDifferences(const ComputedStyle& other,
                                                      StyleDifference&) const;
+  bool PotentialCompositingReasonsFor3DTransformChanged(
+      const ComputedStyle& other) const;
 
   bool PropertiesEqual(const Vector<CSSPropertyID>& properties,
                        const ComputedStyle& other) const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 8c6f696..3eedf01 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2099,7 +2099,8 @@
         SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType));
     SkCanvas canvas(bitmap, SkSurfaceProps{});
     canvas.clear(SK_ColorTRANSPARENT);
-    canvas.drawImageRect(image, SkRect::MakeIWH(width, height), nullptr);
+    canvas.drawImageRect(image, SkRect::MakeIWH(width, height),
+                         SkSamplingOptions());
   }
 
   // Copy the bits into a buffer in RGBA_8888 unpremultiplied format
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 67199fc..8525728 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2134,6 +2134,11 @@
     return true;
   }
 
+  // Include all pseudo element content. Any anonymous subtree is included
+  // from above, in the condition where there is no node.
+  if (GetNode()->IsPseudoElement())
+    return true;
+
   // Use a flag to control whether or not the <html> element is included
   // in the accessibility tree. Either way it's always marked as "ignored",
   // but eventually we want to always include it in the tree to simplify
@@ -2185,7 +2190,7 @@
     return true;
 
   // Preserve SVG grouping elements.
-  if (GetNode() && IsA<SVGGElement>(GetNode()))
+  if (IsA<SVGGElement>(GetNode()))
     return true;
 
   // Preserve nodes with language attributes.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
index b653528..a77d7f9 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
@@ -1215,7 +1215,8 @@
   EXPECT_EQ(0, ax_position_from_dom.TextOffset());
 }
 
-TEST_F(AccessibilityTest, PositionInCSSContent) {
+// TODO(nektar) Fix test to work with ignored containers of pseudo content.
+TEST_F(AccessibilityTest, DISABLED_PositionInCSSContent) {
   SetBodyInnerHTML(kCSSBeforeAndAfter);
 
   const Node* quote = GetElementById("quote");
@@ -1263,7 +1264,8 @@
   EXPECT_EQ(12, position_after.GetPosition().OffsetInContainerNode());
 }
 
-TEST_F(AccessibilityTest, PositionInCSSImageContent) {
+// TODO(nektar) Fix test to work with ignored containers of pseudo content.
+TEST_F(AccessibilityTest, DISABLED_PositionInCSSImageContent) {
   constexpr char css_content_no_text[] = R"HTML(
    <style>
    .heading::before {
@@ -1293,7 +1295,8 @@
   EXPECT_EQ(3, position.GetPosition().OffsetInContainerNode());
 }
 
-TEST_F(AccessibilityTest, PositionInTableWithCSSContent) {
+// TODO(nektar) Fix test to work with ignored containers of pseudo content.
+TEST_F(AccessibilityTest, DISABLED_PositionInTableWithCSSContent) {
   SetBodyInnerHTML(kHTMLTable);
 
   // Add some CSS content, i.e. a plus symbol before and a colon after each
@@ -1338,15 +1341,19 @@
   ASSERT_EQ(ax::mojom::Role::kColumnHeader, ax_last_header_cell->RoleValue());
 
   ASSERT_EQ(3, ax_first_header_cell->ChildCountIncludingIgnored());
+  // Get grandchild text, not the child ignored generic container.
   AXObject* const ax_first_cell_css_before =
-      ax_first_header_cell->FirstChildIncludingIgnored();
+      ax_first_header_cell->FirstChildIncludingIgnored()
+          ->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_first_cell_css_before);
   ASSERT_EQ(ax::mojom::Role::kStaticText,
             ax_first_cell_css_before->RoleValue());
 
   ASSERT_EQ(3, ax_last_header_cell->ChildCountIncludingIgnored());
+  // Get grandchild text, not the child ignored generic container.
   AXObject* const ax_last_cell_css_after =
-      ax_last_header_cell->LastChildIncludingIgnored();
+      ax_last_header_cell->FirstChildIncludingIgnored()
+          ->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_last_cell_css_after);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_last_cell_css_after->RoleValue());
 
diff --git a/third_party/blink/renderer/modules/handwriting/handwriting_drawing.h b/third_party/blink/renderer/modules/handwriting/handwriting_drawing.h
index cafec63..3bd1dd9b 100644
--- a/third_party/blink/renderer/modules/handwriting/handwriting_drawing.h
+++ b/third_party/blink/renderer/modules/handwriting/handwriting_drawing.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
 
 namespace blink {
 
@@ -15,7 +16,6 @@
 class HandwritingRecognizer;
 class HandwritingStroke;
 class ScriptState;
-class Visitor;
 
 class HandwritingDrawing final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
diff --git a/third_party/blink/renderer/modules/handwriting/handwriting_recognition_service.h b/third_party/blink/renderer/modules/handwriting/handwriting_recognition_service.h
index 84999e2..84b6a00 100644
--- a/third_party/blink/renderer/modules/handwriting/handwriting_recognition_service.h
+++ b/third_party/blink/renderer/modules/handwriting/handwriting_recognition_service.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
@@ -14,7 +15,6 @@
 class HandwritingModelConstraint;
 class HandwritingFeatureQuery;
 class ScriptState;
-class Visitor;
 
 class HandwritingRecognitionService final
     : public GarbageCollected<HandwritingRecognitionService>,
diff --git a/third_party/blink/renderer/modules/handwriting/handwriting_recognizer.h b/third_party/blink/renderer/modules/handwriting/handwriting_recognizer.h
index b21195f..71268e8 100644
--- a/third_party/blink/renderer/modules/handwriting/handwriting_recognizer.h
+++ b/third_party/blink/renderer/modules/handwriting/handwriting_recognizer.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
 
 namespace blink {
 
@@ -15,7 +16,6 @@
 class HandwritingDrawing;
 class HandwritingHints;
 class ScriptState;
-class Visitor;
 
 class HandwritingRecognizer final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
diff --git a/third_party/blink/renderer/modules/handwriting/handwriting_stroke.h b/third_party/blink/renderer/modules/handwriting/handwriting_stroke.h
index cca5a65..3656cf1ab 100644
--- a/third_party/blink/renderer/modules/handwriting/handwriting_stroke.h
+++ b/third_party/blink/renderer/modules/handwriting/handwriting_stroke.h
@@ -9,12 +9,12 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
 
 namespace blink {
 
 class ExecutionContext;
 class HandwritingPoint;
-class Visitor;
 
 class HandwritingStroke final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
diff --git a/third_party/blink/renderer/modules/webaudio/BUILD.gn b/third_party/blink/renderer/modules/webaudio/BUILD.gn
index 899b871..247c9ff 100644
--- a/third_party/blink/renderer/modules/webaudio/BUILD.gn
+++ b/third_party/blink/renderer/modules/webaudio/BUILD.gn
@@ -155,5 +155,6 @@
   deps = [
     "//services/metrics/public/cpp:ukm_builders",
     "//third_party/blink/renderer/modules/mediastream",
+    "//third_party/fdlibm",
   ]
 }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
index 323f65dd..159eb733 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
@@ -33,9 +33,10 @@
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -630,7 +631,7 @@
   double final_playback_rate = sample_rate_factor * base_playback_rate;
 
   // Take the detune value into account for the final playback rate.
-  final_playback_rate *= pow(2, detune_->FinalValue() / 1200);
+  final_playback_rate *= fdlibm::pow(2, detune_->FinalValue() / 1200);
 
   // Sanity check the total rate.  It's very important that the resampler not
   // get any bad rate values.
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
index c617742..db3c5c2 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 #if defined(ARCH_CPU_X86_FAMILY)
 #include <emmintrin.h>
@@ -132,7 +133,7 @@
                                                 double time1,
                                                 float value2,
                                                 double time2) {
-  return value1 * pow(value2 / value1, (t - time1) / (time2 - time1));
+  return value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
 }
 
 // Compute the value of a set target event at time t with the given event
@@ -142,7 +143,7 @@
                                             double time1,
                                             float value2,
                                             float time_constant) {
-  return value2 + (value1 - value2) * exp(-(t - time1) / time_constant);
+  return value2 + (value1 - value2) * fdlibm::exp(-(t - time1) / time_constant);
 }
 
 // Compute the value of a set curve event at time t with the given event
@@ -1322,8 +1323,8 @@
       // currentFrame.
       value = event->Value() +
               (value - event->Value()) *
-                  exp(-(current_frame / sample_rate - event->Time()) /
-                      event->TimeConstant());
+                  fdlibm::exp(-(current_frame / sample_rate - event->Time()) /
+                              event->TimeConstant());
     } else {
       // SetTarget has already started.  Update |value| one frame because it's
       // the value from the previous frame.
@@ -1555,11 +1556,12 @@
     //   m = (v2/v1)^(1/(F*(t2-t1)))
 
     // Compute the per-sample multiplier.
-    float multiplier = powf(value2 / value1, 1 / num_sample_frames);
+    float multiplier = fdlibm::powf(value2 / value1, 1 / num_sample_frames);
     // Set the starting value of the exponential ramp.  Do not attempt
     // to optimize pow to powf.  See crbug.com/771306.
-    value = value1 * pow(value2 / static_cast<double>(value1),
-                         (current_frame / sample_rate - time1) / delta_time);
+    value = value1 *
+            fdlibm::pow(value2 / static_cast<double>(value1),
+                        (current_frame / sample_rate - time1) / delta_time);
     for (; write_index < fill_to_frame; ++write_index) {
       values[write_index] = value;
       value *= multiplier;
@@ -1618,9 +1620,9 @@
     // unsigned and could be 0.
     if (ramp_start_frame <= current_frame &&
         current_frame < ramp_start_frame + 1) {
-      value = target +
-              (value - target) *
-                  exp(-(current_frame / sample_rate - time1) / time_constant);
+      value = target + (value - target) *
+                           fdlibm::exp(-(current_frame / sample_rate - time1) /
+                                       time_constant);
     } else {
       // Otherwise, need to compute a new value bacause |value| is the
       // last computed value of SetTarget.  Time has progressed by one
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 11fedf2..3962edd 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1634,6 +1634,7 @@
     "//third_party/blink/renderer/platform/network",
     "//third_party/blink/renderer/platform/scheduler",
     "//third_party/blink/renderer/platform/wtf:buildflags",
+    "//third_party/fdlibm",
     "//third_party/pffft:pffft",
     "//ui/gfx",
   ]
diff --git a/third_party/blink/renderer/platform/audio/audio_utilities.cc b/third_party/blink/renderer/platform/audio/audio_utilities.cc
index 7fc4153..d95cba1d 100644
--- a/third_party/blink/renderer/platform/audio/audio_utilities.cc
+++ b/third_party/blink/renderer/platform/audio/audio_utilities.cc
@@ -27,19 +27,20 @@
 #include "base/notreached.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
 namespace audio_utilities {
 
 float DecibelsToLinear(float decibels) {
-  return powf(10, 0.05f * decibels);
+  return fdlibm::powf(10, 0.05f * decibels);
 }
 
 float LinearToDecibels(float linear) {
   DCHECK_GE(linear, 0);
 
-  return 20 * log10f(linear);
+  return 20 * fdlibm::log10f(linear);
 }
 
 double DiscreteTimeConstantForSampleRate(double time_constant,
@@ -64,7 +65,7 @@
   // discrete time constant is
   //
   //   1 - exp(-1/(Fs*tau)
-  return 1 - exp(-1 / (sample_rate * time_constant));
+  return 1 - fdlibm::exp(-1 / (sample_rate * time_constant));
 }
 
 size_t TimeToSampleFrame(double time,
diff --git a/third_party/blink/renderer/platform/audio/biquad.cc b/third_party/blink/renderer/platform/audio/biquad.cc
index 9dee0b5..dfc3ae2 100644
--- a/third_party/blink/renderer/platform/audio/biquad.cc
+++ b/third_party/blink/renderer/platform/audio/biquad.cc
@@ -32,10 +32,11 @@
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
+#include <stdio.h>
 #include <algorithm>
 #include <complex>
-#include <stdio.h>
 #if defined(OS_MAC)
 #include <Accelerate/Accelerate.h>
 #endif
@@ -48,7 +49,7 @@
 
 // Compute 10^x = exp(x*log(10))
 static double pow10(double x) {
-  return expf(x * 2.30258509299404568402);
+  return fdlibm::expf(x * 2.30258509299404568402);
 }
 
 Biquad::Biquad() : has_sample_accurate_values_(false) {
@@ -277,8 +278,8 @@
     resonance = pow10(resonance / 20);
 
     double theta = kPiDouble * cutoff;
-    double alpha = sin(theta) / (2 * resonance);
-    double cosw = cos(theta);
+    double alpha = fdlibm::sin(theta) / (2 * resonance);
+    double cosw = fdlibm::cos(theta);
     double beta = (1 - cosw) / 2;
 
     double b0 = beta;
@@ -309,8 +310,8 @@
 
     resonance = pow10(resonance / 20);
     double theta = kPiDouble * cutoff;
-    double alpha = sin(theta) / (2 * resonance);
-    double cosw = cos(theta);
+    double alpha = fdlibm::sin(theta) / (2 * resonance);
+    double cosw = fdlibm::cos(theta);
     double beta = (1 + cosw) / 2;
 
     double b0 = beta;
@@ -359,8 +360,8 @@
   } else if (frequency > 0) {
     double w0 = kPiDouble * frequency;
     double s = 1;  // filter slope (1 is max value)
-    double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
-    double k = cos(w0);
+    double alpha = 0.5 * fdlibm::sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
+    double k = fdlibm::cos(w0);
     double k2 = 2 * sqrt(a) * alpha;
     double a_plus_one = a + 1;
     double a_minus_one = a - 1;
@@ -391,8 +392,8 @@
   } else if (frequency > 0) {
     double w0 = kPiDouble * frequency;
     double s = 1;  // filter slope (1 is max value)
-    double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
-    double k = cos(w0);
+    double alpha = 0.5 * fdlibm::sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
+    double k = fdlibm::cos(w0);
     double k2 = 2 * sqrt(a) * alpha;
     double a_plus_one = a + 1;
     double a_minus_one = a - 1;
@@ -426,8 +427,8 @@
   if (frequency > 0 && frequency < 1) {
     if (q > 0) {
       double w0 = kPiDouble * frequency;
-      double alpha = sin(w0) / (2 * q);
-      double k = cos(w0);
+      double alpha = fdlibm::sin(w0) / (2 * q);
+      double k = fdlibm::cos(w0);
 
       double b0 = 1 + alpha * a;
       double b1 = -2 * k;
@@ -459,8 +460,8 @@
   if (frequency > 0 && frequency < 1) {
     if (q > 0) {
       double w0 = kPiDouble * frequency;
-      double alpha = sin(w0) / (2 * q);
-      double k = cos(w0);
+      double alpha = fdlibm::sin(w0) / (2 * q);
+      double k = fdlibm::cos(w0);
 
       double b0 = 1 - alpha;
       double b1 = -2 * k;
@@ -492,8 +493,8 @@
   if (frequency > 0 && frequency < 1) {
     if (q > 0) {
       double w0 = kPiDouble * frequency;
-      double alpha = sin(w0) / (2 * q);
-      double k = cos(w0);
+      double alpha = fdlibm::sin(w0) / (2 * q);
+      double k = fdlibm::cos(w0);
 
       double b0 = 1;
       double b1 = -2 * k;
@@ -525,8 +526,8 @@
   if (frequency > 0 && frequency < 1) {
     double w0 = kPiDouble * frequency;
     if (q > 0) {
-      double alpha = sin(w0) / (2 * q);
-      double k = cos(w0);
+      double alpha = fdlibm::sin(w0) / (2 * q);
+      double k = fdlibm::cos(w0);
 
       double b0 = alpha;
       double b1 = 0;
@@ -586,14 +587,15 @@
       phase_response[k] = std::nanf("");
     } else {
       double omega = -kPiDouble * frequency[k];
-      std::complex<double> z = std::complex<double>(cos(omega), sin(omega));
+      std::complex<double> z =
+          std::complex<double>(fdlibm::cos(omega), fdlibm::sin(omega));
       std::complex<double> numerator = b0 + (b1 + b2 * z) * z;
       std::complex<double> denominator =
           std::complex<double>(1, 0) + (a1 + a2 * z) * z;
       std::complex<double> response = numerator / denominator;
       mag_response[k] = static_cast<float>(abs(response));
       phase_response[k] =
-          static_cast<float>(atan2(imag(response), real(response)));
+          static_cast<float>(fdlibm::atan2(imag(response), real(response)));
     }
   }
 }
@@ -612,7 +614,8 @@
   // This helps with finding a nuemrical solution because this
   // approximately linearizes the response for large n.
 
-  return (n - 2) * log(r) + log(fabs(c1 * (n + 1) * r * r + c2)) - log_eps;
+  return (n - 2) * fdlibm::log(r) +
+         fdlibm::log(fabs(c1 * (n + 1) * r * r + c2)) - log_eps;
 }
 
 // Regula Falsi root finder, Illinois variant
@@ -817,8 +820,10 @@
     // It's possible for kMaxTailAmplitude to be greater than c1 + c2.
     // This may produce a negative tail frame.  Just clamp the tail
     // frame to 0.
-    tail_frame = clampTo(
-        1 + log(kMaxTailAmplitude / (fabs(c1) + fabs(c2))) / log(fabs(r1)), 0);
+    tail_frame =
+        clampTo(1 + fdlibm::log(kMaxTailAmplitude / (fabs(c1) + fabs(c2))) /
+                        fdlibm::log(fabs(r1)),
+                0);
 
     DCHECK(std::isfinite(tail_frame));
   } else if (discrim < 0) {
@@ -842,7 +847,8 @@
       DCHECK(std::isfinite(c1));
       DCHECK(std::isfinite(c2));
 
-      tail_frame = 1 + log(kMaxTailAmplitude / (c1 + c2)) / log(r);
+      tail_frame =
+          1 + fdlibm::log(kMaxTailAmplitude / (c1 + c2)) / fdlibm::log(r);
       if (c1 == 0 && c2 == 0) {
         // If c1 = c2 = 0, then H(z) = b0.  Hence, there's no tail
         // because this is just a wire from input to output.
@@ -883,14 +889,15 @@
         // -(1+log(r))/log(r). so we can start our search from that
         // point to max_frames.
 
-        double low = clampTo(-(1 + log(r)) / log(r), 1.0,
+        double low = clampTo(-(1 + fdlibm::log(r)) / fdlibm::log(r), 1.0,
                              static_cast<double>(max_frame - 1));
         double high = max_frame;
 
         DCHECK(std::isfinite(low));
         DCHECK(std::isfinite(high));
 
-        tail_frame = RootFinder(low, high, log(kMaxTailAmplitude), c1, c2, r);
+        tail_frame =
+            RootFinder(low, high, fdlibm::log(kMaxTailAmplitude), c1, c2, r);
       }
     }
   }
diff --git a/third_party/blink/renderer/platform/audio/distance_effect.cc b/third_party/blink/renderer/platform/audio/distance_effect.cc
index 83f3c13..3fd3ff4 100644
--- a/third_party/blink/renderer/platform/audio/distance_effect.cc
+++ b/third_party/blink/renderer/platform/audio/distance_effect.cc
@@ -33,6 +33,7 @@
 #include "base/notreached.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -88,7 +89,7 @@
   // Clamp distance according to spec
   distance = clampTo(distance, ref_distance_);
 
-  return pow(distance / ref_distance_, -clampTo(rolloff_factor_, 0.0));
+  return fdlibm::pow(distance / ref_distance_, -clampTo(rolloff_factor_, 0.0));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/audio/down_sampler.cc b/third_party/blink/renderer/platform/audio/down_sampler.cc
index d0fddec..f1089317 100644
--- a/third_party/blink/renderer/platform/audio/down_sampler.cc
+++ b/third_party/blink/renderer/platform/audio/down_sampler.cc
@@ -33,6 +33,7 @@
 #include <memory>
 
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -61,13 +62,13 @@
   for (int i = 1; i < n; i += 2) {
     // Compute the sinc() with offset.
     double s = sinc_scale_factor * kPiDouble * (i - half_size);
-    double sinc = !s ? 1.0 : sin(s) / s;
+    double sinc = !s ? 1.0 : fdlibm::sin(s) / s;
     sinc *= sinc_scale_factor;
 
     // Compute Blackman window, matching the offset of the sinc().
     double x = static_cast<double>(i) / n;
-    double window =
-        a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x);
+    double window = a0 - a1 * fdlibm::cos(kTwoPiDouble * x) +
+                    a2 * fdlibm::cos(kTwoPiDouble * 2.0 * x);
 
     // Window the sinc() function.
     // Then store only the odd terms in the kernel.
diff --git a/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc b/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
index 83b1e63a6..dacd5f1 100644
--- a/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
+++ b/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -102,7 +103,8 @@
   if (x < linear_threshold_)
     return x;
 
-  return linear_threshold_ + (1 - expf(-k * (x - linear_threshold_))) / k;
+  return linear_threshold_ +
+         (1 - fdlibm::expf(-k * (x - linear_threshold_))) / k;
 }
 
 // Full compression curve with constant ratio after knee.
@@ -230,7 +232,7 @@
   float full_range_makeup_gain = 1 / full_range_gain;
 
   // Empirical/perceptual tuning.
-  full_range_makeup_gain = powf(full_range_makeup_gain, 0.6f);
+  full_range_makeup_gain = fdlibm::powf(full_range_makeup_gain, 0.6f);
 
   float linear_post_gain =
       audio_utilities::DecibelsToLinear(db_post_gain) * full_range_makeup_gain;
@@ -297,7 +299,7 @@
     float desired_gain = detector_average_;
 
     // Pre-warp so we get desiredGain after sin() warp below.
-    float scaled_desired_gain = asinf(desired_gain) / kPiOverTwoFloat;
+    float scaled_desired_gain = fdlibm::asinf(desired_gain) / kPiOverTwoFloat;
 
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     // Deal with envelopes
@@ -373,7 +375,7 @@
       float eff_atten_diff_db = std::max(0.5f, max_attack_compression_diff_db_);
 
       float x = 0.25f / eff_atten_diff_db;
-      envelope_rate = 1 - powf(x, 1 / attack_frames);
+      envelope_rate = 1 - fdlibm::powf(x, 1 / attack_frames);
     }
 
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -451,14 +453,14 @@
         // Warp pre-compression gain to smooth out sharp exponential transition
         // points.
         float post_warp_compressor_gain =
-            sinf(kPiOverTwoFloat * compressor_gain);
+            fdlibm::sinf(kPiOverTwoFloat * compressor_gain);
 
         // Calculate total gain using the linear post-gain and effect blend.
         float total_gain =
             dry_mix + wet_mix * linear_post_gain * post_warp_compressor_gain;
 
         // Calculate metering.
-        float db_real_gain = 20 * std::log10(post_warp_compressor_gain);
+        float db_real_gain = 20 * fdlibm::log10(post_warp_compressor_gain);
         if (db_real_gain < metering_gain_)
           metering_gain_ = db_real_gain;
         else
diff --git a/third_party/blink/renderer/platform/audio/equal_power_panner.cc b/third_party/blink/renderer/platform/audio/equal_power_panner.cc
index 795cb61..44d882f 100644
--- a/third_party/blink/renderer/platform/audio/equal_power_panner.cc
+++ b/third_party/blink/renderer/platform/audio/equal_power_panner.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -95,8 +96,8 @@
     }
   }
 
-  desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position);
-  desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position);
+  desired_gain_l = fdlibm::cos(kPiOverTwoDouble * desired_pan_position);
+  desired_gain_r = fdlibm::sin(kPiOverTwoDouble * desired_pan_position);
 
   int n = frames_to_process;
 
@@ -164,8 +165,8 @@
     }
   }
 
-  desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position);
-  desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position);
+  desired_gain_l = fdlibm::cos(kPiOverTwoDouble * desired_pan_position);
+  desired_gain_r = fdlibm::sin(kPiOverTwoDouble * desired_pan_position);
 }
 
 void EqualPowerPanner::PanWithSampleAccurateValues(
diff --git a/third_party/blink/renderer/platform/audio/fft_frame.cc b/third_party/blink/renderer/platform/audio/fft_frame.cc
index b10f84b..b53cdefb 100644
--- a/third_party/blink/renderer/platform/audio/fft_frame.cc
+++ b/third_party/blink/renderer/platform/audio/fft_frame.cc
@@ -32,6 +32,7 @@
 #include <memory>
 #include "third_party/blink/renderer/platform/audio/vector_math.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 #ifndef NDEBUG
 #include <stdio.h>
@@ -125,8 +126,8 @@
     double mag2 = abs(c2);
 
     // Interpolate magnitudes in decibels
-    double mag1db = 20.0 * log10(mag1);
-    double mag2db = 20.0 * log10(mag2);
+    double mag1db = 20.0 * fdlibm::log10(mag1);
+    double mag2db = 20.0 * fdlibm::log10(mag2);
 
     double s1 = s1base;
     double s2 = s2base;
@@ -137,16 +138,16 @@
     double threshold = (i > 16) ? 5.0 : 2.0;
 
     if (magdbdiff < -threshold && mag1db < 0.0) {
-      s1 = pow(s1, 0.75);
+      s1 = fdlibm::pow(s1, 0.75);
       s2 = 1.0 - s1;
     } else if (magdbdiff > threshold && mag2db < 0.0) {
-      s2 = pow(s2, 0.75);
+      s2 = fdlibm::pow(s2, 0.75);
       s1 = 1.0 - s2;
     }
 
     // Average magnitude by decibels instead of linearly
     double magdb = s1 * mag1db + s2 * mag2db;
-    double mag = pow(10.0, 0.05 * magdb);
+    double mag = fdlibm::pow(10.0, 0.05 * magdb);
 
     // Now, deal with phase
     double phase1 = arg(c1);
diff --git a/third_party/blink/renderer/platform/audio/iir_filter.cc b/third_party/blink/renderer/platform/audio/iir_filter.cc
index 94370fea..e5a5aaf3 100644
--- a/third_party/blink/renderer/platform/audio/iir_filter.cc
+++ b/third_party/blink/renderer/platform/audio/iir_filter.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/audio/vector_math.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -137,7 +138,7 @@
       // zRecip = 1/z = exp(-j*frequency)
       double omega = -kPiDouble * frequency[k];
       std::complex<double> z_recip =
-          std::complex<double>(cos(omega), sin(omega));
+          std::complex<double>(fdlibm::cos(omega), fdlibm::sin(omega));
 
       std::complex<double> numerator = EvaluatePolynomial(
           feedforward_->Data(), z_recip, feedforward_->size() - 1);
@@ -146,7 +147,7 @@
       std::complex<double> response = numerator / denominator;
       mag_response[k] = static_cast<float>(abs(response));
       phase_response[k] =
-          static_cast<float>(atan2(imag(response), real(response)));
+          static_cast<float>(fdlibm::atan2(imag(response), real(response)));
     }
   }
 }
diff --git a/third_party/blink/renderer/platform/audio/reverb.cc b/third_party/blink/renderer/platform/audio/reverb.cc
index e7eca7d..703fdf8 100644
--- a/third_party/blink/renderer/platform/audio/reverb.cc
+++ b/third_party/blink/renderer/platform/audio/reverb.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
 #include "third_party/blink/renderer/platform/audio/vector_math.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -72,7 +73,7 @@
 
   float scale = 1 / power;
 
-  scale *= powf(
+  scale *= fdlibm::powf(
       10, kGainCalibration *
               0.05f);  // calibrate to make perceived volume same as unprocessed
 
diff --git a/third_party/blink/renderer/platform/audio/sinc_resampler.cc b/third_party/blink/renderer/platform/audio/sinc_resampler.cc
index 5f10d96..924db3f2 100644
--- a/third_party/blink/renderer/platform/audio/sinc_resampler.cc
+++ b/third_party/blink/renderer/platform/audio/sinc_resampler.cc
@@ -31,6 +31,7 @@
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 #if defined(ARCH_CPU_X86_FAMILY)
 #include <emmintrin.h>
@@ -118,13 +119,13 @@
       // Compute the sinc() with offset.
       double s =
           sinc_scale_factor * kPiDouble * (i - half_size - subsample_offset);
-      double sinc = !s ? 1.0 : std::sin(s) / s;
+      double sinc = !s ? 1.0 : fdlibm::sin(s) / s;
       sinc *= sinc_scale_factor;
 
       // Compute Blackman window, matching the offset of the sinc().
       double x = (i - subsample_offset) / n;
-      double window = a0 - a1 * std::cos(kTwoPiDouble * x) +
-                      a2 * std::cos(kTwoPiDouble * 2.0 * x);
+      double window = a0 - a1 * fdlibm::cos(kTwoPiDouble * x) +
+                      a2 * fdlibm::cos(kTwoPiDouble * 2.0 * x);
 
       // Window the sinc() function and store at the correct offset.
       kernel_storage_[i + offset_index * kernel_size_] = sinc * window;
diff --git a/third_party/blink/renderer/platform/audio/stereo_panner.cc b/third_party/blink/renderer/platform/audio/stereo_panner.cc
index 2ff13bec..4d9a9da6 100644
--- a/third_party/blink/renderer/platform/audio/stereo_panner.cc
+++ b/third_party/blink/renderer/platform/audio/stereo_panner.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -55,8 +56,8 @@
       double pan = clampTo(*pan_values++, -1.0, 1.0);
       // Pan from left to right [-1; 1] will be normalized as [0; 1].
       pan_radian = (pan * 0.5 + 0.5) * kPiOverTwoDouble;
-      gain_l = std::cos(pan_radian);
-      gain_r = std::sin(pan_radian);
+      gain_l = fdlibm::cos(pan_radian);
+      gain_r = fdlibm::sin(pan_radian);
       *destination_l++ = static_cast<float>(input_l * gain_l);
       *destination_r++ = static_cast<float>(input_l * gain_r);
     }
@@ -67,8 +68,8 @@
       double pan = clampTo(*pan_values++, -1.0, 1.0);
       // Normalize [-1; 0] to [0; 1]. Do nothing when [0; 1].
       pan_radian = (pan <= 0 ? pan + 1 : pan) * kPiOverTwoDouble;
-      gain_l = std::cos(pan_radian);
-      gain_r = std::sin(pan_radian);
+      gain_l = fdlibm::cos(pan_radian);
+      gain_r = fdlibm::sin(pan_radian);
       if (pan <= 0) {
         *destination_l++ = static_cast<float>(input_l + input_r * gain_l);
         *destination_r++ = static_cast<float>(input_r * gain_r);
@@ -114,8 +115,8 @@
     // Pan from left to right [-1; 1] will be normalized as [0; 1].
     double pan_radian = (target_pan * 0.5 + 0.5) * kPiOverTwoDouble;
 
-    double gain_l = std::cos(pan_radian);
-    double gain_r = std::sin(pan_radian);
+    double gain_l = fdlibm::cos(pan_radian);
+    double gain_r = fdlibm::sin(pan_radian);
 
     // TODO(rtoy): This can be vectorized using vector_math::Vsmul
     while (n--) {
@@ -129,8 +130,8 @@
     double pan_radian =
         (target_pan <= 0 ? target_pan + 1 : target_pan) * kPiOverTwoDouble;
 
-    double gain_l = std::cos(pan_radian);
-    double gain_r = std::sin(pan_radian);
+    double gain_l = fdlibm::cos(pan_radian);
+    double gain_r = fdlibm::sin(pan_radian);
 
     // TODO(rtoy): Consider moving the if statement outside the loop
     // since |target_pan| is constant inside the loop.
diff --git a/third_party/blink/renderer/platform/audio/up_sampler.cc b/third_party/blink/renderer/platform/audio/up_sampler.cc
index fb70a44e..df78152 100644
--- a/third_party/blink/renderer/platform/audio/up_sampler.cc
+++ b/third_party/blink/renderer/platform/audio/up_sampler.cc
@@ -33,6 +33,7 @@
 #include <memory>
 
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/fdlibm/ieee754.h"
 
 namespace blink {
 
@@ -58,12 +59,12 @@
   for (int i = 0; i < n; ++i) {
     // Compute the sinc() with offset.
     double s = kPiDouble * (i - half_size - subsample_offset);
-    double sinc = !s ? 1.0 : sin(s) / s;
+    double sinc = !s ? 1.0 : fdlibm::sin(s) / s;
 
     // Compute Blackman window, matching the offset of the sinc().
     double x = (i - subsample_offset) / n;
-    double window =
-        a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x);
+    double window = a0 - a1 * fdlibm::cos(kTwoPiDouble * x) +
+                    a2 * fdlibm::cos(kTwoPiDouble * 2.0 * x);
 
     // Window the sinc() function.
     (*kernel)[i] = sinc * window;
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index a22f12f..096239c8 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -211,7 +211,7 @@
       decoded = bitmap.installPixels(target_info, memory, adjusted_row_bytes);
       DCHECK(decoded);
 
-      canvas->drawBitmap(bitmap, 0, 0, &paint);
+      canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
     }
   }
   return decoded;
diff --git a/third_party/blink/renderer/platform/graphics/image.cc b/third_party/blink/renderer/platform/graphics/image.cc
index c8c5def..c44f061 100644
--- a/third_party/blink/renderer/platform/graphics/image.cc
+++ b/third_party/blink/renderer/platform/graphics/image.cc
@@ -145,13 +145,13 @@
   DCHECK_GE(opacity, 0);
   DCHECK_LE(opacity, 1);
   paint.setAlpha(opacity * 255);
-  paint.setFilterQuality(interpolation_quality == kInterpolationNone
-                             ? kNone_SkFilterQuality
-                             : kHigh_SkFilterQuality);
+  SkSamplingOptions sampling;
+  if (interpolation_quality != kInterpolationNone)
+    sampling = SkSamplingOptions({1.0f / 3, 1.0f / 3});
 
   SkCanvas* canvas = surface->getCanvas();
   canvas->concat(AffineTransformToSkMatrix(transform));
-  canvas->drawImage(image.GetSwSkImage(), 0, 0, &paint);
+  canvas->drawImage(image.GetSwSkImage(), 0, 0, sampling, &paint);
 
   return PaintImageBuilder::WithProperties(std::move(image))
       .set_image(surface->makeImageSnapshot(), PaintImage::GetNextContentId())
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h b/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
index e81eb2f4..615807f 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/heap.h
@@ -41,6 +41,18 @@
       std::forward<Args>(args)...);
 }
 
+// TODO(1056170): Implement.
+class PLATFORM_EXPORT HeapAllocHooks {
+  STATIC_ONLY(HeapAllocHooks);
+
+ public:
+  typedef void AllocationHook(Address, size_t, const char*);
+  typedef void FreeHook(Address);
+
+  static void SetAllocationHook(AllocationHook* hook) {}
+  static void SetFreeHook(FreeHook* hook) {}
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_H_
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 56bb01c..6d867a8 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -700,7 +700,7 @@
     },
     {
       name: "CustomStatePseudoClass",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "Database",
diff --git a/third_party/blink/renderer/platform/scheduler/TaskSchedulingInBlink.md b/third_party/blink/renderer/platform/scheduler/TaskSchedulingInBlink.md
index d01926e..d5dfc529 100644
--- a/third_party/blink/renderer/platform/scheduler/TaskSchedulingInBlink.md
+++ b/third_party/blink/renderer/platform/scheduler/TaskSchedulingInBlink.md
@@ -18,7 +18,7 @@
 
 ## Tasks
 
-The main scheduling unit in Blink is a task. A task is a base::Closure posted via
+The main scheduling unit in Blink is a task. A task is a base::OnceClosure posted via
 TaskRunner::PostTask or TaskRunner::PostDelayedTask interface. The regular method of
 creating closures (base::BindOnce/Repeating) [is banned](#binding-tasks).
 Blink should use WTF::Bind (for tasks which are posted to the same thread) and
@@ -175,4 +175,3 @@
 
 
 ## TODO(altimin): Document idle tasks
-
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 2759bf8..bcbab1a6 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -1267,6 +1267,13 @@
             'net::registry_controlled_domains::.+',
         ],
     },
+    {
+        'paths': [
+            'third_party/blink/renderer/platform/audio/',
+            'third_party/blink/renderer/modules/webaudio/',
+        ],
+        'allowed': ['fdlibm::.+'],
+    },
 ]
 
 
diff --git a/third_party/blink/web_tests/accessibility/css-alt-text.html b/third_party/blink/web_tests/accessibility/css-alt-text.html
deleted file mode 100644
index d2d9c7c..0000000
--- a/third_party/blink/web_tests/accessibility/css-alt-text.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE HTML>
-<script src="../resources/gc.js"></script>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<div id="controlparent">
-  <span id="controlchild">Some Text</span>
-</div>
-
-<style>
-#controlparent::before {
-  content:  "item1" "item2" url(bullet.png);
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("controlparent");
-  var contentTextNode = parentAXNode.childAtIndex(0);
-  var imageNode = parentAXNode.childAtIndex(1);
-  var spanAXNode = accessibilityController.accessibleElementById("controlchild");
-
-  assert_equals(contentTextNode.name, "item1item2");
-  assert_equals(imageNode.name, "");
-  assert_equals(parentAXNode.childAtIndex(2), spanAXNode);
-}, "When no alternative text is supplied text content should have a (concatenated) accessible name, images should have no name.");
-
-</script>
-<div id="parent">
-  <span id="child">Some Text</span>
-</div>
-
-<style>
-#parent::before {
-  content:  "\25BA" / "code";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("parent");
-  var textNode = parentAXNode.childAtIndex(0);
-  assert_equals(textNode.name, "code");
-  assert_equals(textNode.role, "AXRole: AXStaticText");
-  var spanAXNode = accessibilityController.accessibleElementById("child");
-  assert_equals(parentAXNode.childAtIndex(1), spanAXNode);
-}, "A pseudo element with text content and alt text should have the accessible name overridden.");
-
-</script>
-
-<div id="parentempty">
-  <span id="childempty">Some Text</span>
-</div>
-
-<style>
-#parentempty::before {
-  content:  "\25BA" / "";
-}
-</style>
-
-<script>
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("parentempty");
-  var childAXNode = parentAXNode.childAtIndex(0);
-  var spanAXNode = accessibilityController.accessibleElementById("childempty");
-
-  // As the alt string was blank, there should be no accessible node for the pseudo element.
-  // Therefore, the first child should just be the inner span node.
-  assert_equals(parentAXNode.childrenCount, 1);
-  assert_equals(childAXNode, spanAXNode);
-}, "A pseudo element with text content and an explicitly empty alternative string should not be included in the accessibility tree.");
-
-</script>
-
-<div id="imgparent"class="title">
-  <span id="imgchild">Some Text</span>
-</div>
-
-<style>
-#imgparent::before {
-  content: url(bullet.png) / "star";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("imgparent");
-  var imageNode = parentAXNode.childAtIndex(0);
-  assert_equals(imageNode.name, "star");
-  assert_equals(imageNode.role, "AXRole: AXImage");
-  var spanAXNode = accessibilityController.accessibleElementById("imgchild");
-  assert_equals(parentAXNode.childAtIndex(1), spanAXNode);
-}, "Pseudo element with image content and alt text should have the accessible name overridden.");
-
-</script>
-
-<div id="imgparentempty"class="title">
-  <span id="imgchildempty">Some Text</span>
-</div>
-
-<style>
-#imgparentempty::before {
-  content: url(bullet.png) / "";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("imgparentempty");
-  var childAXNode = parentAXNode.childAtIndex(0);
-  var spanAXNode = accessibilityController.accessibleElementById("imgchildempty");
-
-  // For images content on a pseudo element, if the alternative string was provided and
-  // explicitly empty, this behaves the same as a DOM image node with an empty/missing
-  // alt attribute.
-
-  assert_equals(parentAXNode.childrenCount, 2);
-  assert_equals(childAXNode.role, "AXRole: AXImage");
-  assert_equals(childAXNode.name, "");
-  assert_equals(parentAXNode.childAtIndex(1), spanAXNode);
-}, "A pseudo element with image content and an explicitly empty alt string should still appear in the accessibility tree with a role of AXImage, but no accessible name.");
-
-</script>
-
-<div id="divlistparent" class="title">
-  <span id="divlistchild">Some Text</span>
-</div>
-
-<style>
-#divlistparent::before {
-  content: "item1" "item2" url(bullet.png) / "a list of items";
-}
-</style>
-
-<script>
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("divlistparent");
-  var textContentListNode = parentAXNode.childAtIndex(0);
-  assert_equals(textContentListNode.name, "a list of items");
-  assert_equals(textContentListNode.role, "AXRole: AXStaticText");
-  var parentAXNode = accessibilityController.accessibleElementById("divlistparent");
-  var spanAXNode = accessibilityController.accessibleElementById("divlistchild");
-  assert_equals(parentAXNode.childAtIndex(1), spanAXNode);
-}, "A pseudo element with mixed content list, with first item being text and with alt text should have the accessible name overriden and a role of AXStaticText.");
-
-</script>
-
-<div id="emptylistparent" class="title">
-  <span id="emptylistchild">Some Text</span>
-</div>
-
-<style>
-#emptylistparent::before {
-  content: url(bullet.png) "item1" "item2" url(bullet.png) / "";
-}
-</style>
-
-<script>
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("emptylistparent");
-  var contentListNode = parentAXNode.childAtIndex(0);
-  assert_equals(contentListNode.name, "");
-  assert_equals(contentListNode.role, "AXRole: AXImage");
-  var spanAXNode = accessibilityController.accessibleElementById("emptylistchild");
-  assert_equals(parentAXNode.childAtIndex(1), spanAXNode);
-  assert_equals(parentAXNode.role, "AXRole: AXGenericContainer");
-}, "A pseudo element with mixed content list, with first item being image and with empty alt text should have a role of AXImage and empty name.");
-
-</script>
-
-
-<div id="firstletterparent">
-  <p id="firstletterchild">Some Text</p>
-</div>
-
-<style>
-#firstletterchild::first-letter {
-  color: red;
-  content: "Foo" / "Bar";
-}
-</style>
-
-<script>
-test(function(t) {
-  var parentAXNode = accessibilityController.accessibleElementById("firstletterparent");
-  var firstAXNode = parentAXNode.childAtIndex(0);
-  assert_equals(firstAXNode.role, "AXRole: AXParagraph");
-  var paragraphNode = accessibilityController.accessibleElementById("firstletterchild");
-  assert_equals(firstAXNode, paragraphNode);
-}, "Pseudo elements that don't support the content property should not impact the accessibility tree if the property and alt text is supplied.");
-
-</script>
-
-<div id="divcontent">Div text content</div>
-<style>
-#divcontent {
-  content: url(bullet.png) / "alt";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var domAXNode = accessibilityController.accessibleElementById("divcontent");
-  assert_equals(domAXNode.role, "AXRole: AXImage");
-  assert_equals(domAXNode.name, "alt");
-},"Non pseudo elements which support the content property should have the alt text applied to the image that replaces their content.");
-
-</script>
-
-<!--- The following test cases are merely here to test that the addition of alt text support has not altered the default behaviour if the content property is incorrectly supplied -->
-
-<div id="divdoubleimage">DOM Text</div>
-
-<style>
-#divdoubleimage {
-  content: url(bullet.png) url(bullet.png) / "alt";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var domAXNode = accessibilityController.accessibleElementById("divdoubleimage");
-  assert_equals(domAXNode.role, "AXRole: AXGenericContainer");
-  assert_equals(domAXNode.childrenCount, 1);
-
-  var childAXNode = domAXNode.childAtIndex(0);
-  assert_equals(childAXNode.role, "AXRole: AXStaticText");
-  assert_equals(childAXNode.name, "DOM Text");
-},"A DOM Node with more than one image and alternative text should not impact the accessibility tree.");
-
-</script>
-
-<div id="divtextcontent">DOM Text</div>
-
-<style>
-#divtextcontent {
-  content: "text content replacement" / "alt";
-}
-</style>
-
-<script>
-
-test(function(t) {
-  var domAXNode = accessibilityController.accessibleElementById("divtextcontent");
-  assert_equals(domAXNode.role, "AXRole: AXGenericContainer");
-  assert_equals(domAXNode.childrenCount, 1);
-
-  var childAXNode = domAXNode.childAtIndex(0);
-  assert_equals(childAXNode.role, "AXRole: AXStaticText");
-  assert_equals(childAXNode.name, "DOM Text");
-},"A DOM Node with text replacement content and alt text should not impact the accessibility tree.");
-
-</script>
diff --git a/third_party/blink/web_tests/accessibility/render-counter-text-expected.txt b/third_party/blink/web_tests/accessibility/render-counter-text-expected.txt
deleted file mode 100644
index 62a8446..0000000
--- a/third_party/blink/web_tests/accessibility/render-counter-text-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-This tests that the text for LayoutCounter is exposed correctly.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-PASS line1.childAtIndex(0).name is '1'
-PASS line1.childAtIndex(1).name is ':'
-PASS line1.childAtIndex(2).name is 'line1'
-PASS line2.childAtIndex(0).name is '2'
-PASS line2.childAtIndex(1).name is ':'
-PASS line2.childAtIndex(2).name is 'line2'
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/accessibility/render-counter-text.html b/third_party/blink/web_tests/accessibility/render-counter-text.html
deleted file mode 100644
index 8af37e7..0000000
--- a/third_party/blink/web_tests/accessibility/render-counter-text.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<script src="../resources/js-test.js"></script>
-
-<style>
-ol li::before { content: counter(l1) ":"; counter-increment: l1;}
-ol li { list-style-type: decimial; display: block; }
-</style>
-
-<div id="container" style="counter-reset:l1;">
-<ol style="list-style-type:decimal">
-<li id="line1">line1
-<li id="line2">line2
-<li>line3
-</ol>
-</div>
-
-<div id="description"></div>
-<div id="console"></div>
-
-<script>
-
-description("This tests that the text for LayoutCounter is exposed correctly.")
-
-if (window.testRunner && window.accessibilityController) {
-
-    var line1 = accessibilityController.accessibleElementById("line1");
-    shouldBe("line1.childAtIndex(0).name", "'1'");
-    shouldBe("line1.childAtIndex(1).name", "':'");
-    shouldBe("line1.childAtIndex(2).name", "'line1'");
-
-    var line2 = accessibilityController.accessibleElementById("line2");
-    shouldBe("line2.childAtIndex(0).name", "'2'");
-    shouldBe("line2.childAtIndex(1).name", "':'");
-    shouldBe("line2.childAtIndex(2).name", "'line2'");
-
-    document.getElementById("container").style.display = "none";
-}
-
-</script>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 71a61c7f..8d61cf2d 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -215975,7 +215975,7 @@
       []
      ],
      "from-local-system.md": [
-      "f5cfa36915d7892d827d8f5aa74649e0e2c0c062",
+      "53f6a1fb98d58f900e34895a9461332512e8c06c",
       []
      ],
      "from-web.md": [
@@ -216037,7 +216037,7 @@
       []
      ],
      "h2tests.md": [
-      "c13295e1fe668af1ed9561463b2ec18719f8deb6",
+      "9a429373f567253b174ed6f7be85290d41b20dc3",
       []
      ],
      "idlharness.md": [
@@ -216049,7 +216049,7 @@
       []
      ],
      "lint-tool.md": [
-      "ba11169e020c8c74a2a4dab04c316d3e391321a1",
+      "95f8b574158e77f195b11060b19e67328f0029d2",
       []
      ],
      "making-a-testing-plan.md": [
@@ -216066,7 +216066,7 @@
      ],
      "python-handlers": {
       "index.md": [
-       "e4d396f90a796492323d8c1c878905267a62c617",
+       "96f7edb61601b1af1795d62cefd3bd5bc09c817b",
        []
       ]
      },
@@ -216083,7 +216083,7 @@
       []
      ],
      "server-features.md": [
-      "a1ba09132c5a40591321b0532dab1c3008987c2b",
+      "fe3e84836c21e31583ed1c5d244f8dc85a3cf7eb",
       []
      ],
      "server-pipes.md": [
diff --git a/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md b/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
index f5cfa36..53f6a1fb 100644
--- a/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
+++ b/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
@@ -7,8 +7,7 @@
 Running the tests requires `python`, `pip` and `virtualenv`, as well as updating
 the system `hosts` file.
 
-Python 3 is supported and preferred, but for now it is still possible to use
-Python 2.7 if necessary.
+WPT requires Python 3.6 or higher.
 
 The required setup is different depending on your operating system.
 
@@ -45,10 +44,10 @@
 
 ### Windows Setup
 
-Download and install [Python 2.7](https://www.python.org/downloads). The
+Download and install [Python 3](https://www.python.org/downloads). The
 installer includes `pip` by default.
 
-Add `C:\Python27` and `C:\Python27\Scripts` to your `%Path%`
+Add `C:\Python39` and `C:\Python39\Scripts` to your `%Path%`
 [environment variable](http://www.computerhope.com/issues/ch000549.htm).
 
 Finally, install `virtualenv`:
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/h2tests.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/h2tests.md
index c13295e..9a42937 100644
--- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/h2tests.md
+++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/h2tests.md
@@ -1,7 +1,7 @@
 # Writing H2 Tests
 
-> <b>Important:</b> The HTTP/2.0 server requires you to have Python 2.7.10+
-and OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
+> <b>Important:</b> The HTTP/2.0 server requires you to have
+OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
 [TLS ALPN](https://tools.ietf.org/html/rfc7301) extension, which is only supported in [OpenSSL 1.0.2](https://www.openssl.org/news/openssl-1.0.2-notes.html) and up.
 
 These instructions assume you are already familiar with the testing
@@ -153,4 +153,4 @@
 Ends the stream with the given ID, or the one that request was made on if no ID given.
 
 - <b>Parameters</b>
-    - <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
\ No newline at end of file
+    - <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/lint-tool.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/lint-tool.md
index ba11169..95f8b57 100644
--- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/lint-tool.md
+++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/lint-tool.md
@@ -61,7 +61,7 @@
 
 Similarly, you can also
 use
-[shell-style wildcards](https://docs.python.org/2/library/fnmatch.html) to
+[shell-style wildcards](https://docs.python.org/library/fnmatch.html) to
 express other filename patterns or directory-name patterns.
 
 Finally, to ignore just one line in a file, use the following format:
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/python-handlers/index.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/python-handlers/index.md
index e4d396f..96f7edb 100644
--- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/python-handlers/index.md
+++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/python-handlers/index.md
@@ -81,21 +81,6 @@
 This requirement will be removed once we move to Python 3, due to
 [PEP 420](https://www.python.org/dev/peps/pep-0420/).
 
-### Python3 compatibility
-
-Even though Python3 is not fully supported at this point, some work is being
-done to add compatibility for it. This is why you can see in multiple places
-the use of the `six` python module which is meant to provide a set of simple
-utilities that work for both generation of python (see
-[docs](https://six.readthedocs.io/)). The module is vendored in
-tools/third_party/six/six.py.
-
-When an handler is added, it should be at least syntax-compatible with Python3.
-You can check that by running:
-```
-python3 -m py_compile <path/to/handler.py>
-```
-
 ## Example: Dynamic HTTP headers
 
 The following code defines a Python handler that allows the requester to
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/server-features.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/server-features.md
index a1ba091..fe3e848 100644
--- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/server-features.md
+++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/server-features.md
@@ -127,8 +127,8 @@
 The HTTP/2.0 server supports handlers that work per-frame; these, along with the
 API are documented in [Writing H2 Tests](h2tests).
 
-> <b>Important:</b> The HTTP/2.0 server requires you to have Python 2.7.10+
-and OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
+> <b>Important:</b> The HTTP/2.0 server requires you to have
+OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
 [TLS ALPN](https://tools.ietf.org/html/rfc7301) extension, which is only
 supported in
 [OpenSSL 1.0.2](https://www.openssl.org/news/openssl-1.0.2-notes.html) and up.
diff --git a/third_party/blink/web_tests/fast/canvas-api/canvas-frameless-desync-crash.html b/third_party/blink/web_tests/fast/canvas-api/canvas-frameless-desync-crash.html
new file mode 100644
index 0000000..cb687a2
--- /dev/null
+++ b/third_party/blink/web_tests/fast/canvas-api/canvas-frameless-desync-crash.html
@@ -0,0 +1,11 @@
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<canvas><canvas id="foo" width="65536" height="65536"></canvas>
+<script>
+test(function() {
+  window.addEventListener("load", () => {
+      document.implementation.createHTMLDocument().createElement("canvas").getContext("2d", {"desynchronized": true});
+  })
+}, "Trying to create a desynchronized frameless canvas should not crash.");
+</script>
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 369cab7a..4319d99 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -926,6 +926,19 @@
     getter detail
     method constructor
     method initCustomEvent
+interface CustomStateSet
+    attribute @@toStringTag
+    getter size
+    method @@iterator
+    method add
+    method clear
+    method constructor
+    method delete
+    method entries
+    method forEach
+    method has
+    method keys
+    method values
 interface DOMError
     attribute @@toStringTag
     getter message
@@ -1865,6 +1878,7 @@
     getter form
     getter labels
     getter shadowRoot
+    getter states
     getter validationMessage
     getter validity
     getter willValidate
diff --git a/third_party/unrar/patches/chromium_changes.v6.0.3.patch b/third_party/unrar/patches/chromium_changes.v6.0.3.patch
new file mode 100644
index 0000000..b9f0fe2
--- /dev/null
+++ b/third_party/unrar/patches/chromium_changes.v6.0.3.patch
@@ -0,0 +1,686 @@
+diff --git a/third_party/unrar/src/archive.cpp b/third_party/unrar/src/archive.cpp
+index 8c5a1da81d14..cac841747d86 100644
+--- a/third_party/unrar/src/archive.cpp
++++ b/third_party/unrar/src/archive.cpp
+@@ -336,3 +336,12 @@ int64 Archive::Tell()
+ }
+ #endif
+ 
++#if defined(CHROMIUM_UNRAR)
++void Archive::SetTempFileHandle(FileHandle hF) {
++  hTempFile = hF;
++}
++
++FileHandle Archive::GetTempFileHandle() {
++  return hTempFile;
++}
++#endif
+diff --git a/third_party/unrar/src/archive.hpp b/third_party/unrar/src/archive.hpp
+index d9518f1dc491..08fef7b0e6c0 100644
+--- a/third_party/unrar/src/archive.hpp
++++ b/third_party/unrar/src/archive.hpp
+@@ -57,6 +57,13 @@ class Archive:public File
+     QuickOpen QOpen;
+     bool ProhibitQOpen;
+ #endif
++
++#if defined(CHROMIUM_UNRAR)
++    // A handle for a temporary file that should be used when extracting the
++    // archive. This is used to extract the contents while in a sandbox.
++    FileHandle hTempFile;
++#endif
++
+   public:
+     Archive(RAROptions *InitCmd=NULL);
+     ~Archive();
+@@ -96,6 +103,10 @@ class Archive:public File
+     void QOpenUnload() {QOpen.Unload();}
+     void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
+ #endif
++#if defined(CHROMIUM_UNRAR)
++    void SetTempFileHandle(FileHandle hF);
++    FileHandle GetTempFileHandle();
++#endif
+ 
+     BaseBlock ShortBlock;
+     MarkHeader MarkHead;
+diff --git a/third_party/unrar/src/arcread.cpp b/third_party/unrar/src/arcread.cpp
+index d1df6c04108c..468d387a2472 100644
+--- a/third_party/unrar/src/arcread.cpp
++++ b/third_party/unrar/src/arcread.cpp
+@@ -142,7 +142,8 @@ size_t Archive::ReadHeader15()
+ 
+   if (Decrypt)
+   {
+-#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
++#if defined(RAR_NOCRYPT) || \
++    defined(CHROMIUM_UNRAR)  // For rarext.dll and unrar_nocrypt.dll.
+     return 0;
+ #else
+     RequestArcPassword();
+@@ -554,7 +555,7 @@ size_t Archive::ReadHeader50()
+ 
+   if (Decrypt)
+   {
+-#if defined(RAR_NOCRYPT)
++#if defined(RAR_NOCRYPT) || defined(CHROMIUM_UNRAR)
+     return 0;
+ #else
+ 
+diff --git a/third_party/unrar/src/crc.cpp b/third_party/unrar/src/crc.cpp
+index cf23bbf4f2af..4c86c09e3b4f 100644
+--- a/third_party/unrar/src/crc.cpp
++++ b/third_party/unrar/src/crc.cpp
+@@ -15,6 +15,7 @@
+ #include "rar.hpp"
+ 
+ static uint crc_tables[8][256]; // Tables for Slicing-by-8.
++static bool is_initialized = false;
+ 
+ 
+ // Build the classic CRC32 lookup table.
+@@ -49,10 +50,13 @@ static void InitTables()
+ }
+ 
+ 
+-struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
+-
+ uint CRC32(uint StartCRC,const void *Addr,size_t Size)
+ {
++  if (!is_initialized) {
++    is_initialized = true;
++    InitTables();
++  }
++
+   byte *Data=(byte *)Addr;
+ 
+   // Align Data to 8 for better performance.
+diff --git a/third_party/unrar/src/errhnd.cpp b/third_party/unrar/src/errhnd.cpp
+index 18e91973e61b..dce0fbc09351 100644
+--- a/third_party/unrar/src/errhnd.cpp
++++ b/third_party/unrar/src/errhnd.cpp
+@@ -1,9 +1,11 @@
+-#include "rar.hpp"
++// NOTE(vakh): The process.h file needs to be included first because "rar.hpp"
++// defines certain macros that cause symbol redefinition errors
++#if defined(UNRAR_NO_EXCEPTIONS)
++#include "base/check.h"
++#include "base/process/process.h"
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
+ 
+-ErrorHandler::ErrorHandler()
+-{
+-  Clean();
+-}
++#include "rar.hpp"
+ 
+ 
+ void ErrorHandler::Clean()
+@@ -334,7 +336,11 @@ void ErrorHandler::Throw(RAR_EXIT Code)
+     mprintf(L"\n%s\n",St(MProgAborted));
+ #endif
+   SetErrorCode(Code);
++#if defined(UNRAR_NO_EXCEPTIONS)
++  CHECK(false) << "Failed with RAR_EXIT code: " << Code;
++#else
+   throw Code;
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
+ }
+ 
+ 
+diff --git a/third_party/unrar/src/errhnd.hpp b/third_party/unrar/src/errhnd.hpp
+index 06f4f616fd96..3c5c54c490f7 100644
+--- a/third_party/unrar/src/errhnd.hpp
++++ b/third_party/unrar/src/errhnd.hpp
+@@ -23,14 +23,13 @@ enum RAR_EXIT // RAR exit code.
+ class ErrorHandler
+ {
+   private:
+-    RAR_EXIT ExitCode;
+-    uint ErrCount;
+-    bool EnableBreak;
+-    bool Silent;
+-    bool DisableShutdown; // Shutdown is not suitable after last error.
+-    bool ReadErrIgnoreAll;
++    RAR_EXIT ExitCode = RARX_SUCCESS;
++    uint ErrCount = 0;
++    bool EnableBreak = true;
++    bool Silent = false;
++    bool DisableShutdown = false; // Shutdown is not suitable after last error.
++    bool ReadErrIgnoreAll = false;
+   public:
+-    ErrorHandler();
+     void Clean();
+     void MemoryError();
+     void OpenError(const wchar *FileName);
+@@ -67,8 +66,8 @@ class ErrorHandler
+     void SetDisableShutdown() {DisableShutdown=true;}
+     bool IsShutdownEnabled() {return !DisableShutdown;}
+ 
+-    bool UserBreak; // Ctrl+Break is pressed.
+-    bool MainExit; // main() is completed.
++    bool UserBreak = false; // Ctrl+Break is pressed.
++    bool MainExit = false; // main() is completed.
+ };
+ 
+ 
+diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp
+index abcd3c3385c5..2c264b107040 100644
+--- a/third_party/unrar/src/extract.cpp
++++ b/third_party/unrar/src/extract.cpp
+@@ -524,6 +524,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
+ #endif
+ 
+     File CurFile;
++#if defined(CHROMIUM_UNRAR)
++    // Since extraction is done in a sandbox, this must extract to the temp file
++    // handle instead of the default.
++    CurFile.SetFileHandle(Arc.GetTempFileHandle());
++#endif
+ 
+     bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE;
+     if (LinkEntry && Arc.FileHead.RedirType!=FSREDIR_FILECOPY)
+@@ -1334,4 +1339,4 @@ void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wch
+   wcsncpyz(DestName,ResultName,DestSize);
+ }
+ 
+-#endif
+\ No newline at end of file
++#endif
+diff --git a/third_party/unrar/src/extract.hpp b/third_party/unrar/src/extract.hpp
+index 159759b563f5..9a659591d4f3 100644
+--- a/third_party/unrar/src/extract.hpp
++++ b/third_party/unrar/src/extract.hpp
+@@ -37,8 +37,8 @@ class CmdExtract
+     unsigned long MatchedArgs;
+     bool FirstFile;
+     bool AllMatchesExact;
+-    bool ReconstructDone;
+-    bool UseExactVolName;
++    bool ReconstructDone=false;
++    bool UseExactVolName=false;
+ 
+     // If any non-zero solid file was successfully unpacked before current.
+     // If true and if current encrypted file is broken, obviously
+@@ -62,6 +62,10 @@ class CmdExtract
+     void ExtractArchiveInit(Archive &Arc);
+     bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat);
+     static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
++
++#if defined(CHROMIUM_UNRAR)
++    int64 GetCurrentFileSize() { return DataIO.CurUnpWrite; }
++#endif
+ };
+ 
+ #endif
+diff --git a/third_party/unrar/src/file.cpp b/third_party/unrar/src/file.cpp
+index 5a8099ec5bd1..cd6be338e486 100644
+--- a/third_party/unrar/src/file.cpp
++++ b/third_party/unrar/src/file.cpp
+@@ -19,6 +19,10 @@ File::File()
+ #endif
+   ReadErrorMode=FREM_ASK;
+   TruncatedAfterReadError=false;
++
++#ifdef CHROMIUM_UNRAR
++  hOpenFile=FILE_BAD_HANDLE;
++#endif
+ }
+ 
+ 
+@@ -52,6 +56,11 @@ bool File::Open(const wchar *Name,uint Mode)
+   bool UpdateMode=(Mode & FMF_UPDATE)!=0;
+   bool WriteMode=(Mode & FMF_WRITE)!=0;
+ #ifdef _WIN_ALL
++#if defined(CHROMIUM_UNRAR)
++  // Do not open a file handle since the sandbox doesn't allow it. Use the
++  // handle provided by the caller.
++  hNewFile = hOpenFile;
++#else
+   uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
+   if (UpdateMode)
+     Access|=GENERIC_WRITE;
+@@ -97,7 +106,14 @@ bool File::Open(const wchar *Name,uint Mode)
+     FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification.
+     SetFileTime(hNewFile,NULL,&ft,NULL);
+   }
++#endif  // defined(CHROMIUM_UNRAR)
++
++#else
+ 
++#if defined(CHROMIUM_UNRAR)
++  // Do not open a file handle since the sandbox doesn't allow it. Use the
++  // handle provided by the caller.
++  int handle = hOpenFile;
+ #else
+   int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
+ #ifdef O_BINARY
+@@ -115,6 +131,8 @@ bool File::Open(const wchar *Name,uint Mode)
+   WideToChar(Name,NameA,ASIZE(NameA));
+ 
+   int handle=open(NameA,flags);
++#endif  // defined(CHROMIUM_UNRAR)
++
+ #ifdef LOCK_EX
+ 
+ #ifdef _OSF_SOURCE
+@@ -174,6 +192,11 @@ bool File::WOpen(const wchar *Name)
+ 
+ bool File::Create(const wchar *Name,uint Mode)
+ {
++#if defined(CHROMIUM_UNRAR)
++  // Since the Chromium sandbox does not allow the creation of files, use the
++  // provided file.
++  hFile = hOpenFile;
++#else
+   // OpenIndiana based NAS and CIFS shares fail to set the file time if file
+   // was created in read+write mode and some data was written and not flushed
+   // before SetFileTime call. So we should use the write only mode if we plan
+@@ -211,6 +234,7 @@ bool File::Create(const wchar *Name,uint Mode)
+   hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY);
+ #endif
+ #endif
++#endif  // defined(CHROMIUM_UNRAR)
+   NewFile=true;
+   HandleType=FILE_HANDLENORMAL;
+   SkipClose=false;
+@@ -245,6 +269,8 @@ bool File::Close()
+   {
+     if (!SkipClose)
+     {
++#if !defined(CHROMIUM_UNRAR)
++// unrar should not close the file handle since it wasn't opened by unrar.
+ #ifdef _WIN_ALL
+       // We use the standard system handle for stdout in Windows
+       // and it must not be closed here.
+@@ -257,6 +283,7 @@ bool File::Close()
+       Success=fclose(hFile)!=EOF;
+ #endif
+ #endif
++#endif  // defined(CHROMIUM_UNRAR)
+     }
+     hFile=FILE_BAD_HANDLE;
+   }
+@@ -759,3 +786,9 @@ int64 File::Copy(File &Dest,int64 Length)
+   return CopySize;
+ }
+ #endif
++
++#if defined(CHROMIUM_UNRAR)
++void File::SetFileHandle(FileHandle hF) {
++  hOpenFile = hF;
++}
++#endif  // defined(CHROMIUM_UNRAR)
+diff --git a/third_party/unrar/src/file.hpp b/third_party/unrar/src/file.hpp
+index 1c436d4ef7bc..baf366dfa4a3 100644
+--- a/third_party/unrar/src/file.hpp
++++ b/third_party/unrar/src/file.hpp
+@@ -76,6 +76,10 @@ class File
+     wchar FileName[NM];
+ 
+     FILE_ERRORTYPE ErrorType;
++
++#if defined(CHROMIUM_UNRAR)
++    FileHandle hOpenFile;
++#endif  // defined(CHROMIUM_UNRAR)
+   public:
+     File();
+     virtual ~File();
+@@ -124,6 +128,14 @@ class File
+ #endif
+     void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
+     bool IsTruncatedAfterReadError() {return TruncatedAfterReadError;}
++
++#if defined(CHROMIUM_UNRAR)
++    // Since unrar runs in a sandbox, it doesn't have the permission to open
++    // files on the filesystem. Instead, the caller opens the file and passes
++    // the file handle to unrar. This handle is then used to read the file.
++    void SetFileHandle(FileHandle file);
++#endif  // defined(CHROMIUM_UNRAR)
++
+ #ifdef _UNIX
+     int GetFD()
+     {
+diff --git a/third_party/unrar/src/isnt.cpp b/third_party/unrar/src/isnt.cpp
+index 6fadec049fe4..d30adf550925 100644
+--- a/third_party/unrar/src/isnt.cpp
++++ b/third_party/unrar/src/isnt.cpp
+@@ -1,24 +1,18 @@
+ #include "rar.hpp"
+ 
+ #ifdef _WIN_ALL
++#include "versionhelpers.h"
++
+ DWORD WinNT()
+ {
+-  static int dwPlatformId=-1;
+-  static DWORD dwMajorVersion,dwMinorVersion;
+-  if (dwPlatformId==-1)
+-  {
+-    OSVERSIONINFO WinVer;
+-    WinVer.dwOSVersionInfoSize=sizeof(WinVer);
+-    GetVersionEx(&WinVer);
+-    dwPlatformId=WinVer.dwPlatformId;
+-    dwMajorVersion=WinVer.dwMajorVersion;
+-    dwMinorVersion=WinVer.dwMinorVersion;
+-  }
+-  DWORD Result=0;
+-  if (dwPlatformId==VER_PLATFORM_WIN32_NT)
+-    Result=dwMajorVersion*0x100+dwMinorVersion;
+-
+-
+-  return Result;
++  if (!IsWindowsXPOrGreater())
++    return WNT_NONE;
++  if (!IsWindowsVistaOrGreater())
++    return WNT_WXP;
++  if (!IsWindows7OrGreater()) return WNT_VISTA;
++  if (!IsWindows8OrGreater()) return WNT_W7;
++  if (!IsWindows8Point1OrGreater()) return WNT_W8;
++  if (!IsWindows10OrGreater()) return WNT_W81;
++  return WNT_W10;
+ }
+ #endif
+diff --git a/third_party/unrar/src/isnt.hpp b/third_party/unrar/src/isnt.hpp
+index 85790da46290..a02174447e29 100644
+--- a/third_party/unrar/src/isnt.hpp
++++ b/third_party/unrar/src/isnt.hpp
+@@ -1,6 +1,8 @@
+ #ifndef _RAR_ISNT_
+ #define _RAR_ISNT_
+ 
++#include "windows.h"
++
+ enum WINNT_VERSION {
+   WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500,
+   WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601,
+@@ -9,5 +11,4 @@ enum WINNT_VERSION {
+ 
+ DWORD WinNT();
+ 
+-
+ #endif
+diff --git a/third_party/unrar/src/model.cpp b/third_party/unrar/src/model.cpp
+index 83391c5a4510..1ca9f03e9bcc 100644
+--- a/third_party/unrar/src/model.cpp
++++ b/third_party/unrar/src/model.cpp
+@@ -43,13 +43,27 @@ void ModelPPM::RestartModelRare()
+   InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
+   MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
+   if (MinContext == NULL)
++  {
++#if defined(UNRAR_NO_EXCEPTIONS)
++    base::TerminateBecauseOutOfMemory(0);
++#else
+     throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++  }
++
+   MinContext->Suffix=NULL;
+   OrderFall=MaxOrder;
+   MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
+   FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
+   if (FoundState == NULL)
++  {
++#if defined(UNRAR_NO_EXCEPTIONS)
++    base::TerminateBecauseOutOfMemory(0);
++#else
+     throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++  }
++
+   for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) 
+   {
+     MinContext->U.Stats[i].Symbol=i;      
+diff --git a/third_party/unrar/src/os.hpp b/third_party/unrar/src/os.hpp
+index b69f34878b3d..51d547b0f68b 100644
+--- a/third_party/unrar/src/os.hpp
++++ b/third_party/unrar/src/os.hpp
+@@ -32,6 +32,7 @@
+ #define STRICT 1
+ #endif
+ 
++#if !defined(CHROMIUM_UNRAR)
+ // 'ifndef' check here is needed for unrar.dll header to avoid macro
+ // re-definition warnings in third party projects.
+ #ifndef UNICODE
+@@ -42,12 +43,15 @@
+ #undef _WIN32_WINNT
+ #define WINVER 0x0501
+ #define _WIN32_WINNT 0x0501
++#endif  // CHROMIUM_UNRAR
+ 
+-#if !defined(ZIPSFX)
++#if !defined(ZIPSFX) && !defined(CHROMIUM_UNRAR)
+ #define RAR_SMP
+ #endif
+ 
++#if !defined(CHROMIUM_UNRAR)
+ #define WIN32_LEAN_AND_MEAN
++#endif  // CHROMIUM_UNRAR
+ 
+ #include <windows.h>
+ #include <prsht.h>
+@@ -79,8 +83,11 @@
+   #include <direct.h>
+   #include <intrin.h>
+ 
++#if !defined(CHROMIUM_UNRAR)
+   #define USE_SSE
+   #define SSE_ALIGNMENT 16
++#endif  // CHROMIUM_UNRAR
++
+ #else
+   #include <dirent.h>
+ #endif // _MSC_VER
+diff --git a/third_party/unrar/src/secpassword.cpp b/third_party/unrar/src/secpassword.cpp
+index 4865b3fd02e2..c292b0e00285 100644
+--- a/third_party/unrar/src/secpassword.cpp
++++ b/third_party/unrar/src/secpassword.cpp
+@@ -25,6 +25,7 @@ class CryptLoader
+     }
+     ~CryptLoader()
+     {
++      // We need to call FreeLibrary when RAR is exiting.
+       if (hCrypt!=NULL)
+         FreeLibrary(hCrypt);
+       hCrypt=NULL;
+@@ -46,12 +47,14 @@ class CryptLoader
+       }
+     }
+ 
++    static CryptLoader& GetInstance() {
++      static CryptLoader cryptLoader;
++      return cryptLoader;
++    }
++
+     CRYPTPROTECTMEMORY pCryptProtectMemory;
+     CRYPTUNPROTECTMEMORY pCryptUnprotectMemory;
+ };
+-
+-// We need to call FreeLibrary when RAR is exiting.
+-CryptLoader GlobalCryptLoader;
+ #endif
+ 
+ SecPassword::SecPassword()
+@@ -169,16 +172,15 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess)
+   // increases data size not allowing in place conversion.
+ #if defined(_WIN_ALL)
+   // Try to utilize the secure Crypt[Un]ProtectMemory if possible.
+-  if (GlobalCryptLoader.pCryptProtectMemory==NULL)
+-    GlobalCryptLoader.Load();
++  if (CryptLoader::GetInstance().pCryptProtectMemory == NULL)
++    CryptLoader::GetInstance().Load();
+   size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE;
+   DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS;
+   if (Encode)
+   {
+-    if (GlobalCryptLoader.pCryptProtectMemory!=NULL)
+-    {
+-      if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags))
+-      {
++    if (CryptLoader::GetInstance().pCryptProtectMemory != NULL) {
++      if (!CryptLoader::GetInstance().pCryptProtectMemory(Data, DWORD(Aligned),
++                                                          Flags)) {
+         ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed");
+         ErrHandler.SysErrMsg();
+         ErrHandler.Exit(RARX_FATAL);
+@@ -188,10 +190,9 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess)
+   }
+   else
+   {
+-    if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL)
+-    {
+-      if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags))
+-      {
++    if (CryptLoader::GetInstance().pCryptUnprotectMemory != NULL) {
++      if (!CryptLoader::GetInstance().pCryptUnprotectMemory(
++              Data, DWORD(Aligned), Flags)) {
+         ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed");
+         ErrHandler.SysErrMsg();
+         ErrHandler.Exit(RARX_FATAL);
+diff --git a/third_party/unrar/src/unicode.cpp b/third_party/unrar/src/unicode.cpp
+index 641f6c892a3f..48d7bb2fc44e 100644
+--- a/third_party/unrar/src/unicode.cpp
++++ b/third_party/unrar/src/unicode.cpp
+@@ -576,7 +576,6 @@ int64 atoilw(const wchar *s)
+ 
+ 
+ #ifdef DBCS_SUPPORTED
+-SupportDBCS gdbcs;
+ 
+ SupportDBCS::SupportDBCS()
+ {
+@@ -593,6 +592,11 @@ void SupportDBCS::Init()
+     IsLeadByte[I]=IsDBCSLeadByte(I)!=0;
+ }
+ 
++// static
++SupportDBCS& SupportDBCS::GetInstance() {
++  static SupportDBCS supportDBCS;
++  return supportDBCS;
++}
+ 
+ char* SupportDBCS::charnext(const char *s)
+ {
+diff --git a/third_party/unrar/src/unicode.hpp b/third_party/unrar/src/unicode.hpp
+index 031ac09ab94b..c66cc95a34cc 100644
+--- a/third_party/unrar/src/unicode.hpp
++++ b/third_party/unrar/src/unicode.hpp
+@@ -33,6 +33,7 @@ class SupportDBCS
+   public:
+     SupportDBCS();
+     void Init();
++    static SupportDBCS& GetInstance();
+ 
+     char* charnext(const char *s);
+     size_t strlend(const char *s);
+@@ -44,15 +45,13 @@ class SupportDBCS
+     bool DBCSMode;
+ };
+ 
+-extern SupportDBCS gdbcs;
+-
+-inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);}
+-inline size_t strlend(const char *s) {return (uint)(gdbcs.DBCSMode ? gdbcs.strlend(s):strlen(s));}
+-inline char* strchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strchrd(s,c):strchr(s,c));}
+-inline char* strrchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strrchrd(s,c):strrchr(s,c));}
+-inline void copychrd(char *dest,const char *src) {if (gdbcs.DBCSMode) gdbcs.copychrd(dest,src); else *dest=*src;}
+-inline bool IsDBCSMode() {return(gdbcs.DBCSMode);}
+-inline void InitDBCS() {gdbcs.Init();}
++inline char* charnext(const char *s) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().charnext(s):s+1);}
++inline size_t strlend(const char *s) {return (uint)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strlend(s):strlen(s));}
++inline char* strchrd(const char *s, int c) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strchrd(s,c):strchr(s,c));}
++inline char* strrchrd(const char *s, int c) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strrchrd(s,c):strrchr(s,c));}
++inline void copychrd(char *dest,const char *src) {if (SupportDBCS::GetInstance().DBCSMode) SupportDBCS::GetInstance().copychrd(dest,src); else *dest=*src;}
++inline bool IsDBCSMode() {return(SupportDBCS::GetInstance().DBCSMode);}
++inline void InitDBCS() {SupportDBCS::GetInstance().Init();}
+ 
+ #else
+ #define charnext(s) ((s)+1)
+diff --git a/third_party/unrar/src/unpack.cpp b/third_party/unrar/src/unpack.cpp
+index 037c35546a89..7f579ff06ab3 100644
+--- a/third_party/unrar/src/unpack.cpp
++++ b/third_party/unrar/src/unpack.cpp
+@@ -1,3 +1,9 @@
++// NOTE(vakh): The process.h file needs to be included first because "rar.hpp"
++// defines certain macros that cause symbol redefinition errors
++#if defined(UNRAR_NO_EXCEPTIONS)
++#include "base/process/memory.h"
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++
+ #include "rar.hpp"
+ 
+ #include "coder.cpp"
+@@ -100,16 +106,27 @@ void Unpack::Init(size_t WinSize,bool Solid)
+ 
+   // We do not handle growth for existing fragmented window.
+   if (Grow && Fragmented)
++  {
++#if defined(UNRAR_NO_EXCEPTIONS)
++    base::TerminateBecauseOutOfMemory(0);
++#else
+     throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++  }
+ 
+   byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize);
+ 
+   if (NewWindow==NULL)
++  {
+     if (Grow || WinSize<0x1000000)
+     {
+       // We do not support growth for new fragmented window.
+       // Also exclude RAR4 and small dictionaries.
++#if defined(UNRAR_NO_EXCEPTIONS)
++      base::TerminateBecauseOutOfMemory(WinSize);
++#else
+       throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
+     }
+     else
+     {
+@@ -121,6 +138,7 @@ void Unpack::Init(size_t WinSize,bool Solid)
+       FragWindow.Init(WinSize);
+       Fragmented=true;
+     }
++  }
+ 
+   if (!Fragmented)
+   {
+diff --git a/third_party/unrar/src/unpack50frag.cpp b/third_party/unrar/src/unpack50frag.cpp
+index 3c008ff24539..16d5b1c3d5ef 100644
+--- a/third_party/unrar/src/unpack50frag.cpp
++++ b/third_party/unrar/src/unpack50frag.cpp
+@@ -46,8 +46,14 @@ void FragmentedWindow::Init(size_t WinSize)
+         break;
+       Size-=Size/32;
+     }
+-    if (NewMem==NULL)
++    if (NewMem == NULL)
++    {
++#if defined(UNRAR_NO_EXCEPTIONS)
++      base::TerminateBecauseOutOfMemory(Size);
++#else
+       throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++    }
+ 
+     // Clean the window to generate the same output when unpacking corrupt
+     // RAR files, which may access to unused areas of sliding dictionary.
+@@ -58,8 +64,14 @@ void FragmentedWindow::Init(size_t WinSize)
+     MemSize[BlockNum]=TotalSize;
+     BlockNum++;
+   }
+-  if (TotalSize<WinSize) // Not found enough free blocks.
++  if (TotalSize < WinSize)  // Not found enough free blocks.
++  {
++#if defined(UNRAR_NO_EXCEPTIONS)
++    base::TerminateBecauseOutOfMemory(WinSize);
++#else
+     throw std::bad_alloc();
++#endif  // defined(UNRAR_NO_EXCEPTIONS)
++  }
+ }
+ 
+ 
diff --git a/third_party/unrar/src/acknow.txt b/third_party/unrar/src/acknow.txt
index b982ecee..b5d2695 100644
--- a/third_party/unrar/src/acknow.txt
+++ b/third_party/unrar/src/acknow.txt
@@ -51,7 +51,7 @@
 * RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
   Original Intel Slicing-by-8 code is available here:
 
-    http://sourceforge.net/projects/slicing-by-8/
+    https://sourceforge.net/projects/slicing-by-8/
 
   Original Intel Slicing-by-8 code is licensed under BSD License
   available at http://www.opensource.org/licenses/bsd-license.html
diff --git a/third_party/unrar/src/arccmt.cpp b/third_party/unrar/src/arccmt.cpp
index 92a3896..8b7e498 100644
--- a/third_party/unrar/src/arccmt.cpp
+++ b/third_party/unrar/src/arccmt.cpp
@@ -4,8 +4,15 @@
 {
   if (!MainComment)
     return false;
-  SaveFilePos SavePos(*this);
+  int64 SavePos=Tell();
+  bool Success=DoGetComment(CmtData);
+  Seek(SavePos,SEEK_SET);
+  return Success;
+}
 
+
+bool Archive::DoGetComment(Array<wchar> *CmtData)
+{
 #ifndef SFX_MODULE
   uint CmtLength;
   if (Format==RARFMT14)
@@ -136,7 +143,7 @@
 bool Archive::ReadCommentData(Array<wchar> *CmtData)
 {
   Array<byte> CmtRaw;
-  if (!ReadSubData(&CmtRaw,NULL))
+  if (!ReadSubData(&CmtRaw,NULL,false))
     return false;
   size_t CmtSize=CmtRaw.Size();
   CmtRaw.Push(0);
diff --git a/third_party/unrar/src/archive.cpp b/third_party/unrar/src/archive.cpp
index e4e35cb..cac8417 100644
--- a/third_party/unrar/src/archive.cpp
+++ b/third_party/unrar/src/archive.cpp
@@ -208,8 +208,8 @@
       break;
   }
 
-  // This check allows to make RS based recovery even if password is incorrect.
-  // But we should not do it for EnableBroken or we'll get 'not RAR archive'
+  
+  // We should not do it for EnableBroken or we'll get 'not RAR archive'
   // messages when extracting encrypted archives with wrong password.
   if (FailedHeaderDecryption && !EnableBroken)
     return false;
@@ -233,7 +233,7 @@
   // immediately after IsArchive call.
   if (HeadersLeft && (!SilentOpen || !Encrypted))
   {
-    SaveFilePos SavePos(*this);
+    int64 SavePos=Tell();
     int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
     HEADER_TYPE SaveCurHeaderType=CurHeaderType;
 
@@ -262,6 +262,7 @@
     CurBlockPos=SaveCurBlockPos;
     NextBlockPos=SaveNextBlockPos;
     CurHeaderType=SaveCurHeaderType;
+    Seek(SavePos,SEEK_SET);
   }
   if (!Volume || FirstVolume)
     wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
diff --git a/third_party/unrar/src/archive.hpp b/third_party/unrar/src/archive.hpp
index bb05dded..08fef7b0 100644
--- a/third_party/unrar/src/archive.hpp
+++ b/third_party/unrar/src/archive.hpp
@@ -29,7 +29,6 @@
     void UpdateLatestTime(FileHeader *CurBlock);
     void ConvertNameCase(wchar *Name);
     void ConvertFileHeader(FileHeader *hd);
-    void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
     size_t ReadHeader14();
     size_t ReadHeader15();
     size_t ReadHeader50();
@@ -38,6 +37,7 @@
     void UnexpEndArcMsg();
     void BrokenHeaderMsg();
     void UnkEncVerMsg(const wchar *Name,const wchar *Info);
+    bool DoGetComment(Array<wchar> *CmtData);
     bool ReadCommentData(Array<wchar> *CmtData);
 
 #if !defined(RAR_NOCRYPT)
@@ -72,8 +72,6 @@
     size_t SearchBlock(HEADER_TYPE HeaderType);
     size_t SearchSubBlock(const wchar *Type);
     size_t SearchRR();
-    void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false);
-    void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);}
     size_t ReadHeader();
     void CheckArc(bool EnableBroken);
     void CheckOpen(const wchar *Name);
@@ -90,7 +88,7 @@
     int64 GetStartPos();
     void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
          const wchar *Name,uint Flags);
-    bool ReadSubData(Array<byte> *UnpData,File *DestFile);
+    bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
     HEADER_TYPE GetHeaderType() {return CurHeaderType;}
     RAROptions* GetRAROptions() {return Cmd;}
     void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
diff --git a/third_party/unrar/src/arcread.cpp b/third_party/unrar/src/arcread.cpp
index f1ed7ba..468d387a 100644
--- a/third_party/unrar/src/arcread.cpp
+++ b/third_party/unrar/src/arcread.cpp
@@ -269,14 +269,14 @@
         uint FileTime=Raw.Get4();
         hd->UnpVer=Raw.Get1();
 
-        // RAR15 did not use the special dictionary size to mark dirs.
-        if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
-          hd->Dir=true;
-
         hd->Method=Raw.Get1()-0x30;
         size_t NameSize=Raw.Get2();
         hd->FileAttr=Raw.Get4();
 
+        // RAR15 did not use the special dictionary size to mark dirs.
+        if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
+          hd->Dir=true;
+
         hd->CryptMethod=CRYPT_NONE;
         if (hd->Encrypted)
           switch(hd->UnpVer)
@@ -403,8 +403,8 @@
             if (rmode & 4)
               rlt.Second++;
             rlt.Reminder=0;
-            int count=rmode&3;
-            for (int J=0;J<count;J++)
+            uint count=rmode&3;
+            for (uint J=0;J<count;J++)
             {
               byte CurByte=Raw.Get1();
               rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
@@ -522,7 +522,6 @@
     {
       // Last 7 bytes of recovered volume can contain zeroes, because
       // REV files store its own information (volume number, etc.) here.
-      SaveFilePos SavePos(*this);
       int64 Length=Tell();
       Seek(Length-7,SEEK_SET);
       Recovered=true;
@@ -585,7 +584,7 @@
         {
           // This message is used by Android GUI to reset cached passwords.
           // Update appropriate code if changed.
-          uiMsg(UIERROR_BADPSW,FileName);
+          uiMsg(UIERROR_BADPSW,FileName,FileName);
           FailedHeaderDecryption=true;
           ErrHandler.SetErrorCode(RARX_BADPWD);
           return 0;
@@ -594,7 +593,7 @@
         {
           // This message is used by Android GUI and Windows GUI and SFX to
           // reset cached passwords. Update appropriate code if changed.
-          uiMsg(UIWAIT_BADPSW,FileName);
+          uiMsg(UIWAIT_BADPSW,FileName,FileName);
           Cmd->Password.Clean();
         }
 
@@ -721,6 +720,7 @@
           UnkEncVerMsg(FileName,Info);
           return 0;
         }
+
         Raw.GetB(CryptHead.Salt,SIZE_SALT50);
         if (CryptHead.UsePswCheck)
         {
@@ -786,7 +786,7 @@
     case HEAD_SERVICE:
       {
         FileHeader *hd=ShortBlock.HeaderType==HEAD_FILE ? &FileHead:&SubHead;
-        hd->Reset();
+        hd->Reset(); // Clear hash, time fields and other stuff like flags.
         *(BaseBlock *)hd=ShortBlock;
 
         bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
@@ -1257,11 +1257,13 @@
     Raw.Read(NameSize);
 
     char FileName[NM];
-    Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
-    FileName[NameSize]=0;
+    size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
+    Raw.GetB((byte *)FileName,ReadNameSize);
+    FileName[ReadNameSize]=0;
     IntToExt(FileName,FileName,ASIZE(FileName));
     CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
     ConvertNameCase(FileHead.FileName);
+    ConvertFileHeader(&FileHead);
 
     if (Raw.Size()!=0)
       NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
@@ -1415,7 +1417,7 @@
 }
 
 
-bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
+bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode)
 {
   if (BrokenHeader)
   {
@@ -1463,6 +1465,7 @@
   SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
   SubDataIO.EnableShowProgress(false);
   SubDataIO.SetFiles(this,DestFile);
+  SubDataIO.SetTestMode(TestMode);
   SubDataIO.UnpVolume=SubHead.SplitAfter;
   SubDataIO.SetSubHeader(&SubHead,NULL);
   Unpack.SetDestSize(SubHead.UnpSize);
diff --git a/third_party/unrar/src/blake2s.hpp b/third_party/unrar/src/blake2s.hpp
index 7dd715713..f88ef37 100644
--- a/third_party/unrar/src/blake2s.hpp
+++ b/third_party/unrar/src/blake2s.hpp
@@ -3,6 +3,7 @@
 #define _RAR_BLAKE2_
 
 #define BLAKE2_DIGEST_SIZE 32
+#define BLAKE2_THREADS_NUMBER 8
 
 enum blake2s_constant
 {
diff --git a/third_party/unrar/src/cmddata.cpp b/third_party/unrar/src/cmddata.cpp
index 7b92686..455a07b2 100644
--- a/third_party/unrar/src/cmddata.cpp
+++ b/third_party/unrar/src/cmddata.cpp
@@ -56,7 +56,6 @@
   // In Windows we may prefer to implement our own command line parser
   // to avoid replacing \" by " in standard parser. Such replacing corrupts
   // destination paths like "dest path\" in extraction commands.
-  // Also our own parser is Unicode compatible.
   const wchar *CmdLine=GetCommandLine();
 
   wchar *Par;
@@ -123,6 +122,7 @@
         wchar CmdChar=toupperw(*Command);
         bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
         bool Extract=CmdChar=='X' || CmdChar=='E';
+        bool Repair=CmdChar=='R' && Command[1]==0;
         if (EndSeparator && !Add)
           wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
         else
@@ -140,8 +140,8 @@
               ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
 
             }
-            else
-              if (Found && FileData.IsDir && Extract && *ExtrPath==0)
+            else // We use 'destpath\' when extracting and reparing.
+              if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0)
               {
                 wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
                 AddEndSlash(ExtrPath,ASIZE(ExtrPath));
@@ -287,17 +287,23 @@
             AppendArcNameToPath=APPENDARCNAME_DESTPATH;
           else
             if (Switch[2]=='1')
-              AppendArcNameToPath=APPENDARCNAME_OWNDIR;
+              AppendArcNameToPath=APPENDARCNAME_OWNSUBDIR;
+            else
+              if (Switch[2]=='2')
+                AppendArcNameToPath=APPENDARCNAME_OWNDIR;
           break;
 #ifndef SFX_MODULE
         case 'G':
           if (Switch[2]=='-' && Switch[3]==0)
             GenerateArcName=0;
           else
-          {
-            GenerateArcName=true;
-            wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
-          }
+            if (toupperw(Switch[2])=='F')
+              wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask));
+            else
+            {
+              GenerateArcName=true;
+              wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
+            }
           break;
 #endif
         case 'I':
@@ -372,11 +378,11 @@
         default:
           if (Switch[1]=='+')
           {
-            InclFileAttr|=GetExclAttr(Switch+2);
+            InclFileAttr|=GetExclAttr(Switch+2,InclDir);
             InclAttrSet=true;
           }
           else
-            ExclFileAttr|=GetExclAttr(Switch+1);
+            ExclFileAttr|=GetExclAttr(Switch+1,ExclDir);
           break;
       }
       break;
@@ -432,9 +438,9 @@
         wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo));
         break;
       }
-      if (wcsicomp(Switch+1,L"M")==0)
+      if (wcsicomp(Switch+1,L"M")==0) // For compatibility with pre-WinRAR 6.0 -im syntax. Replaced with -idv.
       {
-        MoreInfo=true;
+        VerboseOutput=true;
         break;
       }
       if (wcsicomp(Switch+1,L"NUL")==0)
@@ -461,6 +467,12 @@
             case 'P':
               DisablePercentage=true;
               break;
+            case 'N':
+              DisableNames=true;
+              break;
+            case 'V':
+              VerboseOutput=true;
+              break;
           }
         break;
       }
@@ -535,7 +547,6 @@
                   case 'D': Type=FILTER_DELTA;       break;
                   case 'A': Type=FILTER_AUDIO;       break;
                   case 'C': Type=FILTER_RGB;         break;
-                  case 'I': Type=FILTER_ITANIUM;     break;
                   case 'R': Type=FILTER_ARM;         break;
                 }
                 if (*Str=='+' || *Str=='-')
@@ -824,39 +835,7 @@
           SetTimeFilters(Switch+2,false,false);
           break;
         case 'S':
-          {
-            EXTTIME_MODE Mode=EXTTIME_HIGH3;
-            bool CommonMode=Switch[2]>='0' && Switch[2]<='4';
-            if (CommonMode)
-              Mode=(EXTTIME_MODE)(Switch[2]-'0');
-            if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
-              Mode=EXTTIME_HIGH3;
-            if (Switch[2]=='-')
-              Mode=EXTTIME_NONE;
-            if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0)
-              xmtime=xctime=xatime=Mode;
-            else
-            {
-              if (Switch[3]>='0' && Switch[3]<='4')
-                Mode=(EXTTIME_MODE)(Switch[3]-'0');
-              if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
-                Mode=EXTTIME_HIGH3;
-              if (Switch[3]=='-')
-                Mode=EXTTIME_NONE;
-              switch(toupperw(Switch[2]))
-              {
-                case 'M':
-                  xmtime=Mode;
-                  break;
-                case 'C':
-                  xctime=Mode;
-                  break;
-                case 'A':
-                  xatime=Mode;
-                  break;
-              }
-            }
-          }
+          SetStoreTimeMode(Switch+2);
           break;
         case '-':
           Test=false;
@@ -959,7 +938,10 @@
   if (wcschr(L"AFUMD",*Command)==NULL)
   {
     if (GenerateArcName)
-      GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false);
+    {
+      const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask;
+      GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false);
+    }
 
     StringList ArcMasks;
     ArcMasks.AddString(ArcName);
@@ -978,7 +960,6 @@
     case 'X':
     case 'E':
     case 'T':
-    case 'I':
       {
         CmdExtract Extract(this);
         Extract.DoExtract();
@@ -1021,7 +1002,7 @@
 
 
 #ifndef SFX_MODULE
-uint CommandData::GetExclAttr(const wchar *Str)
+uint CommandData::GetExclAttr(const wchar *Str,bool &Dir)
 {
   if (IsDigit(*Str))
     return wcstol(Str,NULL,0);
@@ -1031,10 +1012,10 @@
   {
     switch(toupperw(*Str))
     {
-#ifdef _UNIX
       case 'D':
-        Attr|=S_IFDIR;
+        Dir=true;
         break;
+#ifdef _UNIX
       case 'V':
         Attr|=S_IFCHR;
         break;
@@ -1048,9 +1029,6 @@
       case 'S':
         Attr|=0x4;
         break;
-      case 'D':
-        Attr|=0x10;
-        break;
       case 'A':
         Attr|=0x20;
         break;
diff --git a/third_party/unrar/src/cmddata.hpp b/third_party/unrar/src/cmddata.hpp
index bf0efa66..719b400 100644
--- a/third_party/unrar/src/cmddata.hpp
+++ b/third_party/unrar/src/cmddata.hpp
@@ -11,12 +11,12 @@
 class CommandData:public RAROptions
 {
   private:
-    void ProcessSwitchesString(const wchar *Str);
     void ProcessSwitch(const wchar *Switch);
     void BadSwitch(const wchar *Switch);
-    uint GetExclAttr(const wchar *Str);
+    uint GetExclAttr(const wchar *Str,bool &Dir);
 #if !defined(SFX_MODULE)
     void SetTimeFilters(const wchar *Mod,bool Before,bool Age);
+    void SetStoreTimeMode(const wchar *S);
 #endif
 
     bool FileLists;
@@ -33,6 +33,7 @@
     void ParseEnvVar();
     void ReadConfig();
     void PreprocessArg(const wchar *Arg);
+    void ProcessSwitchesString(const wchar *Str);
     void OutTitle();
     void OutHelp(RAR_EXIT ExitCode);
     bool IsSwitch(int Ch);
diff --git a/third_party/unrar/src/cmdfilter.cpp b/third_party/unrar/src/cmdfilter.cpp
index 20660cb..d6517ceb 100644
--- a/third_party/unrar/src/cmdfilter.cpp
+++ b/third_party/unrar/src/cmdfilter.cpp
@@ -128,16 +128,22 @@
 {
   bool ModeOR=false,TimeMods=false;
   const wchar *S=Mod;
-  for (;wcschr(L"MCAOmcao",*S)!=NULL;S++)
+  // Check if any 'mca' modifiers are present, set OR mode if 'o' is present,
+  // skip modifiers and set S to beginning of time string. Be sure to check
+  // *S!=0, because termination 0 is a part of string for wcschr.
+  for (;*S!=0 && wcschr(L"MCAOmcao",*S)!=NULL;S++)
     if (*S=='o' || *S=='O')
       ModeOR=true;
     else
       TimeMods=true;
 
-  if (!TimeMods)
+  if (!TimeMods) // Assume 'm' if no modifiers are specified.
     Mod=L"m";
 
-  for (;wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++)
+  // Set the specified time for every modifier. Be sure to check *Mod!=0,
+  // because termination 0 is a part of string for wcschr. This check is
+  // important when we set Mod to "m" above.
+  for (;*Mod!=0 && wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++)
     switch(toupperw(*Mod))
     {
       case 'M': 
@@ -279,7 +285,10 @@
 #ifndef SFX_MODULE
   if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime))
     return 0;
-  if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0)
+  if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir)
+    return 0;
+  if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 ||
+      FileHead.Dir && !InclDir))
     return 0;
   if (!Dir && SizeCheck(FileHead.UnpSize))
     return 0;
@@ -297,3 +306,47 @@
     }
   return 0;
 }
+
+
+#if !defined(SFX_MODULE)
+void CommandData::SetStoreTimeMode(const wchar *S)
+{
+  if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+')
+  {
+    // Apply -ts, -ts1, -ts-, -ts+ to all 3 times.
+    // Handle obsolete -ts[2,3,4] as ts+.
+    EXTTIME_MODE Mode=EXTTIME_MAX;
+    if (*S=='-')
+      Mode=EXTTIME_NONE;
+    if (*S=='1')
+      Mode=EXTTIME_1S;
+    xmtime=xctime=xatime=Mode;
+    S++;
+  }
+
+  while (*S!=0)
+  {
+    EXTTIME_MODE Mode=EXTTIME_MAX;
+    if (S[1]=='-')
+      Mode=EXTTIME_NONE;
+    if (S[1]=='1')
+      Mode=EXTTIME_1S;
+    switch(toupperw(*S))
+    {
+      case 'M':
+        xmtime=Mode;
+        break;
+      case 'C':
+        xctime=Mode;
+        break;
+      case 'A':
+        xatime=Mode;
+        break;
+      case 'P':
+        PreserveAtime=true;
+        break;
+    }
+    S++;
+  }
+}
+#endif
diff --git a/third_party/unrar/src/consio.cpp b/third_party/unrar/src/consio.cpp
index 196066e..fedd5c0 100644
--- a/third_party/unrar/src/consio.cpp
+++ b/third_party/unrar/src/consio.cpp
@@ -164,7 +164,7 @@
     SetConsoleMode(hConIn,ConInMode);
     SetConsoleMode(hConOut,ConOutMode);
 #else
-    char StrA[MAXPASSWORD];
+    char StrA[MAXPASSWORD*4]; // "*4" for multibyte UTF-8 characters.
 #if defined(_EMX) || defined (__VMS)
     fgets(StrA,ASIZE(StrA)-1,stdin);
 #elif defined(__sun)
@@ -248,6 +248,12 @@
       ErrHandler.Exit(RARX_USERBREAK);
     }
     StrA[ReadSize]=0;
+
+    // We expect ANSI encoding here, but "echo text|rar ..." to pipe to RAR,
+    // such as send passwords, we get OEM encoding by default, unless we
+    // use "chcp" in console. But we avoid OEM to ANSI conversion,
+    // because we also want to handle ANSI files redirection correctly,
+    // like "rar ... < ansifile.txt".
     CharToWide(&StrA[0],str,n);
     cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords.
   }
@@ -305,7 +311,7 @@
 
   for (int I=0;I<NumItems;I++)
   {
-    eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
+    eprintf(I==0 ? (NumItems>3 ? L"\n":L" "):L", ");
     int KeyPos=ItemKeyPos[I];
     for (int J=0;J<KeyPos;J++)
       eprintf(L"%c",Item[I][J]);
diff --git a/third_party/unrar/src/crc.cpp b/third_party/unrar/src/crc.cpp
index 8488e10..4c86c09 100644
--- a/third_party/unrar/src/crc.cpp
+++ b/third_party/unrar/src/crc.cpp
@@ -77,7 +77,7 @@
                crc_tables[5][(byte)(StartCRC >> 16)] ^
                crc_tables[4][(byte)(StartCRC >> 24)] ^
                crc_tables[3][(byte) NextData       ] ^
-               crc_tables[2][(byte)(NextData >>8 ) ] ^
+               crc_tables[2][(byte)(NextData >> 8) ] ^
                crc_tables[1][(byte)(NextData >> 16)] ^
                crc_tables[0][(byte)(NextData >> 24)];
   }
diff --git a/third_party/unrar/src/dll.cpp b/third_party/unrar/src/dll.cpp
index 5f4d00e..31818e49 100644
--- a/third_party/unrar/src/dll.cpp
+++ b/third_party/unrar/src/dll.cpp
@@ -95,23 +95,23 @@
     r->Flags=0;
     
     if (Data->Arc.Volume)
-      r->Flags|=0x01;
+      r->Flags|=ROADF_VOLUME;
     if (Data->Arc.MainComment)
-      r->Flags|=0x02;
+      r->Flags|=ROADF_COMMENT;
     if (Data->Arc.Locked)
-      r->Flags|=0x04;
+      r->Flags|=ROADF_LOCK;
     if (Data->Arc.Solid)
-      r->Flags|=0x08;
+      r->Flags|=ROADF_SOLID;
     if (Data->Arc.NewNumbering)
-      r->Flags|=0x10;
+      r->Flags|=ROADF_NEWNUMBERING;
     if (Data->Arc.Signed)
-      r->Flags|=0x20;
+      r->Flags|=ROADF_SIGNED;
     if (Data->Arc.Protected)
-      r->Flags|=0x40;
+      r->Flags|=ROADF_RECOVERY;
     if (Data->Arc.Encrypted)
-      r->Flags|=0x80;
+      r->Flags|=ROADF_ENCHEADERS;
     if (Data->Arc.FirstVolume)
-      r->Flags|=0x100;
+      r->Flags|=ROADF_FIRSTVOLUME;
 
     Array<wchar> CmtDataW;
     if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
@@ -474,6 +474,7 @@
   switch(ErrCode)
   {
     case RARX_FATAL:
+    case RARX_READ:
       return ERAR_EREAD;
     case RARX_CRC:
       return ERAR_BAD_DATA;
diff --git a/third_party/unrar/src/dll.rc b/third_party/unrar/src/dll.rc
index 4564d92..e12a927 100644
--- a/third_party/unrar/src/dll.rc
+++ b/third_party/unrar/src/dll.rc
@@ -2,8 +2,8 @@
 #include <commctrl.h>

 

 VS_VERSION_INFO VERSIONINFO

-FILEVERSION 5, 70, 100, 2983
-PRODUCTVERSION 5, 70, 100, 2983
+FILEVERSION 6, 0, 100, 3629
+PRODUCTVERSION 6, 0, 100, 3629
 FILEOS VOS__WINDOWS32

 FILETYPE VFT_APP

 {

@@ -14,9 +14,9 @@
       VALUE "CompanyName", "Alexander Roshal\0"

       VALUE "ProductName", "RAR decompression library\0"

       VALUE "FileDescription", "RAR decompression library\0"

-      VALUE "FileVersion", "5.70.0\0"
-      VALUE "ProductVersion", "5.70.0\0"
-      VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2019\0"
+      VALUE "FileVersion", "6.0.0\0"
+      VALUE "ProductVersion", "6.0.0\0"
+      VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0"
       VALUE "OriginalFilename", "Unrar.dll\0"

     }

   }

diff --git a/third_party/unrar/src/errhnd.cpp b/third_party/unrar/src/errhnd.cpp
index 8ccdaa7..dce0fbc09 100644
--- a/third_party/unrar/src/errhnd.cpp
+++ b/third_party/unrar/src/errhnd.cpp
@@ -17,6 +17,7 @@
   UserBreak=false;
   MainExit=false;
   DisableShutdown=false;
+  ReadErrIgnoreAll=false;
 }
 
 
@@ -58,24 +59,34 @@
   ReadErrorMsg(FileName);
 #endif
 #if !defined(SILENT) || defined(RARDLL)
-  Exit(RARX_FATAL);
+  Exit(RARX_READ);
 #endif
 }
 
 
-bool ErrorHandler::AskRepeatRead(const wchar *FileName)
+void ErrorHandler::AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit)
 {
+  SetErrorCode(RARX_READ);
 #if !defined(SILENT) && !defined(SFX_MODULE)
   if (!Silent)
   {
+    uiMsg(UIERROR_FILEREAD,UINULL,FileName);
     SysErrMsg();
-    bool Repeat=uiAskRepeatRead(FileName);
-    if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
-      DisableShutdown=true;
-    return Repeat;
+    if (ReadErrIgnoreAll)
+      Ignore=true;
+    else
+    {
+      bool All=false;
+      uiAskRepeatRead(FileName,Ignore,All,Retry,Quit);
+      if (All)
+        ReadErrIgnoreAll=Ignore=true;
+      if (Quit) // Disable shutdown if user select Quit in read error prompt.
+        DisableShutdown=true;
+    }
+    return;
   }
 #endif
-  return false;
+  Ignore=true; // Saving the file part for -y or -inul or "Ignore all" choice.
 }
 
 
@@ -160,6 +171,7 @@
 
 void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
 {
+  Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
   uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
   SysErrMsg();
   SetErrorCode(RARX_OPEN);
@@ -190,7 +202,7 @@
 {
   uiMsg(UIERROR_FILEREAD,ArcName,FileName);
   SysErrMsg();
-  SetErrorCode(RARX_FATAL);
+  SetErrorCode(RARX_READ);
 }
 
 
@@ -334,7 +346,7 @@
 
 bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
 {
-#if !defined(SFX_MODULE) && !defined(SILENT)
+#ifndef SILENT
 #ifdef _WIN_ALL
   int ErrType=GetLastError();
   if (ErrType!=0)
@@ -367,7 +379,7 @@
     return;
 #ifdef _WIN_ALL
   wchar *CurMsg=Msg;
-  while (CurMsg!=NULL)
+  while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines.
   {
     while (*CurMsg=='\r' || *CurMsg=='\n')
       CurMsg++;
diff --git a/third_party/unrar/src/errhnd.hpp b/third_party/unrar/src/errhnd.hpp
index 13027c1..3c5c54c49 100644
--- a/third_party/unrar/src/errhnd.hpp
+++ b/third_party/unrar/src/errhnd.hpp
@@ -15,9 +15,11 @@
   RARX_CREATE    =   9,
   RARX_NOFILES   =  10,
   RARX_BADPWD    =  11,
+  RARX_READ      =  12,
   RARX_USERBREAK = 255
 };
 
+
 class ErrorHandler
 {
   private:
@@ -26,13 +28,14 @@
     bool EnableBreak = true;
     bool Silent = false;
     bool DisableShutdown = false; // Shutdown is not suitable after last error.
+    bool ReadErrIgnoreAll = false;
   public:
     void Clean();
     void MemoryError();
     void OpenError(const wchar *FileName);
     void CloseError(const wchar *FileName);
     void ReadError(const wchar *FileName);
-    bool AskRepeatRead(const wchar *FileName);
+    void AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit);
     void WriteError(const wchar *ArcName,const wchar *FileName);
     void WriteErrorFAT(const wchar *FileName);
     bool AskRepeatWrite(const wchar *FileName,bool DiskFull);
diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp
index a748718..2c264b10 100644
--- a/third_party/unrar/src/extract.cpp
+++ b/third_party/unrar/src/extract.cpp
@@ -40,6 +40,9 @@
   {
     if (Cmd->ManualPassword)
       Cmd->Password.Clean(); // Clean user entered password before processing next archive.
+  
+    ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
+    UseExactVolName=false; // Must be reset here, not in ExtractArchiveInit().
     while (true)
     {
       EXTRACT_ARC_CODE Code=ExtractArchive();
@@ -93,7 +96,6 @@
 
   PrevProcessed=false;
   AllMatchesExact=true;
-  ReconstructDone=false;
   AnySolidDataUnpackedWell=false;
 
   StartTime.SetCurrentTime();
@@ -139,7 +141,7 @@
     return EXTRACT_ARC_NEXT;
 
 #ifndef SFX_MODULE
-  if (Arc.Volume && !Arc.FirstVolume)
+  if (Arc.Volume && !Arc.FirstVolume && !UseExactVolName)
   {
     wchar FirstVolName[NM];
     VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering);
@@ -157,6 +159,16 @@
 
   if (Arc.Volume)
   {
+#ifndef SFX_MODULE
+    // Try to speed up extraction for independent solid volumes by starting
+    // extraction from non-first volume if we can.
+    if (!UseExactVolName && Arc.Solid && DetectStartVolume(Arc.FileName,Arc.NewNumbering))
+    {
+      UseExactVolName=true;
+      return EXTRACT_ARC_REPEAT;
+    }
+#endif
+
     // Calculate the total size of all accessible volumes.
     // This size is necessary to display the correct total progress indicator.
 
@@ -317,11 +329,11 @@
   Arc.ConvertAttributes();
 
 #if !defined(SFX_MODULE) && !defined(RARDLL)
-  if (Arc.FileHead.SplitBefore && FirstFile)
+  if (Arc.FileHead.SplitBefore && FirstFile && !UseExactVolName)
   {
     wchar CurVolName[NM];
     wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName));
-    VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering);
+    GetFirstVolIfFullSet(ArcName,Arc.NewNumbering,ArcName,ASIZE(ArcName));
 
     if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
     {
@@ -479,13 +491,13 @@
         {
           // This message is used by Android GUI to reset cached passwords.
           // Update appropriate code if changed.
-          uiMsg(UIERROR_BADPSW,ArcFileName);
+          uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName);
         }
         else // For passwords entered manually.
         {
           // This message is used by Android GUI and Windows GUI and SFX to
           // reset cached passwords. Update appropriate code if changed.
-          uiMsg(UIWAIT_BADPSW,ArcFileName);
+          uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName);
           Cmd->Password.Clean();
 
           // Avoid new requests for unrar.dll to prevent the infinite loop
@@ -579,7 +591,7 @@
         TotalFileCount++;
       }
       FileCount++;
-      if (Command!='I')
+      if (Command!='I' && !Cmd->DisableNames)
         if (SkipSolid)
           mprintf(St(MExtrSkipFile),ArcFileName);
         else
@@ -598,8 +610,10 @@
               mprintf(St(MExtrFile),DestFileName);
               break;
           }
-      if (!Cmd->DisablePercentage)
+      if (!Cmd->DisablePercentage && !Cmd->DisableNames)
         mprintf(L"     ");
+      if (Cmd->DisableNames)
+        uiEolAfterMsg(); // Avoid erasing preceding messages by percentage indicator in -idn mode.
 
       DataIO.CurUnpRead=0;
       DataIO.CurUnpWrite=0;
@@ -621,11 +635,14 @@
       }
 #endif
 
-      if (!TestMode && !Arc.BrokenHeader &&
-          (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
+      uint64 Preallocated=0;
+      if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 &&
+          Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize &&
           (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
+      {
         CurFile.Prealloc(Arc.FileHead.UnpSize);
-
+        Preallocated=Arc.FileHead.UnpSize;
+      }
       CurFile.SetAllowDelete(!Cmd->KeepBroken);
 
       bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
@@ -712,7 +729,7 @@
       {
         if (ValidCRC)
         {
-          if (Command!='P' && Command!='I')
+          if (Command!='P' && Command!='I' && !Cmd->DisableNames)
             mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ",
               Arc.FileHead.FileHash.Type==HASH_NONE ? L"  ?":St(MOk));
         }
@@ -737,37 +754,58 @@
       else
         mprintf(L"\b\b\b\b\b     ");
 
+      // If we successfully unpacked a hard link, we wish to set its file
+      // attributes. Hard link shares file metadata with link target,
+      // so we do not need to set link time or owner. But when we overwrite
+      // an existing link, we can call PrepareToDelete(), which affects
+      // link target attributes as well. So we set link attributes to restore
+      // both target and link attributes if PrepareToDelete() changed them.
+      bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess;
+
       if (!TestMode && (Command=='X' || Command=='E') &&
-          (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && 
+          (!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && 
           (!BrokenFile || Cmd->KeepBroken))
       {
-        // We could preallocate more space that really written to broken file.
-        if (BrokenFile)
-          CurFile.Truncate();
+        // Below we use DestFileName instead of CurFile.FileName,
+        // so we can set file attributes also for hard links, which do not
+        // have the open CurFile. These strings are the same for other items.
 
-#if defined(_WIN_ALL) || defined(_EMX)
-        if (Cmd->ClearArc)
-          Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
-#endif
+        if (!SetAttrOnly)
+        {
+          // We could preallocate more space that really written to broken file
+          // or file with crafted header.
+          if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated))
+            CurFile.Truncate();
 
 
-        CurFile.SetOpenFileTime(
-          Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
-          Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
-          Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
-        CurFile.Close();
+          CurFile.SetOpenFileTime(
+            Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
+            Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
+            Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
+          CurFile.Close();
+
+          SetFileHeaderExtra(Cmd,Arc,DestFileName);
+
+          CurFile.SetCloseFileTime(
+            Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
+            Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
+        }
+        
 #if defined(_WIN_ALL) && !defined(SFX_MODULE)
         if (Cmd->SetCompressedAttr &&
             (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
-          SetFileCompression(CurFile.FileName,true);
+          SetFileCompression(DestFileName,true);
+        if (Cmd->ClearArc)
+          Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
 #endif
-        SetFileHeaderExtra(Cmd,Arc,CurFile.FileName);
-
-        CurFile.SetCloseFileTime(
-          Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
-          Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
-        if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr))
-          uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName);
+        if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr))
+        {
+          uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName);
+          // Android cannot set file attributes and while UIERROR_FILEATTR
+          // above is handled by Android RAR silently, this call would cause
+          // "Operation not permitted" message for every unpacked file.
+          ErrHandler.SysErrMsg();
+        }
 
         PrevProcessed=true;
       }
@@ -860,11 +898,21 @@
 #ifndef SFX_MODULE
   if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE)
   {
-    if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH)
-      wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
-    else
-      wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir.
-    SetExt(DestName,NULL,DestSize);
+    switch(Cmd->AppendArcNameToPath)
+    {
+      case APPENDARCNAME_DESTPATH: // To subdir of destination path.
+        wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
+        SetExt(DestName,NULL,DestSize);
+        break;
+      case APPENDARCNAME_OWNSUBDIR: // To subdir of archive own dir.
+        wcsncpyz(DestName,Arc.FirstVolumeName,DestSize);
+        SetExt(DestName,NULL,DestSize);
+        break;
+      case APPENDARCNAME_OWNDIR:  // To archive own dir.
+        wcsncpyz(DestName,Arc.FirstVolumeName,DestSize);
+        RemoveNameFromPath(DestName);
+        break;
+    }
     AddEndSlash(DestName,DestSize);
   }
 #endif
@@ -976,7 +1024,11 @@
     if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/)
     {
       // Suppress "test is ok" message if user cancelled the password prompt.
-      uiMsg(UIERROR_INCERRCOUNT);
+// 2019.03.23: If some archives are tested ok and prompt is cancelled for others,
+// do we really need to suppress "test is ok"? Also if we set an empty password
+// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives.
+// We commented out this UIERROR_INCERRCOUNT for now.
+//      uiMsg(UIERROR_INCERRCOUNT);
       return false;
     }
     Cmd->ManualPassword=true;
@@ -1030,8 +1082,11 @@
 {
   if (Cmd->Test)
   {
-    mprintf(St(MExtrTestFile),ArcFileName);
-    mprintf(L" %s",St(MOk));
+    if (!Cmd->DisableNames)
+    {
+      mprintf(St(MExtrTestFile),ArcFileName);
+      mprintf(L" %s",St(MOk));
+    }
     return;
   }
 
@@ -1068,8 +1123,11 @@
   }
   if (MDCode==MKDIR_SUCCESS)
   {
-    mprintf(St(MCreatDir),DestFileName);
-    mprintf(L" %s",St(MOk));
+    if (!Cmd->DisableNames)
+    {
+      mprintf(St(MCreatDir),DestFileName);
+      mprintf(L" %s",St(MOk));
+    }
     PrevProcessed=true;
   }
   else
@@ -1123,6 +1181,9 @@
       if (!UserReject)
       {
         ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
+        if (FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName)))
+          uiMsg(UIERROR_DIRNAMEEXISTS);
+
 #ifdef RARDLL
         Cmd->DllError=ERAR_ECREATE;
 #endif
@@ -1178,3 +1239,104 @@
   }
   return !WrongVer;
 }
+
+
+#ifndef SFX_MODULE
+// To speed up solid volumes extraction, try to find a non-first start volume,
+// which still allows to unpack all files. It is possible for independent
+// solid volumes with solid statistics reset in the beginning.
+bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering)
+{
+  wchar *ArgName=Cmd->FileArgs.GetString();
+  Cmd->FileArgs.Rewind();
+  if (ArgName!=NULL && (wcscmp(ArgName,L"*")==0 || wcscmp(ArgName,L"*.*")==0))
+    return false; // No need to check further for * and *.* masks.
+
+  wchar StartName[NM];
+  *StartName=0;
+  
+  // Start search from first volume if all volumes preceding current are available.
+  wchar NextName[NM];
+  GetFirstVolIfFullSet(VolName,NewNumbering,NextName,ASIZE(NextName));
+
+  bool Matched=false;
+  while (!Matched)
+  {
+    Archive Arc(Cmd);
+    if (!Arc.Open(NextName) || !Arc.IsArchive(false) || !Arc.Volume)
+      break;
+
+    bool OpenNext=false;
+    while (Arc.ReadHeader()>0)
+    {
+      Wait();
+
+      HEADER_TYPE HeaderType=Arc.GetHeaderType();
+      if (HeaderType==HEAD_ENDARC)
+      {
+        OpenNext|=Arc.EndArcHead.NextVolume; // Allow open next volume.
+        break;
+      }
+      if (HeaderType==HEAD_FILE)
+      {
+        if (!Arc.FileHead.SplitBefore)
+        {
+          if (!Arc.FileHead.Solid) // Can start extraction from here.
+            wcsncpyz(StartName,NextName,ASIZE(StartName));
+
+          if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0)
+          {
+            Matched=true; // First matched file found, must stop further scan.
+            break;
+          }
+        }
+        if (Arc.FileHead.SplitAfter)
+        {
+          OpenNext=true; // Allow open next volume.
+          break;
+        }
+      }
+      Arc.SeekToNext();
+    }
+    Arc.Close();
+
+    if (!OpenNext)
+      break;
+
+    NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
+  }
+  bool NewStartFound=wcscmp(VolName,StartName)!=0;
+  if (NewStartFound) // Found a new volume to start extraction.
+    wcsncpyz(ArcName,StartName,ASIZE(ArcName));
+  
+  return NewStartFound;
+}
+#endif
+
+
+#ifndef SFX_MODULE
+// Return the first volume name if all volumes preceding the specified
+// are available. Otherwise return the specified volume name.
+void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize)
+{
+  wchar FirstVolName[NM];
+  VolNameToFirstName(SrcName,FirstVolName,ASIZE(FirstVolName),NewNumbering);
+  wchar NextName[NM];
+  wcsncpyz(NextName,FirstVolName,ASIZE(NextName));
+  wchar ResultName[NM];
+  wcsncpyz(ResultName,SrcName,ASIZE(ResultName));
+  while (true)
+  {
+    if (wcscmp(SrcName,NextName)==0)
+    {
+      wcsncpyz(ResultName,FirstVolName,DestSize);
+      break;
+    }
+    if (!FileExist(NextName))
+      break;
+    NextVolumeName(NextName,ASIZE(NextName),!NewNumbering);
+  }
+  wcsncpyz(DestName,ResultName,DestSize);
+}
+
+#endif
diff --git a/third_party/unrar/src/extract.hpp b/third_party/unrar/src/extract.hpp
index aa69a3dc..9a65959 100644
--- a/third_party/unrar/src/extract.hpp
+++ b/third_party/unrar/src/extract.hpp
@@ -20,8 +20,12 @@
     void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName);
     bool ExtrCreateFile(Archive &Arc,File &CurFile);
     bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
+#ifndef SFX_MODULE
+    bool DetectStartVolume(const wchar *VolName,bool NewNumbering);
+    void GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize);
+#endif
 
-    RarTime StartTime; // time when extraction started
+    RarTime StartTime; // Time when extraction started.
 
     CommandData *Cmd;
 
@@ -33,7 +37,8 @@
     unsigned long MatchedArgs;
     bool FirstFile;
     bool AllMatchesExact;
-    bool ReconstructDone;
+    bool ReconstructDone=false;
+    bool UseExactVolName=false;
 
     // If any non-zero solid file was successfully unpacked before current.
     // If true and if current encrypted file is broken, obviously
diff --git a/third_party/unrar/src/file.cpp b/third_party/unrar/src/file.cpp
index d8bf24a..cd6be33 100644
--- a/third_party/unrar/src/file.cpp
+++ b/third_party/unrar/src/file.cpp
@@ -8,15 +8,17 @@
   LastWrite=false;
   HandleType=FILE_HANDLENORMAL;
   SkipClose=false;
-  IgnoreReadErrors=false;
   ErrorType=FILE_SUCCESS;
   OpenShared=false;
   AllowDelete=true;
   AllowExceptions=true;
+  PreserveAtime=false;
 #ifdef _WIN_ALL
   NoSequentialRead=false;
   CreateMode=FMF_UNDEFINED;
 #endif
+  ReadErrorMode=FREM_ASK;
+  TruncatedAfterReadError=false;
 
 #ifdef CHROMIUM_UNRAR
   hOpenFile=FILE_BAD_HANDLE;
@@ -40,6 +42,7 @@
   NewFile=SrcFile.NewFile;
   LastWrite=SrcFile.LastWrite;
   HandleType=SrcFile.HandleType;
+  TruncatedAfterReadError=SrcFile.TruncatedAfterReadError;
   wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName));
   SrcFile.SkipClose=true;
 }
@@ -65,6 +68,9 @@
   if (OpenShared)
     ShareMode|=FILE_SHARE_WRITE;
   uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
+  FindData FD;
+  if (PreserveAtime)
+    Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime.
   hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
 
   DWORD LastError;
@@ -95,7 +101,11 @@
   }
   if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
     ErrorType=FILE_NOTFOUND;
-
+  if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE)
+  {
+    FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification.
+    SetFileTime(hNewFile,NULL,&ft,NULL);
+  }
 #endif  // defined(CHROMIUM_UNRAR)
 
 #else
@@ -112,8 +122,14 @@
   flags|=O_LARGEFILE;
 #endif
 #endif
+  // NDK r20 has O_NOATIME, but fails to create files with it in Android 7+.
+#if defined(O_NOATIME)
+  if (PreserveAtime)
+    flags|=O_NOATIME;
+#endif
   char NameA[NM];
   WideToChar(Name,NameA,ASIZE(NameA));
+
   int handle=open(NameA,flags);
 #endif  // defined(CHROMIUM_UNRAR)
 
@@ -122,12 +138,12 @@
 #ifdef _OSF_SOURCE
   extern "C" int flock(int, int);
 #endif
-
   if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
   {
     close(handle);
     return false;
   }
+
 #endif
   if (handle==-1)
     hNewFile=FILE_BAD_HANDLE;
@@ -150,6 +166,7 @@
   {
     hFile=hNewFile;
     wcsncpyz(FileName,Name,ASIZE(FileName));
+    TruncatedAfterReadError=false;
   }
   return Success;
 }
@@ -256,7 +273,7 @@
 // unrar should not close the file handle since it wasn't opened by unrar.
 #ifdef _WIN_ALL
       // We use the standard system handle for stdout in Windows
-      // and it must not  be closed here.
+      // and it must not be closed here.
       if (HandleType==FILE_HANDLENORMAL)
         Success=CloseHandle(hFile)==TRUE;
 #else
@@ -382,9 +399,12 @@
 
 int File::Read(void *Data,size_t Size)
 {
+  if (TruncatedAfterReadError)
+    return 0;
+
   int64 FilePos=0; // Initialized only to suppress some compilers warning.
 
-  if (IgnoreReadErrors)
+  if (ReadErrorMode==FREM_IGNORE)
     FilePos=Tell();
   int ReadSize;
   while (true)
@@ -394,7 +414,7 @@
     {
       ErrorType=FILE_READERROR;
       if (AllowExceptions)
-        if (IgnoreReadErrors)
+        if (ReadErrorMode==FREM_IGNORE)
         {
           ReadSize=0;
           for (size_t I=0;I<Size;I+=512)
@@ -407,14 +427,24 @@
         }
         else
         {
-          if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
-            continue;
+          bool Ignore=false,Retry=false,Quit=false;
+          if (ReadErrorMode==FREM_ASK && HandleType==FILE_HANDLENORMAL)
+          {
+            ErrHandler.AskRepeatRead(FileName,Ignore,Retry,Quit);
+            if (Retry)
+              continue;
+          }
+          if (Ignore || ReadErrorMode==FREM_TRUNCATE)
+          {
+            TruncatedAfterReadError=true;
+            return 0;
+          }
           ErrHandler.ReadError(FileName);
         }
     }
     break;
   }
-  return ReadSize;
+  return ReadSize; // It can return -1 only if AllowExceptions is disabled.
 }
 
 
@@ -697,9 +727,11 @@
 
 int64 File::FileLength()
 {
-  SaveFilePos SavePos(*this);
+  int64 SavePos=Tell();
   Seek(0,SEEK_END);
-  return Tell();
+  int64 Length=Tell();
+  Seek(SavePos,SEEK_SET);
+  return Length;
 }
 
 
diff --git a/third_party/unrar/src/file.hpp b/third_party/unrar/src/file.hpp
index a4dc7e0..baf366dfa 100644
--- a/third_party/unrar/src/file.hpp
+++ b/third_party/unrar/src/file.hpp
@@ -46,6 +46,12 @@
   FMF_UNDEFINED=256
 };
 
+enum FILE_READ_ERROR_MODE {
+  FREM_ASK,          // Propose to use the already read part, retry or abort.
+  FREM_TRUNCATE,     // Use the already read part without additional prompt.
+  FREM_IGNORE        // Try to skip unreadable block and read further.
+};
+
 
 class File
 {
@@ -54,7 +60,7 @@
     bool LastWrite;
     FILE_HANDLETYPE HandleType;
     bool SkipClose;
-    bool IgnoreReadErrors;
+    FILE_READ_ERROR_MODE ReadErrorMode;
     bool NewFile;
     bool AllowDelete;
     bool AllowExceptions;
@@ -62,6 +68,8 @@
     bool NoSequentialRead;
     uint CreateMode;
 #endif
+    bool PreserveAtime;
+    bool TruncatedAfterReadError;
   protected:
     bool OpenShared; // Set by 'Archive' class.
   public:
@@ -111,13 +119,15 @@
     static bool RemoveCreated();
     FileHandle GetHandle() {return hFile;}
     void SetHandle(FileHandle Handle) {Close();hFile=Handle;}
-    void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}
+    void SetReadErrorMode(FILE_READ_ERROR_MODE Mode) {ReadErrorMode=Mode;}
     int64 Copy(File &Dest,int64 Length=INT64NDF);
     void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
     void SetExceptions(bool Allow) {AllowExceptions=Allow;}
 #ifdef _WIN_ALL
     void RemoveSequentialFlag() {NoSequentialRead=true;}
 #endif
+    void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
+    bool IsTruncatedAfterReadError() {return TruncatedAfterReadError;}
 
 #if defined(CHROMIUM_UNRAR)
     // Since unrar runs in a sandbox, it doesn't have the permission to open
diff --git a/third_party/unrar/src/filefn.cpp b/third_party/unrar/src/filefn.cpp
index cae7598..57a334d 100644
--- a/third_party/unrar/src/filefn.cpp
+++ b/third_party/unrar/src/filefn.cpp
@@ -360,7 +360,7 @@
 #if !defined(SFX_MODULE)
 void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
 {
-  SaveFilePos SavePos(*SrcFile);
+  int64 SavePos=SrcFile->Tell();
 #ifndef SILENT
   int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
 #endif
@@ -415,6 +415,8 @@
     if (Size!=INT64NDF)
       Size-=ReadSize;
   }
+  SrcFile->Seek(SavePos,SEEK_SET);
+
   if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
     uiMsg(UIEVENT_FILESUMEND);
 
diff --git a/third_party/unrar/src/find.cpp b/third_party/unrar/src/find.cpp
index 98cf7719..b22f82d 100644
--- a/third_party/unrar/src/find.cpp
+++ b/third_party/unrar/src/find.cpp
@@ -63,12 +63,12 @@
   }
   while (1)
   {
+    wchar Name[NM];
     struct dirent *ent=readdir(dirp);
     if (ent==NULL)
       return false;
     if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
       continue;
-    wchar Name[NM];
     if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
       uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
 
diff --git a/third_party/unrar/src/hash.cpp b/third_party/unrar/src/hash.cpp
index 42791f4f..a4559e05 100644
--- a/third_party/unrar/src/hash.cpp
+++ b/third_party/unrar/src/hash.cpp
@@ -53,7 +53,7 @@
 DataHash::~DataHash()
 {
 #ifdef RAR_SMP
-  DestroyThreadPool(ThPool);
+  delete ThPool;
 #endif
   cleandata(&CurCRC32, sizeof(CurCRC32));
   if (blake2ctx!=NULL)
@@ -94,7 +94,7 @@
   {
 #ifdef RAR_SMP
     if (MaxThreads>1 && ThPool==NULL)
-      ThPool=CreateThreadPool();
+      ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
     blake2ctx->ThPool=ThPool;
     blake2ctx->MaxThreads=MaxThreads;
 #endif
diff --git a/third_party/unrar/src/list.cpp b/third_party/unrar/src/list.cpp
index 11c404e..476fd3c 100644
--- a/third_party/unrar/src/list.cpp
+++ b/third_party/unrar/src/list.cpp
@@ -28,7 +28,7 @@
     if (!Arc.WOpen(ArcName))
       continue;
     bool FileMatched=true;
-    while (1)
+    while (true)
     {
       int64 TotalPackSize=0,TotalUnpSize=0;
       uint FileCount=0;
@@ -69,8 +69,9 @@
 
         wchar VolNumText[50];
         *VolNumText=0;
-        while(Arc.ReadHeader()>0)
+        while (Arc.ReadHeader()>0)
         {
+          Wait(); // Allow quit listing with Ctrl+C.
           HEADER_TYPE HeaderType=Arc.GetHeaderType();
           if (HeaderType==HEAD_ENDARC)
           {
@@ -344,7 +345,7 @@
       mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
 
     mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
-            Format==RARFMT15 ? L"3.0":L"5.0",
+            Format==RARFMT15 ? L"1.5":L"5.0",
             hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method,
             hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
             hd.WinSize>=0x100000 ? L"M":L"K");
diff --git a/third_party/unrar/src/loclang.hpp b/third_party/unrar/src/loclang.hpp
index 181fcb4..99108c9 100644
--- a/third_party/unrar/src/loclang.hpp
+++ b/third_party/unrar/src/loclang.hpp
@@ -4,6 +4,7 @@
 #define   MYesNoAllRenQ      L"_Yes_No_All_nEver_Rename_Quit"
 #define   MContinueQuit      L"_Continue_Quit"
 #define   MRetryAbort        L"_Retry_Abort"
+#define   MIgnoreAllRetryQuit L"_Ignore_iGnore all_Retry_Quit"
 #define   MCopyright         L"\nRAR %s   Copyright (c) 1993-%d Alexander Roshal   %d %s %d"
 #define   MRegTo             L"\nRegistered to %s\n"
 #define   MShare             L"\nTrial version             Type 'rar -?' for help\n"
@@ -54,7 +55,7 @@
 #define   MCHelpSwm          L"\n  -             Stop switches scanning"
 #define   MCHelpSwAT         L"\n  @[+]          Disable [enable] file lists"
 #define   MCHelpSwAC         L"\n  ac            Clear Archive attribute after compression or extraction"
-#define   MCHelpSwAD         L"\n  ad            Append archive name to destination path"
+#define   MCHelpSwAD         L"\n  ad[1,2]       Alternate destination path"
 #define   MCHelpSwAG         L"\n  ag[format]    Generate archive name using the current date"
 #define   MCHelpSwAI         L"\n  ai            Ignore file attributes"
 #define   MCHelpSwAO         L"\n  ao            Add files with Archive attribute set"
@@ -79,13 +80,13 @@
 #define   MCHelpSwF          L"\n  f             Freshen files"
 #define   MCHelpSwHP         L"\n  hp[password]  Encrypt both file data and headers"
 #define   MCHelpSwHT         L"\n  ht[b|c]       Select hash type [BLAKE2,CRC32] for file checksum"
-#define   MCHelpSwIDP        L"\n  id[c,d,p,q]   Disable messages"
+#define   MCHelpSwIDP        L"\n  id[c,d,n,p,q] Display or disable messages"
 #define   MCHelpSwIEML       L"\n  ieml[addr]    Send archive by email"
 #define   MCHelpSwIERR       L"\n  ierr          Send all messages to stderr"
 #define   MCHelpSwILOG       L"\n  ilog[name]    Log errors to file"
 #define   MCHelpSwINUL       L"\n  inul          Disable all messages"
 #define   MCHelpSwIOFF       L"\n  ioff[n]       Turn PC off after completing an operation"
-#define   MCHelpSwISND       L"\n  isnd          Control notification sounds"
+#define   MCHelpSwISND       L"\n  isnd[-]       Control notification sounds"
 #define   MCHelpSwIVER       L"\n  iver          Display the version number"
 #define   MCHelpSwK          L"\n  k             Lock archive"
 #define   MCHelpSwKB         L"\n  kb            Keep broken extracted files"
@@ -131,7 +132,7 @@
 #define   MCHelpSwTO         L"\n  to[mcao]<t>   Process files older than <t> time"
 #define   MCHelpSwTA         L"\n  ta[mcao]<d>   Process files modified after <d> YYYYMMDDHHMMSS date"
 #define   MCHelpSwTB         L"\n  tb[mcao]<d>   Process files modified before <d> YYYYMMDDHHMMSS date"
-#define   MCHelpSwTS         L"\n  ts[m,c,a]     Save or restore file time (modification, creation, access)"
+#define   MCHelpSwTS         L"\n  ts[m,c,a,p]   Save or restore time (modification, creation, access, preserve)"
 #define   MCHelpSwU          L"\n  u             Update files"
 #define   MCHelpSwV          L"\n  v             Create volumes with size autodetection or list all volumes"
 #define   MCHelpSwVUnr       L"\n  v             List all volumes"
@@ -203,7 +204,6 @@
 #define   MErrOpenFile       L"file"
 #define   MAddNoFiles        L"\nWARNING: No files"
 #define   MMdfEncrSol        L"\n%s: encrypted"
-#define   MCannotMdfEncrSol  L"\nCannot modify solid archive containing encrypted files"
 #define   MAddAnalyze        L"\nAnalyzing archived files: "
 #define   MRepacking         L"\nRepacking archived files: "
 #define   MCRCFailed         L"\n%-20s - checksum error"
@@ -342,7 +342,7 @@
 #define   MFAT32Size         L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
 #define   MErrChangeAttr     L"\nWARNING: Cannot change attributes of %s"
 #define   MWrongSFXVer       L"\nERROR: default SFX module does not support RAR %d.%d archives"
-#define   MCannotEncName     L"\nCannot encrypt archive already containing encrypted files"
+#define   MHeadEncMismatch   L"\nCannot change the header encryption mode in already encrypted archive"
 #define   MCannotEmail       L"\nCannot email the file %s"
 #define   MCopyrightS        L"\nRAR SFX archive" 
 #define   MSHelpCmd          L"\n\n<Commands>" 
@@ -352,7 +352,7 @@
 #define   MRecVolLimit       L"\nTotal number of usual and recovery volumes must not exceed %d"
 #define   MVolumeNumber      L"volume %d"
 #define   MCannotDelete      L"\nCannot delete %s"
-#define   MRecycleFailed     L"\nCannot move some files and folders to Recycle Bin"
+#define   MRecycleFailed     L"\nCannot move some files and directories to Recycle Bin"
 #define   MCalcCRC           L"\nCalculating the checksum"
 #define   MTooLargeSFXArc    L"\nToo large SFX archive. Windows cannot run the executable file exceeding 4 GB."
 #define   MCalcCRCAllVol     L"\nCalculating checksums of all volumes."
@@ -360,6 +360,7 @@
 #define   MNewerRAR          L"\nYou may need a newer version of RAR."
 #define   MUnkEncMethod      L"\nUnknown encryption method in %s"
 #define   MWrongPassword     L"\nThe specified password is incorrect."
+#define   MWrongFilePassword L"\nIncorrect password for %s"
 #define   MAreaDamaged       L"\nCorrupt %d bytes at %08x %08x"
 #define   MBlocksRecovered   L"\n%u blocks are recovered, %u blocks are relocated"
 #define   MRRDamaged         L"\nRecovery record is corrupt."
@@ -379,3 +380,8 @@
 #define   MNeedAdmin         L"\nYou may need to run RAR as administrator"
 #define   MDictOutMem        L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
 #define   MUseSmalllerDict   L"\nPlease use a smaller compression dictionary."
+#define   MOpenErrAtime      L"\nYou may need to remove -tsp switch to open this file."
+#define   MErrReadInfo       L"\nChoose 'Ignore' to continue with the already read file part only, 'Ignore all' to do it for all read errors, 'Retry' to repeat read and 'Quit' to abort."
+#define   MErrReadTrunc      L"\n%s is archived incompletely because of read error.\n"
+#define   MErrReadCount      L"\n%u files are archived incompletely because of read errors."
+#define   MDirNameExists     L"\nDirectory with such name already exists"
diff --git a/third_party/unrar/src/makefile b/third_party/unrar/src/makefile
index f70755f..214f87e 100644
--- a/third_party/unrar/src/makefile
+++ b/third_party/unrar/src/makefile
@@ -138,7 +138,9 @@
 uninstall:	uninstall-unrar
 
 clean:
-	@rm -f *.o *.bak *~
+	@rm -f *.bak *~
+	@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
+	@rm -f unrar libunrar.*
 
 unrar:	clean $(OBJECTS) $(UNRAR_OBJ)
 	@rm -f unrar
@@ -154,8 +156,7 @@
 lib:	WHAT=RARDLL
 lib:	CXXFLAGS+=$(LIBFLAGS)
 lib:	clean $(OBJECTS) $(LIB_OBJ)
-	@rm -f libunrar.so
-	@rm -f libunrar.a
+	@rm -f libunrar.*
 	$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
 	$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
 
diff --git a/third_party/unrar/src/options.cpp b/third_party/unrar/src/options.cpp
index b53edc6..40323be 100644
--- a/third_party/unrar/src/options.cpp
+++ b/third_party/unrar/src/options.cpp
@@ -22,7 +22,7 @@
   Method=3;
   MsgStream=MSG_STDOUT;
   ConvertNames=NAMES_ORIGINALCASE;
-  xmtime=EXTTIME_HIGH3;
+  xmtime=EXTTIME_MAX;
   FileSizeLess=INT64NDF;
   FileSizeMore=INT64NDF;
   HashType=HASH_CRC32;
diff --git a/third_party/unrar/src/options.hpp b/third_party/unrar/src/options.hpp
index 7c33a03..993b219 100644
--- a/third_party/unrar/src/options.hpp
+++ b/third_party/unrar/src/options.hpp
@@ -21,7 +21,7 @@
 enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
 
 enum EXTTIME_MODE {
-  EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
+  EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX
 };
 
 enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
@@ -61,7 +61,8 @@
 
 enum APPENDARCNAME_MODE
 {
-  APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR
+  APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNSUBDIR,
+  APPENDARCNAME_OWNDIR
 };
 
 enum POWER_MODE {
@@ -92,6 +93,12 @@
 
     uint ExclFileAttr;
     uint InclFileAttr;
+
+    // We handle -ed and -e+d with special flags instead of attribute mask,
+    // so it works with both Windows and Unix archives.
+    bool ExclDir;
+    bool InclDir;
+
     bool InclAttrSet;
     size_t WinSize;
     wchar TempPath[NM];
@@ -126,6 +133,7 @@
     bool DisablePercentage;
     bool DisableCopyright;
     bool DisableDone;
+    bool DisableNames;
     bool PrintVersion;
     int Solid;
     int SolidCount;
@@ -140,7 +148,7 @@
     Array<int64> NextVolSizes;
     uint CurVolNum;
     bool AllYes;
-    bool MoreInfo; // -im, show more information, used only in "WinRAR t" now.
+    bool VerboseOutput; // -iv, display verbose output, used only in "WinRAR t" now.
     bool DisableSortSolid;
     int ArcTime;
     int ConvertNames;
@@ -162,6 +170,7 @@
 #ifndef SFX_MODULE
     bool GenerateArcName;
     wchar GenerateMask[MAX_GENERATE_MASK];
+    wchar DefGenerateMask[MAX_GENERATE_MASK];
 #endif
     bool SyncFiles;
     bool ProcessEA;
@@ -185,6 +194,7 @@
     EXTTIME_MODE xmtime; // Extended time modes (time precision to store).
     EXTTIME_MODE xctime;
     EXTTIME_MODE xatime;
+    bool PreserveAtime;
     wchar CompressStdin[NM];
 
     uint Threads; // We use it to init hash even if RAR_SMP is not defined.
diff --git a/third_party/unrar/src/os.hpp b/third_party/unrar/src/os.hpp
index 707d604..51d547b 100644
--- a/third_party/unrar/src/os.hpp
+++ b/third_party/unrar/src/os.hpp
@@ -140,7 +140,7 @@
 
 #ifdef _UNIX
 
-#define  NM  2048
+#define NM  2048
 
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/third_party/unrar/src/pathfn.cpp b/third_party/unrar/src/pathfn.cpp
index cb1d7edf..41594bf9 100644
--- a/third_party/unrar/src/pathfn.cpp
+++ b/third_party/unrar/src/pathfn.cpp
@@ -170,14 +170,17 @@
 void AddEndSlash(wchar *Path,size_t MaxLength)
 {
   size_t Length=wcslen(Path);
-  if (Length>0 && Path[Length-1]!=CPATHDIVIDER)
-    wcsncatz(Path,SPATHDIVIDER,MaxLength);
+  if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1<MaxLength)
+  {
+    Path[Length]=CPATHDIVIDER;
+    Path[Length+1]=0;
+  }
 }
 
 
 void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize)
 {
-  // 'Name' and 'Pathname' can point to same memory area. This is why we use
+  // 'Path', 'Name' and 'Pathname' can point to same memory area. So we use
   // the temporary buffer instead of constructing the name in 'Pathname'.
   wchar OutName[NM];
   wcsncpyz(OutName,Path,ASIZE(OutName));
@@ -652,7 +655,7 @@
   }
   if (!FileExist(FirstName))
   {
-    // If the first volume, which name we just generated, is not exist,
+    // If the first volume, which name we just generated, does not exist,
     // check if volume with same name and any other extension is available.
     // It can help in case of *.exe or *.sfx first volume.
     wchar Mask[NM];
diff --git a/third_party/unrar/src/qopen.cpp b/third_party/unrar/src/qopen.cpp
index 89a83b3..43346b0 100644
--- a/third_party/unrar/src/qopen.cpp
+++ b/third_party/unrar/src/qopen.cpp
@@ -67,7 +67,7 @@
     SeekPos=Arc->Tell();
     UnsyncSeekPos=false;
 
-    SaveFilePos SavePos(*Arc);
+    int64 SavePos=SeekPos;
     Arc->Seek(BlockPos,SEEK_SET);
 
     // If BlockPos points to original main header, we'll have the infinite
@@ -83,10 +83,14 @@
 
     if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
         !Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
+    {
+      Arc->Seek(SavePos,SEEK_SET);
       return;
+    }
     QOHeaderPos=Arc->CurBlockPos;
     RawDataStart=Arc->Tell();
     RawDataSize=Arc->SubHead.UnpSize;
+    Arc->Seek(SavePos,SEEK_SET);
 
     Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader.
   }
@@ -201,22 +205,28 @@
 
 uint QuickOpen::ReadBuffer()
 {
-  SaveFilePos SavePos(*Arc);
+  int64 SavePos=Arc->Tell();
   Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
   size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
   if (Arc->SubHead.Encrypted)
     SizeToRead &= ~CRYPT_BLOCK_MASK;
-  if (SizeToRead==0)
-    return 0;
-  int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
-  if (ReadSize<=0)
-    return 0;
+  int ReadSize=0;
+  if (SizeToRead!=0)
+  {
+    ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
+    if (ReadSize<=0)
+      ReadSize=0;
+    else
+    {
 #ifndef RAR_NOCRYPT
-  if (Arc->SubHead.Encrypted)
-    Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
+      if (Arc->SubHead.Encrypted)
+        Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
 #endif
-  RawDataPos+=ReadSize;
-  ReadBufSize+=ReadSize;
+      RawDataPos+=ReadSize;
+      ReadBufSize+=ReadSize;
+    }
+  }
+  Arc->Seek(SavePos,SEEK_SET);
   return ReadSize;
 }
 
diff --git a/third_party/unrar/src/rar.hpp b/third_party/unrar/src/rar.hpp
index 65e04967..3f7414c 100644
--- a/third_party/unrar/src/rar.hpp
+++ b/third_party/unrar/src/rar.hpp
@@ -39,7 +39,6 @@
 #include "filestr.hpp"
 #include "find.hpp"
 #include "scantree.hpp"
-#include "savepos.hpp"
 #include "getbits.hpp"
 #include "rdwrfn.hpp"
 #ifdef USE_QOPEN
@@ -77,6 +76,9 @@
 
 #include "rs.hpp"
 #include "rs16.hpp"
+
+
+
 #include "recvol.hpp"
 #include "volume.hpp"
 #include "smallfn.hpp"
diff --git a/third_party/unrar/src/rartypes.hpp b/third_party/unrar/src/rartypes.hpp
index 1ec97c9..3d3111b 100644
--- a/third_party/unrar/src/rartypes.hpp
+++ b/third_party/unrar/src/rartypes.hpp
@@ -21,15 +21,12 @@
 // Maximum int64 value.
 #define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff))
 
-// Special int64 value, large enough to never be found in real life.
+// Special int64 value, large enough to never be found in real life
+// and small enough to fit to both signed and unsigned 64-bit ints.
 // We use it in situations, when we need to indicate that parameter 
 // is not defined and probably should be calculated inside of function.
 // Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it 
-// compatible with 32 bit int64.
+// compatible with 32 bit int64 if 64 bit type is not supported.
 #define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
 
-// Maximum uint64 value.
-#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff)
-#define UINT64NDF MAX_UINT64
-
 #endif
diff --git a/third_party/unrar/src/rdwrfn.hpp b/third_party/unrar/src/rdwrfn.hpp
index 070010ea..fc38fd3 100644
--- a/third_party/unrar/src/rdwrfn.hpp
+++ b/third_party/unrar/src/rdwrfn.hpp
@@ -3,6 +3,7 @@
 
 class CmdAdd;
 class Unpack;
+class ArcFileSearch;
 
 #if 0
 // We use external i/o calls for Benchmark command.
diff --git a/third_party/unrar/src/recvol.cpp b/third_party/unrar/src/recvol.cpp
index 166eef4..adf5840 100644
--- a/third_party/unrar/src/recvol.cpp
+++ b/third_party/unrar/src/recvol.cpp
@@ -31,12 +31,12 @@
   // handling exceptions. So it can close and delete files on Cancel.
   if (Fmt==RARFMT15)
   {
-    RecVolumes3 RecVol(false);
+    RecVolumes3 RecVol(Cmd,false);
     return RecVol.Restore(Cmd,Name,Silent);
   }
   else
   {
-    RecVolumes5 RecVol(false);
+    RecVolumes5 RecVol(Cmd,false);
     return RecVol.Restore(Cmd,Name,Silent);
   }
 }
@@ -100,12 +100,12 @@
   RevFile.Close();
   if (Rev5)
   {
-    RecVolumes5 RecVol(true);
+    RecVolumes5 RecVol(Cmd,true);
     RecVol.Test(Cmd,Name);
   }
   else
   {
-    RecVolumes3 RecVol(true);
+    RecVolumes3 RecVol(Cmd,true);
     RecVol.Test(Cmd,Name);
   }
 }
diff --git a/third_party/unrar/src/recvol.hpp b/third_party/unrar/src/recvol.hpp
index 7f2f1adb..06510a2 100644
--- a/third_party/unrar/src/recvol.hpp
+++ b/third_party/unrar/src/recvol.hpp
@@ -14,7 +14,7 @@
     ThreadPool *RSThreadPool;
 #endif
   public:
-    RecVolumes3(bool TestOnly);
+    RecVolumes3(RAROptions *Cmd,bool TestOnly);
     ~RecVolumes3();
     void Make(RAROptions *Cmd,wchar *ArcName);
     bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
@@ -71,11 +71,12 @@
 #ifdef RAR_SMP
     ThreadPool *RecThreadPool;
 #endif
-    RecRSThreadData ThreadData[MaxPoolThreads]; // Store thread parameters.
+    uint MaxUserThreads; // Maximum number of threads defined by user.
+    RecRSThreadData *ThreadData; // Array to store thread parameters.
   public: // 'public' only because called from thread functions.
     void ProcessAreaRS(RecRSThreadData *td);
   public:
-    RecVolumes5(bool TestOnly);
+    RecVolumes5(RAROptions *Cmd,bool TestOnly);
     ~RecVolumes5();
     bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
     void Test(RAROptions *Cmd,const wchar *Name);
diff --git a/third_party/unrar/src/recvol3.cpp b/third_party/unrar/src/recvol3.cpp
index 51776d40..9fb846a 100644
--- a/third_party/unrar/src/recvol3.cpp
+++ b/third_party/unrar/src/recvol3.cpp
@@ -36,7 +36,7 @@
 }
 #endif
 
-RecVolumes3::RecVolumes3(bool TestOnly)
+RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
 {
   memset(SrcFile,0,sizeof(SrcFile));
   if (TestOnly)
@@ -50,7 +50,7 @@
     Buf.Alloc(TotalBufferSize);
     memset(SrcFile,0,sizeof(SrcFile));
 #ifdef RAR_SMP
-    RSThreadPool=CreateThreadPool();
+    RSThreadPool=new ThreadPool(Cmd->Threads);
 #endif
   }
 }
@@ -61,7 +61,7 @@
   for (size_t I=0;I<ASIZE(SrcFile);I++)
     delete SrcFile[I];
 #ifdef RAR_SMP
-  DestroyThreadPool(RSThreadPool);
+  delete RSThreadPool;
 #endif
 }
 
@@ -363,11 +363,10 @@
 
 #ifdef RAR_SMP
   uint ThreadNumber=Cmd->Threads;
-  RSEncode rse[MaxPoolThreads];
 #else
   uint ThreadNumber=1;
-  RSEncode rse[1];
 #endif
+  RSEncode *rse=new RSEncode[ThreadNumber];
   for (uint I=0;I<ThreadNumber;I++)
     rse[I].Init(RecVolNumber);
 
@@ -438,6 +437,8 @@
       if (WriteFlags[I])
         SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
   }
+  delete[] rse;
+
   for (int I=0;I<RecVolNumber+FileNumber;I++)
     if (SrcFile[I]!=NULL)
     {
diff --git a/third_party/unrar/src/recvol5.cpp b/third_party/unrar/src/recvol5.cpp
index a0e5b19..3c524d8 100644
--- a/third_party/unrar/src/recvol5.cpp
+++ b/third_party/unrar/src/recvol5.cpp
@@ -1,6 +1,6 @@
 static const uint MaxVolumes=65535;
 
-RecVolumes5::RecVolumes5(bool TestOnly)
+RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly)
 {
   RealBuf=NULL;
   RealReadBuffer=NULL;
@@ -10,7 +10,14 @@
   TotalCount=0;
   RecBufferSize=0;
 
-  for (uint I=0;I<ASIZE(ThreadData);I++)
+#ifdef RAR_SMP
+  MaxUserThreads=Cmd->Threads;
+#else
+  MaxUserThreads=1;
+#endif
+
+  ThreadData=new RecRSThreadData[MaxUserThreads];
+  for (uint I=0;I<MaxUserThreads;I++)
   {
     ThreadData[I].RecRSPtr=this;
     ThreadData[I].RS=NULL;
@@ -25,7 +32,7 @@
   else
   {
 #ifdef RAR_SMP
-    RecThreadPool=CreateThreadPool();
+    RecThreadPool=new ThreadPool(MaxUserThreads);
 #endif
     RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT];
     Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT);
@@ -39,10 +46,11 @@
   delete[] RealReadBuffer;
   for (uint I=0;I<RecItems.Size();I++)
     delete RecItems[I].f;
-  for (uint I=0;I<ASIZE(ThreadData);I++)
+  for (uint I=0;I<MaxUserThreads;I++)
     delete ThreadData[I].RS;
+  delete[] ThreadData;
 #ifdef RAR_SMP
-  DestroyThreadPool(RecThreadPool);
+  delete RecThreadPool;
 #endif
 }
 
@@ -68,11 +76,7 @@
     RS.UpdateECC(DataNum, I, Data, Buf+I*RecBufferSize, MaxRead);
 */
 
-#ifdef RAR_SMP
-  uint ThreadNumber=Cmd->Threads;
-#else
-  uint ThreadNumber=1;
-#endif
+  uint ThreadNumber=MaxUserThreads;
 
   const uint MinThreadBlock=0x1000;
   ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock);
@@ -238,7 +242,7 @@
       uiMsg(UIMSG_STRING,Item->Name);
 
       uint RevCRC;
-      CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS);
+      CalcFileSum(Item->f,&RevCRC,NULL,MaxUserThreads,INT64NDF,CALCFSUM_CURPOS);
       Item->Valid=RevCRC==Item->CRC;
       if (!Item->Valid)
       {
diff --git a/third_party/unrar/src/resource.cpp b/third_party/unrar/src/resource.cpp
index 2eec79c7..dadd072 100644
--- a/third_party/unrar/src/resource.cpp
+++ b/third_party/unrar/src/resource.cpp
@@ -2,8 +2,10 @@
 
 
 
+
+
 #ifndef RARDLL
-const wchar *St(MSGID StringId)
+const wchar* St(MSGID StringId)
 {
   return StringId;
 }
diff --git a/third_party/unrar/src/rijndael.cpp b/third_party/unrar/src/rijndael.cpp
index ba29c910..dd19750a 100644
--- a/third_party/unrar/src/rijndael.cpp
+++ b/third_party/unrar/src/rijndael.cpp
@@ -75,8 +75,14 @@
   // Check SSE here instead of constructor, so if object is a part of some
   // structure memset'ed before use, this variable is not lost.
   int CPUInfo[4];
-  __cpuid(CPUInfo, 1);
-  AES_NI=(CPUInfo[2] & 0x2000000)!=0;
+  __cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
+  if ((CPUInfo[0] & 0x7fffffff)>=1)
+  {
+    __cpuid(CPUInfo, 1);
+    AES_NI=(CPUInfo[2] & 0x2000000)!=0;
+  }
+  else
+    AES_NI=0;
 #endif
 
   // Other developers asked us to initialize it to suppress "may be used
diff --git a/third_party/unrar/src/savepos.hpp b/third_party/unrar/src/savepos.hpp
index 10a0664..1f8353f6 100644
--- a/third_party/unrar/src/savepos.hpp
+++ b/third_party/unrar/src/savepos.hpp
@@ -14,13 +14,26 @@
     }
     ~SaveFilePos()
     {
-      // If file is already closed by current exception processing,
-      // we would get uneeded error messages and an exception inside of
-      // exception and terminate if we try to seek without checking
-      // if file is still opened. We should not also restore the position
-      // if external code closed the file on purpose.
+      // Unless the file is already closed either by current exception
+      // processing or intentionally by external code.
       if (SaveFile->IsOpened())
-        SaveFile->Seek(SavePos,SEEK_SET);
+      {
+        try
+        {
+          SaveFile->Seek(SavePos,SEEK_SET);
+        }
+        catch(RAR_EXIT)
+        {
+          // Seek() can throw an exception and it terminates process
+          // if we are already processing another exception. Also in C++ 11
+          // an exception in destructor always terminates process unless
+          // we mark destructor with noexcept(false). So we do not want to
+          // throw here. To prevent data loss we do not want to continue
+          // execution after seek error, so we close the file.
+          // Any next access to this file will return an error.
+          SaveFile->Close();
+        }
+      }
     }
 };
 
diff --git a/third_party/unrar/src/strfn.cpp b/third_party/unrar/src/strfn.cpp
index 6545f0a..8904b90 100644
--- a/third_party/unrar/src/strfn.cpp
+++ b/third_party/unrar/src/strfn.cpp
@@ -241,8 +241,8 @@
 
 bool LowAscii(const char *Str)
 {
-  for (int I=0;Str[I]!=0;I++)
-    if ((byte)Str[I]<32 || (byte)Str[I]>127)
+  for (size_t I=0;Str[I]!=0;I++)
+    if (/*(byte)Str[I]<32 || */(byte)Str[I]>127)
       return false;
   return true;
 }
@@ -250,11 +250,11 @@
 
 bool LowAscii(const wchar *Str)
 {
-  for (int I=0;Str[I]!=0;I++)
+  for (size_t I=0;Str[I]!=0;I++)
   {
     // We convert wchar_t to uint just in case if some compiler
     // uses signed wchar_t.
-    if ((uint)Str[I]<32 || (uint)Str[I]>127)
+    if (/*(uint)Str[I]<32 || */(uint)Str[I]>127)
       return false;
   }
   return true;
diff --git a/third_party/unrar/src/system.cpp b/third_party/unrar/src/system.cpp
index c13c81e..4ae2b89 100644
--- a/third_party/unrar/src/system.cpp
+++ b/third_party/unrar/src/system.cpp
@@ -187,18 +187,29 @@
 SSE_VERSION GetSSEVersion()
 {
   int CPUInfo[4];
-  __cpuid(CPUInfo, 7);
-  if ((CPUInfo[1] & 0x20)!=0)
-    return SSE_AVX2;
-  __cpuid(CPUInfo, 1);
-  if ((CPUInfo[2] & 0x80000)!=0)
-    return SSE_SSE41;
-  if ((CPUInfo[2] & 0x200)!=0)
-    return SSE_SSSE3;
-  if ((CPUInfo[3] & 0x4000000)!=0)
-    return SSE_SSE2;
-  if ((CPUInfo[3] & 0x2000000)!=0)
-    return SSE_SSE;
+  __cpuid(CPUInfo, 0x80000000);
+
+  // Maximum supported cpuid function. For example, Pentium M 755 returns 4 here.
+  uint MaxSupported=CPUInfo[0] & 0x7fffffff;
+
+  if (MaxSupported>=7)
+  {
+    __cpuid(CPUInfo, 7);
+    if ((CPUInfo[1] & 0x20)!=0)
+      return SSE_AVX2;
+  }
+  if (MaxSupported>=1)
+  {
+    __cpuid(CPUInfo, 1);
+    if ((CPUInfo[2] & 0x80000)!=0)
+      return SSE_SSE41;
+    if ((CPUInfo[2] & 0x200)!=0)
+      return SSE_SSSE3;
+    if ((CPUInfo[3] & 0x4000000)!=0)
+      return SSE_SSE2;
+    if ((CPUInfo[3] & 0x2000000)!=0)
+      return SSE_SSE;
+  }
   return SSE_NONE;
 }
 #endif
diff --git a/third_party/unrar/src/threadmisc.cpp b/third_party/unrar/src/threadmisc.cpp
index 9dfd2b9..742eda4 100644
--- a/third_party/unrar/src/threadmisc.cpp
+++ b/third_party/unrar/src/threadmisc.cpp
@@ -1,7 +1,3 @@
-// Typically we use the same global thread pool for all RAR modules.
-static ThreadPool *GlobalPool=NULL;
-static uint GlobalPoolUseCount=0;
-
 static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection)
 {
 #ifdef _WIN_ALL
@@ -43,62 +39,6 @@
 }
 
 
-struct GlobalPoolCreateSync
-{
-  CRITSECT_HANDLE CritSection;
-  GlobalPoolCreateSync()  { CriticalSectionCreate(&CritSection); }
-  ~GlobalPoolCreateSync() { CriticalSectionDelete(&CritSection); }
-};
-
-static GlobalPoolCreateSync& GetPoolCreateSync() {
-  static GlobalPoolCreateSync PoolCreateSync;
-  return PoolCreateSync;
-}
-
-
-ThreadPool* CreateThreadPool()
-{
-  CriticalSectionStart(&(GetPoolCreateSync().CritSection));
-
-  if (GlobalPoolUseCount++ == 0)
-    GlobalPool=new ThreadPool(MaxPoolThreads);
-
-  // We use a simple thread pool, which does not allow to add tasks from
-  // different functions and threads in the same time. It is ok for RAR,
-  // but UnRAR.dll can be used in multithreaded environment. So if one of
-  // threads requests a copy of global pool and another copy is already
-  // in use, we create and return a new pool instead of existing global.
-  if (GlobalPoolUseCount > 1)
-  {
-    ThreadPool *Pool = new ThreadPool(MaxPoolThreads);
-    CriticalSectionEnd(&(GetPoolCreateSync().CritSection));
-    return Pool;
-  }
-
-  CriticalSectionEnd(&(GetPoolCreateSync().CritSection));
-  return GlobalPool;
-}
-
-
-void DestroyThreadPool(ThreadPool *Pool)
-{
-  if (Pool!=NULL)
-  {
-    CriticalSectionStart(&(GetPoolCreateSync().CritSection));
-
-    if (Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0)
-      delete GlobalPool;
-
-    // To correctly work in multithreaded environment UnRAR.dll creates
-    // new pools if global pool is already in use. We delete such pools here.
-    if (Pool!=GlobalPool)
-      delete Pool;
-
-    CriticalSectionEnd(&(GetPoolCreateSync().CritSection));
-  }
-}
-
-
 static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data)
 {
 #ifdef _UNIX
diff --git a/third_party/unrar/src/threadpool.cpp b/third_party/unrar/src/threadpool.cpp
index 732dd75..8c63a8b 100644
--- a/third_party/unrar/src/threadpool.cpp
+++ b/third_party/unrar/src/threadpool.cpp
@@ -170,12 +170,13 @@
     CreateThreads();
   
   // If queue is full, wait until it is empty.
-  if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom)
+  if (ActiveThreads>=ASIZE(TaskQueue))
     WaitDone();
 
   TaskQueue[QueueTop].Proc = Proc;
   TaskQueue[QueueTop].Param = Data;
   QueueTop = (QueueTop + 1) % ASIZE(TaskQueue);
+  ActiveThreads++;
 }
 
 
@@ -184,9 +185,6 @@
 // are sleeping yet.
 void ThreadPool::WaitDone()
 {
-  // We add ASIZE(TaskQueue) for case if TaskQueue array size is not
-  // a power of two. Negative numbers would not suit our purpose here.
-  ActiveThreads=(QueueTop+ASIZE(TaskQueue)-QueueBottom) % ASIZE(TaskQueue);
   if (ActiveThreads==0)
     return;
 #ifdef _WIN_ALL
diff --git a/third_party/unrar/src/threadpool.hpp b/third_party/unrar/src/threadpool.hpp
index dc45ca0..85ed90d 100644
--- a/third_party/unrar/src/threadpool.hpp
+++ b/third_party/unrar/src/threadpool.hpp
@@ -4,7 +4,10 @@
 #ifndef RAR_SMP
 const uint MaxPoolThreads=1; // For single threaded version.
 #else
-const uint MaxPoolThreads=32;
+// We need to use the processor groups API to increase it beyond 64.
+// Also be sure to check and adjust if needed per thread and total block size
+// when compressing if going above 64.
+const uint MaxPoolThreads=64;
 
 
 #ifdef _UNIX
@@ -98,9 +101,6 @@
 #endif
 };
 
-ThreadPool* CreateThreadPool();
-void DestroyThreadPool(ThreadPool *Pool);
-
 #endif // RAR_SMP
 
 #endif // _RAR_THREADPOOL_
diff --git a/third_party/unrar/src/ui.hpp b/third_party/unrar/src/ui.hpp
index 69ce2a5..2654387c 100644
--- a/third_party/unrar/src/ui.hpp
+++ b/third_party/unrar/src/ui.hpp
@@ -20,7 +20,7 @@
   UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD,
   UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR,
   UIERROR_NOTSFX, UIERROR_OLDTOSFX,
-  UIERROR_WRONGSFXVER, UIERROR_ALREADYENC, UIERROR_DICTOUTMEM,
+  UIERROR_WRONGSFXVER, UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM,
   UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD,
   UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME,
   UIERROR_NOTFIRSTVOLUME, UIERROR_RECVOLLIMIT, UIERROR_RECVOLDIFFSETS,
@@ -38,6 +38,8 @@
   UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, UIERROR_UOWNERGET,
   UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID,
   UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST,
+  UIERROR_OPENPRESERVEATIME, UIERROR_READERRTRUNCATED, UIERROR_READERRCOUNT,
+  UIERROR_DIRNAMEEXISTS,
 
   UIMSG_FIRST,
   UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA,
@@ -91,16 +93,18 @@
 enum UIALARM_TYPE {UIALARM_ERROR, UIALARM_INFO, UIALARM_QUESTION};
 void uiAlarm(UIALARM_TYPE Type);
 
+void uiEolAfterMsg();
 
 bool uiAskNextVolume(wchar *VolName,size_t MaxSize);
-bool uiAskRepeatRead(const wchar *FileName);
+#if !defined(SILENT) && !defined(SFX_MODULE)
+void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit);
+#endif
 bool uiAskRepeatWrite(const wchar *FileName,bool DiskFull);
 
 #ifndef SFX_MODULE
 const wchar *uiGetMonthName(int Month);
 #endif
 
-
 class uiMsgStore
 {
   private:
diff --git a/third_party/unrar/src/uiconsole.cpp b/third_party/unrar/src/uiconsole.cpp
index 3f4c654..f29ca47 100644
--- a/third_party/unrar/src/uiconsole.cpp
+++ b/third_party/unrar/src/uiconsole.cpp
@@ -1,3 +1,5 @@
+static bool AnyMessageDisplayed=0; // For console -idn switch.
+
 // Purely user interface function. Gets and returns user input.
 UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags)
 {
@@ -83,6 +85,8 @@
 
 void uiMsgStore::Msg()
 {
+  AnyMessageDisplayed=true;
+
   switch(Code)
   {
     case UIERROR_SYSERRMSG:
@@ -99,6 +103,8 @@
       Log(Str[0],St(MDataBadCRC),Str[1],Str[0]);
       break;
     case UIERROR_BADPSW:
+      Log(Str[0],St(MWrongFilePassword),Str[1]);
+      break;
     case UIWAIT_BADPSW:
       Log(Str[0],St(MWrongPassword));
       break;
@@ -119,6 +125,7 @@
       Log(NULL,St(MErrSeek),Str[0]);
       break;
     case UIERROR_FILEREAD:
+      mprintf(L"\n");
       Log(Str[0],St(MErrRead),Str[1]);
       break;
     case UIERROR_FILEWRITE:
@@ -302,7 +309,15 @@
     case UIERROR_ULINKEXIST:
       Log(NULL,St(MSymLinkExists),Str[0]);
       break;
-
+    case UIERROR_READERRTRUNCATED:
+      Log(NULL,St(MErrReadTrunc),Str[0]);
+      break;
+    case UIERROR_READERRCOUNT:
+      Log(NULL,St(MErrReadCount),Num[0]);
+      break;
+    case UIERROR_DIRNAMEEXISTS:
+      Log(NULL,St(MDirNameExists));
+      break;
 
 #ifndef SFX_MODULE
     case UIMSG_STRING:
@@ -395,11 +410,15 @@
 }
 
 
-bool uiAskRepeatRead(const wchar *FileName)
+void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit)
 {
-  mprintf(L"\n");
-  Log(NULL,St(MErrRead),FileName);
-  return Ask(St(MRetryAbort))==1;
+  eprintf(St(MErrReadInfo));
+  int Code=Ask(St(MIgnoreAllRetryQuit));
+
+  Ignore=(Code==1);
+  All=(Code==2);
+  Quit=(Code==4);
+  Retry=!Ignore && !All && !Quit; // Default also for invalid input, not just for 'Retry'.
 }
 
 
@@ -421,3 +440,15 @@
   return St(MonthID[Month]);
 }
 #endif
+
+
+void uiEolAfterMsg()
+{
+  if (AnyMessageDisplayed)
+  {
+    // Avoid deleting several last characters of any previous error message
+    // with percentage indicator in -idn mode.
+    AnyMessageDisplayed=false;
+    mprintf(L"\n");
+  }
+}
diff --git a/third_party/unrar/src/uisilent.cpp b/third_party/unrar/src/uisilent.cpp
index 1b5de13d..1df09756 100644
--- a/third_party/unrar/src/uisilent.cpp
+++ b/third_party/unrar/src/uisilent.cpp
@@ -67,3 +67,8 @@
   return L"";
 }
 #endif
+
+
+void uiEolAfterMsg()
+{
+}
diff --git a/third_party/unrar/src/unicode.cpp b/third_party/unrar/src/unicode.cpp
index b2015b8..48d7bb2f 100644
--- a/third_party/unrar/src/unicode.cpp
+++ b/third_party/unrar/src/unicode.cpp
@@ -1,7 +1,7 @@
 #include "rar.hpp"
 #define MBFUNCTIONS
 
-#if !defined(_WIN_ALL) && !defined(_APPLE) && defined(_UNIX) && defined(MBFUNCTIONS)
+#if defined(_UNIX) && defined(MBFUNCTIONS)
 
 static bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success);
 static void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success);
@@ -30,7 +30,7 @@
 #elif defined(_APPLE)
   WideToUtf(Src,Dest,DestSize);
 
-#elif defined(_UNIX) && defined(MBFUNCTIONS)
+#elif defined(MBFUNCTIONS)
   if (!WideToCharMap(Src,Dest,DestSize,RetCode))
   {
     mbstate_t ps; // Use thread safe external state based functions.
@@ -95,7 +95,7 @@
 #elif defined(_APPLE)
   UtfToWide(Src,Dest,DestSize);
 
-#elif defined(_UNIX) && defined(MBFUNCTIONS)
+#elif defined(MBFUNCTIONS)
   mbstate_t ps;
   memset (&ps, 0, sizeof(ps));
   const char *SrcParam=Src; // mbsrtowcs can change the pointer.
@@ -128,8 +128,8 @@
 }
 
 
-#if !defined(_WIN_ALL) && !defined(_APPLE) && defined(_UNIX) && defined(MBFUNCTIONS)
-// Convert and restore mapped inconvertible Unicode characters.
+#if defined(_UNIX) && defined(MBFUNCTIONS)
+// Convert and restore mapped inconvertible Unicode characters. 
 // We use it for extended ASCII names in Unix.
 bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success)
 {
@@ -142,7 +142,7 @@
   // can produce uninitilized output while reporting success on garbage input.
   // So we clean the destination to calm analyzers.
   memset(Dest,0,DestSize);
-
+  
   Success=true;
   uint SrcPos=0,DestPos=0;
   while (Src[SrcPos]!=0 && DestPos<DestSize-MB_CUR_MAX)
@@ -177,7 +177,7 @@
 #endif
 
 
-#if !defined(_WIN_ALL) && !defined(_APPLE) && defined(_UNIX) && defined(MBFUNCTIONS)
+#if defined(_UNIX) && defined(MBFUNCTIONS)
 // Convert and map inconvertible Unicode characters.
 // We use it for extended ASCII names in Unix.
 void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success)
@@ -471,6 +471,7 @@
 }
 
 
+// Case insensitive wcsstr().
 const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search)
 {
   for (size_t i=0;str[i]!=0;i++)
@@ -489,6 +490,8 @@
 wchar* wcslower(wchar *s)
 {
 #ifdef _WIN_ALL
+  // _wcslwr requires setlocale and we do not want to depend on setlocale
+  // in Windows. Also CharLower involves less overhead.
   CharLower(s);
 #else
   for (wchar *c=s;*c!=0;c++)
@@ -503,6 +506,8 @@
 wchar* wcsupper(wchar *s)
 {
 #ifdef _WIN_ALL
+  // _wcsupr requires setlocale and we do not want to depend on setlocale
+  // in Windows. Also CharUpper involves less overhead.
   CharUpper(s);
 #else
   for (wchar *c=s;*c!=0;c++)
@@ -520,8 +525,9 @@
 #if defined(_WIN_ALL)
   // CharUpper is more reliable than towupper in Windows, which seems to be
   // C locale dependent even in Unicode version. For example, towupper failed
-  // to convert lowercase Russian characters.
-  return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)ch);
+  // to convert lowercase Russian characters. Use 0xffff mask to prevent crash
+  // if value larger than 0xffff is passed to this function.
+  return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)(ch&0xffff));
 #else
   return towupper(ch);
 #endif
@@ -532,8 +538,9 @@
 {
 #if defined(_WIN_ALL)
   // CharLower is more reliable than towlower in Windows.
-  // See comment for towupper above.
-  return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)ch);
+  // See comment for towupper above. Use 0xffff mask to prevent crash
+  // if value larger than 0xffff is passed to this function.
+  return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)(ch&0xffff));
 #else
   return towlower(ch);
 #endif
@@ -652,3 +659,5 @@
   return((char *)found);
 }
 #endif
+
+
diff --git a/third_party/unrar/src/unicode.hpp b/third_party/unrar/src/unicode.hpp
index 0efb4c91..c66cc95a 100644
--- a/third_party/unrar/src/unicode.hpp
+++ b/third_party/unrar/src/unicode.hpp
@@ -62,4 +62,5 @@
 inline void copychrd(char *dest,const char *src) {*dest=*src;}
 #endif
 
+
 #endif
diff --git a/third_party/unrar/src/unpack.cpp b/third_party/unrar/src/unpack.cpp
index ca3c52e..7f579ff0 100644
--- a/third_party/unrar/src/unpack.cpp
+++ b/third_party/unrar/src/unpack.cpp
@@ -32,7 +32,7 @@
   UnpSomeRead=false;
 #ifdef RAR_SMP
   MaxUserThreads=1;
-  UnpThreadPool=CreateThreadPool();
+  UnpThreadPool=NULL;
   ReadBufMT=NULL;
   UnpThreadData=NULL;
 #endif
@@ -58,13 +58,24 @@
   if (Window!=NULL)
     free(Window);
 #ifdef RAR_SMP
-  DestroyThreadPool(UnpThreadPool);
+  delete UnpThreadPool;
   delete[] ReadBufMT;
   delete[] UnpThreadData;
 #endif
 }
 
 
+#ifdef RAR_SMP
+void Unpack::SetThreads(uint Threads)
+{
+  // More than 8 threads are unlikely to provide noticeable gain
+  // for unpacking, but would use the additional memory.
+  MaxUserThreads=Min(Threads,8);
+  UnpThreadPool=new ThreadPool(MaxUserThreads);
+}
+#endif
+
+
 void Unpack::Init(size_t WinSize,bool Solid)
 {
   // If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size
diff --git a/third_party/unrar/src/unpack.hpp b/third_party/unrar/src/unpack.hpp
index ec5d688b..75dadb0 100644
--- a/third_party/unrar/src/unpack.hpp
+++ b/third_party/unrar/src/unpack.hpp
@@ -24,7 +24,7 @@
 #define MAX_FILTER_BLOCK_SIZE 0x400000
 
 // Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE,
-// so we keep number of buffered filter in unpacker reasonable.
+// so we keep a number of buffered filters in unpacker reasonable.
 #define UNPACK_MAX_WRITE      0x400000
 
 // Decode compressed bit fields to alphabet numbers.
@@ -382,10 +382,7 @@
     void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
 
 #ifdef RAR_SMP
-    // More than 8 threads are unlikely to provide a noticeable gain
-    // for unpacking, but would use the additional memory.
-    void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
-
+    void SetThreads(uint Threads);
     void UnpackDecode(UnpackThreadData &D);
 #endif
 
diff --git a/third_party/unrar/src/unpack50.cpp b/third_party/unrar/src/unpack50.cpp
index ec60c82..9911950 100644
--- a/third_party/unrar/src/unpack50.cpp
+++ b/third_party/unrar/src/unpack50.cpp
@@ -436,6 +436,10 @@
       }
       return SrcData;
     case FILTER_ARM:
+      // 2019-11-15: we turned off ARM filter by default when compressing,
+      // mostly because it is inefficient for modern 64 bit ARM binaries.
+      // It was turned on by default in 5.0 - 5.80b3 , so we still need it
+      // here for compatibility with some of previously created archives.
       {
         uint FileOffset=(uint)WrittenFileSize;
         // DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3"
diff --git a/third_party/unrar/src/version.hpp b/third_party/unrar/src/version.hpp
index de774ff..99e7cae 100644
--- a/third_party/unrar/src/version.hpp
+++ b/third_party/unrar/src/version.hpp
@@ -1,6 +1,6 @@
-#define RARVER_MAJOR     5
-#define RARVER_MINOR    70
+#define RARVER_MAJOR     6
+#define RARVER_MINOR     0
 #define RARVER_BETA      0
-#define RARVER_DAY      25
-#define RARVER_MONTH     2
-#define RARVER_YEAR   2019
+#define RARVER_DAY       1
+#define RARVER_MONTH    12
+#define RARVER_YEAR   2020
diff --git a/third_party/unrar/src/win32acl.cpp b/third_party/unrar/src/win32acl.cpp
index 6bc865b..d4797bde 100644
--- a/third_party/unrar/src/win32acl.cpp
+++ b/third_party/unrar/src/win32acl.cpp
@@ -67,7 +67,7 @@
 void ExtractACL(Archive &Arc,const wchar *FileName)
 {
   Array<byte> SubData;
-  if (!Arc.ReadSubData(&SubData,NULL))
+  if (!Arc.ReadSubData(&SubData,NULL,false))
     return;
 
   SetACLPrivileges();
diff --git a/third_party/unrar/src/win32stm.cpp b/third_party/unrar/src/win32stm.cpp
index 54b872e..eaa43be 100644
--- a/third_party/unrar/src/win32stm.cpp
+++ b/third_party/unrar/src/win32stm.cpp
@@ -104,7 +104,8 @@
 
   if (TestMode)
   {
-    Arc.ReadSubData(NULL,NULL);
+    File CurFile;
+    Arc.ReadSubData(NULL,&CurFile,true);
     return;
   }
 
@@ -116,7 +117,7 @@
   if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0)
     SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);
   File CurFile;
-  if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile))
+  if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile,false))
     CurFile.Close();
   File HostFile;
   if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE))
diff --git a/third_party/zlib/google/zip_internal.cc b/third_party/zlib/google/zip_internal.cc
index 9cbb78c..354fbf8 100644
--- a/third_party/zlib/google/zip_internal.cc
+++ b/third_party/zlib/google/zip_internal.cc
@@ -56,10 +56,10 @@
     creation_disposition = CREATE_ALWAYS;
   }
 
-  base::string16 filename16 = base::UTF8ToUTF16(filename);
+  std::wstring filenamew = base::UTF8ToWide(filename);
   if ((filename != NULL) && (desired_access != 0)) {
-    file = CreateFile(filename16.c_str(), desired_access, share_mode,
-        NULL, creation_disposition, flags_and_attributes, NULL);
+    file = CreateFile(filenamew.c_str(), desired_access, share_mode, NULL,
+                      creation_disposition, flags_and_attributes, NULL);
   }
 
   if (file == INVALID_HANDLE_VALUE)
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
index 53ff73f..f1322ff2 100644
--- a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
+++ b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
@@ -120,6 +120,24 @@
 courgette::LabelManagerTest_SimpleIndexAssigner_Test::TestBody()::TestCase::expect_backward
 courgette::LabelManagerTest_SimpleIndexAssigner_Test::TestBody()::TestCase::expect_in
 
+# Populated manually - uninitialized memory reinterpret_cast to CheckedPtr
+# causing AddRef/Deref mismatch.
+sandbox::(anonymous namespace)::_HEAP_32::Heap
+sandbox::(anonymous namespace)::_HEAP_64::Heap
+sql::SandboxedVfsFileSqliteBridge::sandboxed_vfs_file
+sandbox::SharedMemIPCServer::client_control_
+sandbox::SharedMemIPCServer::thread_provider_
+sandbox::SharedMemIPCServer::call_dispatcher_
+
+# Populated manually - pointing past the end of a non-PA allocation might point
+# to PA memory
+cc::PaintOpWriter::memory_ # https://crbug.com/1169579
+
+# Populated manually - pointer to stale non-PA allocation could be confused as a
+# pointer to PA memory when that address space is reused
+base::PersistentMemoryAllocator::mem_base_ # https://crbug.com/1169582
+base::SharedMemoryMapping::memory_ # https://crbug.com/1169581
+
 # Populated manually - other compile-time reasons
 iovec::iov_base  # requires adding .get() in another repository, used e.g. in
                  # reinterpret_cast in quic_stream_sequencer_buffer.cc
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index 41df350c..60c6a90e 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -22,7 +22,6 @@
 import shutil
 import subprocess
 import sys
-import tempfile
 
 from update import (CDS_URL, CHROMIUM_DIR, CLANG_REVISION, LLVM_BUILD_DIR,
                     FORCE_HEAD_REVISION_FILE, PACKAGE_VERSION, RELEASE_VERSION,
@@ -46,12 +45,10 @@
     CHROMIUM_DIR, 'third_party', 'android_ndk')
 FUCHSIA_SDK_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'fuchsia-sdk',
                                'sdk')
-HOST_CLANG_DIR = os.path.join(LLVM_BUILD_TOOLS_DIR, 'pinned-clang')
 
 BUG_REPORT_URL = ('https://crbug.com and run'
                   ' tools/clang/scripts/process_crashreports.py'
                   ' (only works inside Google) which will upload a report')
-UPDATE_PY_URL = 'https://raw.githubusercontent.com/chromium/chromium/master/tools/clang/scripts/update.py'
 
 
 win_sdk_dir = None
@@ -327,22 +324,6 @@
   args.gcc_toolchain = gcc_dir
 
 
-def DownloadHostClang():
-  """Download update.py and run it."""
-  if not os.path.exists(HOST_CLANG_DIR):
-    tempfile_name = ""
-    with tempfile.NamedTemporaryFile(delete=False) as f:
-      DownloadUrl(UPDATE_PY_URL, f)
-      tempfile_name = f.name
-    print("Running update.py")
-    code = subprocess.call(
-        [sys.executable, tempfile_name, '--output-dir=' + HOST_CLANG_DIR])
-    os.remove(tempfile_name)
-    if code != 0:
-      print("update.py failed.")
-      sys.exit(1)
-
-
 def VerifyVersionOfBuiltClangMatchesVERSION():
   """Checks that `clang --version` outputs RELEASE_VERSION. If this
   fails, update.RELEASE_VERSION is out-of-date and needs to be updated (possibly
@@ -727,8 +708,6 @@
       cxxflags.append('--gcc-toolchain=' + args.gcc_toolchain)
 
     print('Bootstrap compiler installed.')
-  else:
-    DownloadHostClang()
 
   if args.pgo:
     print('Building instrumented compiler')
@@ -1013,7 +992,6 @@
       android_args = base_cmake_args + [
         '-DCMAKE_C_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang'),
         '-DCMAKE_CXX_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang++'),
-        '-DLLVM_USE_LINKER=' + os.path.join(HOST_CLANG_DIR, 'bin/ld.lld'), 
         '-DLLVM_CONFIG_PATH=' + os.path.join(LLVM_BUILD_DIR, 'bin/llvm-config'),
         '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
         '-DCMAKE_CXX_FLAGS=' + ' '.join(cflags),
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py
index 35cce40..98de2eaf 100644
--- a/tools/grit/grit/format/resource_map.py
+++ b/tools/grit/grit/format/resource_map.py
@@ -129,13 +129,6 @@
 def _GetItemName(item):
   return item.attrs['name']
 
-# Check if |path2| is a subpath of |path1|.
-def _IsSubpath(path1, path2):
-  path1_abs = os.path.abspath(path1)
-  path2_abs = os.path.abspath(path2)
-  common = os.path.commonprefix([path1_abs, path2_abs])
-  return path1_abs == common
-
 def _GetItemPath(item):
   resource_path = item.attrs.get('resource_path', '')
   if resource_path:
@@ -143,21 +136,14 @@
 
   path = item.GetInputPath().replace("\\", "/")
 
-  # Handle the case where the file resides within the output folder,
-  # by expanding any variables as well as replacing the output folder name with
-  # a fixed string such that the key added to the map does not depend on a given
-  # developer's setup.
-  #
-  # For example this will convert the following path:
-  # ../../out/gchrome/${root_gen_dir}/ui/webui/resources/js/foo.js
-  # to:
-  # @out_folder@/gen/ui/webui/resources/js/foo.js
-
-  real_path = item.ToRealPath(item.GetInputPath())
-  if (item.attrs.get('use_base_dir', 'true') != 'true' and
-          _IsSubpath(os.path.curdir, real_path)):
-    path = os.path.join(
-        '@out_folder@', os.path.relpath(real_path)).replace("\\", "/")
+  # For the case of generated files such as
+  # out/gchrome/${root_gen_dir}/ui/webui/resources/js/foo.js
+  # |resource_path| must be provided. It will be used as the ID in the
+  # generated GritResourceMap entry. For WebUI files, it will also be used as
+  # the URL subpath under which a file will be served at runtime.
+  assert item.attrs.get('use_base_dir', 'true') == 'true', \
+      'resource_path attribute missing for %s. Generated files must specify' \
+      ' resource_path' % item.attrs.get('name')
 
   assert '$' not in path, 'all variables should have been expanded'
   return path
diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py
index 3531a8e..b56e7e1 100755
--- a/tools/grit/grit/format/resource_map_unittest.py
+++ b/tools/grit/grit/format/resource_map_unittest.py
@@ -112,18 +112,11 @@
          </includes>
         </release>''', run_gatherers=True)
 
-    formatter = resource_map.GetFormatter('resource_file_map_source')
-    output = util.StripBlankLinesAndComments(''.join(formatter(grd, 'en', '.')))
-    expected = '''\
-#include "resource_map_header.h"
-#include <stddef.h>
-#include "base/stl_util.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
-  {"@out_folder@/gen/foo/bar/baz.js", IDR_FOO_BAR_BAZ_JS},
-};
-const size_t kTheRcHeaderSize = base::size(kTheRcHeader);'''
-    self.assertEqual(expected, output)
+    with self.assertRaises(AssertionError) as assertion_error:
+      formatter = resource_map.GetFormatter('resource_file_map_source')
+      util.StripBlankLinesAndComments(''.join(formatter(grd, 'en', '.')))
+    self.assertTrue(str(assertion_error.exception). \
+        startswith('resource_path attribute missing for IDR_FOO_BAR_BAZ_JS'))
 
   def testFormatResourceMapWithOutputAllEqualsFalseForStructures(self):
     grd = util.ParseGrdForUnittest('''
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 7c9e9f9..b06f88c 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -110,8 +110,9 @@
     "META": {"sizes": {"includes": [50],}},
     "includes": [1260],
   },
-  "chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd": {
-    "structures": [1360],
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/cellular_setup/resources.grd": {
+    "META": {"sizes": {"includes": [10]}},
+    "includes": [1360],
   },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/emoji_picker/resources.grd": {
     "META": {"sizes": {"includes": [20]}},
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 792415e..a1901bd 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -169,6 +169,7 @@
       'chromeos-arm-generic-dbg': 'chromeos_arm-generic_dbg',
       'chromeos-arm-generic-rel': 'chromeos_arm-generic',
       'chromeos-kevin-rel': 'chromeos_kevin',
+      'lacros-amd64-generic-binary-size-rel': 'chromeos_amd64-generic_lacros_rel',
       'lacros-amd64-generic-rel': 'chromeos_amd64-generic_lacros_rel',
       'linux-chromeos-rel': 'chromeos_with_codecs_release_bot',
       'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot',
diff --git a/tools/mb/mb_config_expectations/chromium.chromiumos.json b/tools/mb/mb_config_expectations/chromium.chromiumos.json
index ec722e3..7b760d02 100644
--- a/tools/mb/mb_config_expectations/chromium.chromiumos.json
+++ b/tools/mb/mb_config_expectations/chromium.chromiumos.json
@@ -101,6 +101,34 @@
       "use_goma": true
     }
   },
+  "lacros-amd64-generic-binary-size-rel": {
+    "args_file": "//build/args/chromeos/amd64-generic.gni",
+    "gn_args": {
+      "chromeos_is_browser_only": true,
+      "cros_host_sysroot": "//build/linux/debian_sid_amd64-sysroot",
+      "cros_v8_snapshot_sysroot": "//build/linux/debian_sid_amd64-sysroot",
+      "enable_linux_installer": false,
+      "is_chromeos_device": true,
+      "ozone_platform_headless": true,
+      "ozone_platform_wayland": true,
+      "ozone_platform_x11": false,
+      "rtc_use_pipewire": false,
+      "target_os": "chromeos",
+      "use_custom_libcxx": false,
+      "use_custom_libcxx_for_host": true,
+      "use_evdev_gestures": false,
+      "use_gio": false,
+      "use_glib": false,
+      "use_goma": true,
+      "use_gtk": false,
+      "use_ozone": true,
+      "use_pangocairo": false,
+      "use_pulseaudio": false,
+      "use_system_libsync": false,
+      "use_v8_context_snapshot": false,
+      "use_vaapi": false
+    }
+  },
   "lacros-amd64-generic-rel": {
     "args_file": "//build/args/chromeos/amd64-generic.gni",
     "gn_args": {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 7cb477e..06a8451a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -23433,6 +23433,7 @@
   <int value="819" label="SSLErrorOverrideAllowedForUrls"/>
   <int value="820" label="WebXRImmersiveArEnabled"/>
   <int value="821" label="GaiaOfflineSigninTimeLimitDays"/>
+  <int value="822" label="FileSystemEnterpriseConnector"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -41801,6 +41802,7 @@
   <int value="7" label="Error: invalid image uri"/>
   <int value="8" label="Error: early terminated"/>
   <int value="9" label="Disabled"/>
+  <int value="10" label="Error: additional web context malformed (nonfatal)"/>
 </enum>
 
 <enum name="LensSdkError">
@@ -45215,6 +45217,7 @@
   <int value="176773784" label="EnableHardwareMirrorMode:disabled"/>
   <int value="178337215" label="enable-md-history"/>
   <int value="178693406" label="LockScreenMediaControls:disabled"/>
+  <int value="179871410" label="ui-debug-tools:disabled"/>
   <int value="180074362" label="memory-pressure-thresholds"/>
   <int value="181150000" label="CrosVmCupsProxy:enabled"/>
   <int value="182788555" label="DecoupleSyncFromAndroidMasterSync:disabled"/>
@@ -46110,6 +46113,8 @@
   <int value="1033597574" label="disable-layer-squashing"/>
   <int value="1036068554" label="enable-android-pay-integration-v2"/>
   <int value="1036565901" label="AssistPersonalInfo:enabled"/>
+  <int value="1036958177"
+      label="enable-experimental-accessibility-dictation-extension"/>
   <int value="1037961753" label="CCTIncognito:disabled"/>
   <int value="1038264914" label="PerDeskShelf:enabled"/>
   <int value="1042202617" label="RemoteCopyReceiver:enabled"/>
@@ -47250,6 +47255,7 @@
       label="AutofillEnforceMinRequiredFieldsForUpload:enabled"/>
   <int value="2085186092" label="BulkPrinters:disabled"/>
   <int value="2085438501" label="ChromeHome:enabled"/>
+  <int value="2087069781" label="ui-debug-tools:enabled"/>
   <int value="2088446947" label="enable-ephemeral-guest-profiles-on-desktop"/>
   <int value="2089897928" label="enable-audio-focus"/>
   <int value="2091002949" label="RemoveNavigationHistory:disabled"/>
@@ -63370,6 +63376,19 @@
   <int value="189" label="QUIC_QPACK_DECODER_STREAM_IMPOSSIBLE_INSERT_COUNT"/>
   <int value="190" label="QUIC_QPACK_DECODER_STREAM_INCORRECT_ACKNOWLEDGEMENT"/>
   <int value="191" label="QUIC_MAX_AGE_TIMEOUT"/>
+  <int value="192" label="QUIC_INVALID_0RTT_PACKET_NUMBER_OUT_OF_ORDER"/>
+  <int value="193" label="QUIC_INVALID_PRIORITY_UPDATE"/>
+  <int value="194" label="QUIC_PEER_PORT_CHANGE_HANDSHAKE_UNCONFIRMED"/>
+  <int value="195" label="QUIC_TLS_BAD_CERTIFICATE"/>
+  <int value="196" label="QUIC_TLS_UNSUPPORTED_CERTIFICATE"/>
+  <int value="197" label="QUIC_TLS_CERTIFICATE_REVOKED"/>
+  <int value="198" label="QUIC_TLS_CERTIFICATE_EXPIRED"/>
+  <int value="199" label="QUIC_TLS_CERTIFICATE_UNKNOWN"/>
+  <int value="200" label="QUIC_TLS_INTERNAL_ERROR"/>
+  <int value="201" label="QUIC_TLS_UNRECOGNIZED_NAME"/>
+  <int value="202" label="QUIC_TLS_CERTIFICATE_REQUIRED"/>
+  <int value="203" label="QUIC_CONNECTION_ID_LIMIT_ERROR"/>
+  <int value="204" label="QUIC_TOO_MANY_CONNECTION_ID_WAITING_TO_RETIRE"/>
 </enum>
 
 <enum name="QuicFailToSerializePacketLocation">
@@ -78019,6 +78038,14 @@
   <int value="3" label="HitTestData outdated"/>
 </enum>
 
+<enum name="VkPipelinePopulatedCacheEntryUsage">
+  <int value="0" label="Used"/>
+  <int value="1" label="Overwritten"/>
+  <int value="2" label="Discarded: too large"/>
+  <int value="3" label="Discarded: have newer data"/>
+  <int value="4" label="Evicted"/>
+</enum>
+
 <enum name="VoiceInteractionEventSource">
 <!-- This must be kept in sync with VoiceInteraction.AssistantActionPerformed in
 others/histograms.xml -->
diff --git a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
index 1b3c180..94a8d642 100644
--- a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
@@ -1223,6 +1223,65 @@
   </summary>
 </histogram>
 
+<histogram name="GPU.Vulkan.PipelineCache.LoadCacheHit" enum="BooleanCacheHit"
+    expires_after="2021-06-25">
+  <owner>backer@chromium.org</owner>
+  <owner>penghuang@chromium.org</owner>
+  <owner>vasilyt@chromium.org</owner>
+  <summary>
+    Shows if we had a vkPipelineCache entry in cache when skia requested it.
+    Recorded each time skia loads vkPipelineCache entry from the GrShaderCache.
+  </summary>
+</histogram>
+
+<histogram name="GPU.Vulkan.PipelineCache.PopulatedCacheUsage"
+    enum="VkPipelinePopulatedCacheEntryUsage" expires_after="2021-06-25">
+  <owner>backer@chromium.org</owner>
+  <owner>penghuang@chromium.org</owner>
+  <owner>vasilyt@chromium.org</owner>
+  <summary>
+    Shows if the populated from disk cache entry was used by skia or discarded
+    and why. Recorded when cache entry that was read from disk is either loaded
+    by skia, overwriten by skia or discarded by GrShaderCache.
+  </summary>
+</histogram>
+
+<histogram name="GPU.Vulkan.PipelineCache.Size" units="KB"
+    expires_after="2021-06-25">
+  <owner>backer@chromium.org</owner>
+  <owner>penghuang@chromium.org</owner>
+  <owner>vasilyt@chromium.org</owner>
+  <summary>
+    Size of stored VkPipelineCache in kb. Recorded every time we store a
+    pipeline cache item. Currently happens when gpu goes idle after we stored or
+    loaded new shader.
+  </summary>
+</histogram>
+
+<histogram name="GPU.Vulkan.PipelineCache.StoreDuration" units="microseconds"
+    expires_after="2021-06-25">
+  <owner>backer@chromium.org</owner>
+  <owner>penghuang@chromium.org</owner>
+  <owner>vasilyt@chromium.org</owner>
+  <summary>
+    Duration of storeVkPipelineCacheData in Skia, this includes chromium side
+    GrShaderCache::store. Recorded even if data didn't fit into the cache. Only
+    reported for platforms supporting high resolution clocks.
+  </summary>
+</histogram>
+
+<histogram name="GPU.Vulkan.PipelineCache.vkCreateGraphicsPipelines"
+    units="microseconds" expires_after="2021-06-25">
+  <owner>backer@chromium.org</owner>
+  <owner>penghuang@chromium.org</owner>
+  <owner>vasilyt@chromium.org</owner>
+  <summary>
+    Duration of vkCreateGraphicsPipelines call. Recorded every time Skia creates
+    graphics pipeline. Only reported for platforms supporting high resolution
+    clocks.
+  </summary>
+</histogram>
+
 <histogram name="GPU.Vulkan.QueueSubmitPerSwapBuffers" units="units"
     expires_after="2021-04-04">
   <owner>backer@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index d3c8cfe..dba35d1 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -4348,7 +4348,7 @@
 </histogram>
 
 <histogram name="Net.RestrictedCookieManager.SiteForCookiesOK" enum="Boolean"
-    expires_after="M87">
+    expires_after="M95">
   <owner>morlovich@chromium.org</owner>
   <owner>chlily@chromium.org</owner>
   <summary>
@@ -4358,7 +4358,7 @@
 </histogram>
 
 <histogram name="Net.RestrictedCookieManager.TopFrameOriginOK" enum="Boolean"
-    expires_after="M87">
+    expires_after="M95">
   <owner>morlovich@chromium.org</owner>
   <owner>chlily@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/profile/histograms.xml b/tools/metrics/histograms/histograms_xml/profile/histograms.xml
index 127256d6..03dfd20 100644
--- a/tools/metrics/histograms/histograms_xml/profile/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/profile/histograms.xml
@@ -653,6 +653,9 @@
 
 <histogram name="Profile.ValidateMenuItemInvalidIndex.IsGuest" enum="Boolean"
     expires_after="M85">
+  <obsolete>
+    Removed in M90.
+  </obsolete>
   <owner>anthonyvd@chromium.org</owner>
   <summary>
     Whether the active profile is a guest profile when -validateMenuItem in the
@@ -662,6 +665,9 @@
 
 <histogram name="Profile.ValidateMenuItemInvalidIndex.ProfileCount"
     units="units" expires_after="M85">
+  <obsolete>
+    Removed in M90.
+  </obsolete>
   <owner>anthonyvd@chromium.org</owner>
   <summary>
     The count of profiles in the avatar menu when -validateMenuItem in the
@@ -671,6 +677,9 @@
 
 <histogram name="Profile.ValidateMenuItemInvalidIndex.Selector"
     enum="ValidateMenuItemSelectorType" expires_after="M85">
+  <obsolete>
+    Removed in M90.
+  </obsolete>
   <owner>anthonyvd@chromium.org</owner>
   <summary>
     The selector associated with the menu item when -validateMenuItem in the
diff --git a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
index dd06534..ea71600 100644
--- a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
@@ -757,6 +757,9 @@
 
 <histogram name="SafeBrowsing.NavigationObserver.NavigationEventCleanUpCount"
     units="NavigationEvents" expires_after="2021-01-27">
+  <obsolete>
+    Removed 01-29-2021 due to lack of use.
+  </obsolete>
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 274ad67..37203b4 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -1265,6 +1265,20 @@
   </metric>
 </event>
 
+<event name="Autofill.FormFillSuccessIOS">
+  <owner>kazinova@chromium.org</owner>
+  <summary>
+    Records whether the the form was successfully filled by Autofill on iOS. The
+    metric is used to measure silent renderer fails when the filling request is
+    executed successfully but the results reported in a callback are empty.
+  </summary>
+  <metric name="FormFillSuccess" enum="Boolean">
+    <summary>
+      A boolean indicating success or failure.
+    </summary>
+  </metric>
+</event>
+
 <event name="Autofill.FormSubmitted">
   <owner>jiahuiguo@google.com</owner>
   <summary>
@@ -4784,7 +4798,7 @@
   </summary>
   <metric name="Activation">
     <summary>
-      The duration of the activation stage.
+      The duration of the activation stage, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4798,7 +4812,7 @@
   <metric name="BeginImplFrameToSendBeginMainFrame">
     <summary>
       The time from when the Impl frame is started to when BeginMainFrame is
-      sent.
+      sent, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4815,12 +4829,12 @@
     </obsolete>
     <summary>
       The time from when the event is created in the browser until the first
-      compositor stage after the event arrives in the renderer.
+      compositor stage after the event arrives in the renderer, in microseconds.
     </summary>
   </metric>
   <metric name="Commit">
     <summary>
-      The duration of the commit stage.
+      The duration of the commit stage, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4834,7 +4848,7 @@
   <metric name="EndActivateToSubmitCompositorFrame">
     <summary>
       The time from when an activation is complete to the next
-      SubmitCompositorFrame.
+      SubmitCompositorFrame, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4848,7 +4862,7 @@
   <metric name="EndCommitToActivation">
     <summary>
       The time from when a commit is complete to the beginning of the next
-      activation.
+      activation, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4875,7 +4889,7 @@
   <metric name="GenerationToRendererCompositor">
     <summary>
       The time from when the event is created until it arrives in the renderer
-      compositor.
+      compositor, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -4889,9 +4903,10 @@
   <metric name="RendererCompositorFinishedToActivation">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the beginning of the activation. This metric is only
-      reported if the event is handled on the renderer compositor and the first
-      compositor step after that is the beginning of the activation.
+      compositor until the beginning of the activation, in microseconds. This
+      metric is only reported if the event is handled on the renderer compositor
+      and the first compositor step after that is the beginning of the
+      activation.
     </summary>
     <aggregation>
       <history>
@@ -4905,9 +4920,9 @@
   <metric name="RendererCompositorFinishedToBeginImplFrame">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the compositor frame is started. This metric is only
-      reported if the event is handled on the renderer compositor and compositor
-      frame is started after that.
+      compositor until the compositor frame is started, in microseconds. This
+      metric is only reported if the event is handled on the renderer compositor
+      and compositor frame is started after that.
     </summary>
     <aggregation>
       <history>
@@ -4921,9 +4936,9 @@
   <metric name="RendererCompositorFinishedToCommit">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the beginning of the commit. This metric is only reported
-      if the event is handled on the renderer compositor and the first
-      compositor step after that is the beginning of the commit.
+      compositor until the beginning of the commit, in microseconds. This metric
+      is only reported if the event is handled on the renderer compositor and
+      the first compositor step after that is the beginning of the commit.
     </summary>
     <aggregation>
       <history>
@@ -4937,9 +4952,9 @@
   <metric name="RendererCompositorFinishedToEndActivate">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the end of the activation. This metric is only reported
-      if the event is handled on the renderer compositor and the first
-      compositor step after that is the end of the activation.
+      compositor until the end of the activation, in microseconds. This metric
+      is only reported if the event is handled on the renderer compositor and
+      the first compositor step after that is the end of the activation.
     </summary>
     <aggregation>
       <history>
@@ -4953,9 +4968,9 @@
   <metric name="RendererCompositorFinishedToEndCommit">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the end of the commit. This metric is only reported if
-      the event is handled on the renderer compositor and the first compositor
-      step after that is the end of the commit.
+      compositor until the end of the commit, in microseconds. This metric is
+      only reported if the event is handled on the renderer compositor and the
+      first compositor step after that is the end of the commit.
     </summary>
     <aggregation>
       <history>
@@ -4969,9 +4984,9 @@
   <metric name="RendererCompositorFinishedToSendBeginMainFrame">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until BeginMainFrame is sent. This metric is only reported if
-      the event is handled on the renderer compositor and the first compositor
-      step after that is SendBeginMainFrame.
+      compositor until BeginMainFrame is sent, in microseconds. This metric is
+      only reported if the event is handled on the renderer compositor and the
+      first compositor step after that is SendBeginMainFrame.
     </summary>
     <aggregation>
       <history>
@@ -4985,9 +5000,10 @@
   <metric name="RendererCompositorFinishedToSubmitCompositorFrame">
     <summary>
       The time from when the event processing is finished on the renderer
-      compositor until the compositor frame is submitted. This metric is only
-      reported if the event is handled on the renderer compositor and the first
-      compositor step after that is the submission of the compositor frame.
+      compositor until the compositor frame is submitted, in microseconds. This
+      metric is only reported if the event is handled on the renderer compositor
+      and the first compositor step after that is the submission of the
+      compositor frame.
     </summary>
     <aggregation>
       <history>
@@ -5000,9 +5016,9 @@
   </metric>
   <metric name="RendererCompositorProcessing">
     <summary>
-      The time spent in the renderer compositor to process the event. This
-      metric won't be reported if the renderer compositor does not have a
-      dedicated thread.
+      The time spent in the renderer compositor to process the event, in
+      microseconds. This metric won't be reported if the renderer compositor
+      does not have a dedicated thread.
     </summary>
     <aggregation>
       <history>
@@ -5016,8 +5032,8 @@
   <metric name="RendererCompositorQueueingDelay">
     <summary>
       The time from when the event arrives in the renderer compositor until the
-      compositor starts processing it. This metric won't be reported if the
-      renderer compositor does not have a dedicated thread.
+      compositor starts processing it, in microseconds. This metric won't be
+      reported if the renderer compositor does not have a dedicated thread.
     </summary>
     <aggregation>
       <history>
@@ -5031,11 +5047,12 @@
   <metric name="RendererCompositorToMain">
     <summary>
       The time from when the processing of the event on the renderer compositor
-      is finished until the main thread starts processing the event. If the
-      renderer compositor does not have a dedicated thread, the processing of
-      the event on the renderer compositor is considered finished as soon as the
-      event arrives in the renderer compositor. This metric won't be reported if
-      the event is handled on the renderer compositor.
+      is finished until the main thread starts processing the event, in
+      microseconds. If the renderer compositor does not have a dedicated thread,
+      the processing of the event on the renderer compositor is considered
+      finished as soon as the event arrives in the renderer compositor. This
+      metric won't be reported if the event is handled on the renderer
+      compositor.
     </summary>
     <aggregation>
       <history>
@@ -5049,9 +5066,9 @@
   <metric name="RendererMainFinishedToActivation">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the beginning of the activation. This metric is only reported if the
-      event is handled on the renderer main and the first compositor step after
-      that is the beginning of the activation.
+      until the beginning of the activation, in microseconds. This metric is
+      only reported if the event is handled on the renderer main and the first
+      compositor step after that is the beginning of the activation.
     </summary>
     <aggregation>
       <history>
@@ -5065,9 +5082,9 @@
   <metric name="RendererMainFinishedToBeginImplFrame">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the compositor frame is started. This metric is only reported if the
-      event is handled on the renderer main and compositor frame is started
-      after that.
+      until the compositor frame is started, in microseconds. This metric is
+      only reported if the event is handled on the renderer main and compositor
+      frame is started after that.
     </summary>
     <aggregation>
       <history>
@@ -5081,9 +5098,9 @@
   <metric name="RendererMainFinishedToCommit">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the beginning of the commit. This metric is only reported if the
-      event is handled on the renderer main and the first compositor step after
-      that is the beginning of the commit.
+      until the beginning of the commit, in microseconds. This metric is only
+      reported if the event is handled on the renderer main and the first
+      compositor step after that is the beginning of the commit.
     </summary>
     <aggregation>
       <history>
@@ -5097,9 +5114,9 @@
   <metric name="RendererMainFinishedToEndActivate">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the end of the activation. This metric is only reported if the event
-      is handled on the renderer main and the first compositor step after that
-      is the end of the activation.
+      until the end of the activation, in microseconds. This metric is only
+      reported if the event is handled on the renderer main and the first
+      compositor step after that is the end of the activation.
     </summary>
     <aggregation>
       <history>
@@ -5113,9 +5130,9 @@
   <metric name="RendererMainFinishedToEndCommit">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the end of the commit. This metric is only reported if the event is
-      handled on the renderer main and the first compositor step after that is
-      the end of the commit.
+      until the end of the commit, in microseconds. This metric is only reported
+      if the event is handled on the renderer main and the first compositor step
+      after that is the end of the commit.
     </summary>
     <aggregation>
       <history>
@@ -5129,9 +5146,9 @@
   <metric name="RendererMainFinishedToSendBeginMainFrame">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until BeginMainFrame is sent. This metric is only reported if the event is
-      handled on the renderer main and the first compositor step after that is
-      SendBeginMainFrame.
+      until BeginMainFrame is sent, in microseconds. This metric is only
+      reported if the event is handled on the renderer main and the first
+      compositor step after that is SendBeginMainFrame.
     </summary>
     <aggregation>
       <history>
@@ -5145,9 +5162,9 @@
   <metric name="RendererMainFinishedToSubmitCompositorFrame">
     <summary>
       The time from when the event processing is finished on the renderer main
-      until the compositor frame is submitted. This metric is only reported if
-      the event is handled on the renderer main and the first compositor step
-      after that is the submission of the compositor frame.
+      until the compositor frame is submitted, in microseconds. This metric is
+      only reported if the event is handled on the renderer main and the first
+      compositor step after that is the submission of the compositor frame.
     </summary>
     <aggregation>
       <history>
@@ -5160,8 +5177,9 @@
   </metric>
   <metric name="RendererMainProcessing">
     <summary>
-      The time spent in the main thread to process the event. This metric won't
-      be reported if the renderer compositor handles the event.
+      The time spent in the main thread to process the event, in microseconds.
+      This metric won't be reported if the renderer compositor handles the
+      event.
     </summary>
     <aggregation>
       <history>
@@ -5187,7 +5205,7 @@
   <metric name="SendBeginMainFrameToCommit">
     <summary>
       The time from when the BeginMainFrame is sent to the beginning of the
-      commit.
+      commit, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5201,7 +5219,162 @@
   <metric name="SubmitCompositorFrameToPresentationCompositorFrame">
     <summary>
       The time from when a compositor frame is submitted to the display
-      compositor to when it is presented.
+      compositor to when it is presented, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.BufferAvailableToBufferReady">
+    <summary>
+      The time from when the target framebuffer is available to when the GPU has
+      finished drawing to it, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.BufferReadyToLatch">
+    <summary>
+      The time from when the target framebuffer is ready to be displayed to when
+      the buffer is latched on for presentation, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.LatchToSwapEnd">
+    <summary>
+      The time from when the target framebuffer is latched on to when the swap
+      ends, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.ReceivedCompositorFrameToStartDraw">
+    <summary>
+      The time from when a compositor frame is received to when it starts to
+      draw, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.StartDrawToSwapEnd">
+    <obsolete>
+      Deprecated 02/2020. Split into
+      SubmitCompositorFrameToPresentationCompositorFrame.StartDrawToSwapStart
+      and SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd.
+    </obsolete>
+    <summary>
+      The time from when the a compositor frame is started to draw to when it
+      ends swap, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.StartDrawToSwapStart">
+    <summary>
+      The time from when a compositor frame is started to draw to when it starts
+      swap, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.SubmitToReceiveCompositorFrame">
+    <summary>
+      The time from when a compositor frame is submitted to when it is received,
+      in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.SwapEndToPresentationCompositorFrame">
+    <summary>
+      The time from when a compositor frame ends swap to when it is presented,
+      in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToBufferAvailable">
+    <summary>
+      The time from when the compositor frame starts to swap to when the target
+      framebuffer becomes available, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd">
+    <summary>
+      The time from when a compositor frame starts swap to when it ends swap, in
+      microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5215,7 +5388,7 @@
   <metric name="TotalLatency">
     <summary>
       The total time from when the event is created in the browser to when the
-      frame is presented.
+      frame is presented, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5229,7 +5402,7 @@
   <metric name="TotalLatencyToSwapBegin">
     <summary>
       The time from when the event is created in the browser to when the
-      gpu-swap is started, for scroll events.
+      gpu-swap is started, for scroll events, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5247,7 +5420,7 @@
     </obsolete>
     <summary>
       The time from when the event is created in the browser to when the
-      gpu-swap is completed, for scroll events.
+      gpu-swap is completed, for scroll events, in microseconds.
     </summary>
   </metric>
 </event>
@@ -5262,7 +5435,7 @@
   </summary>
   <metric name="Activation">
     <summary>
-      The duration of the activation stage.
+      The duration of the activation stage, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5276,7 +5449,7 @@
   <metric name="BeginImplFrameToSendBeginMainFrame">
     <summary>
       The time from when the Impl frame is started to when BeginMainFrame is
-      sent.
+      sent, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5294,7 +5467,7 @@
   </metric>
   <metric name="Commit">
     <summary>
-      The duration of the commit stage.&quot;
+      The duration of the commit stage, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5313,7 +5486,7 @@
   <metric name="EndActivateToSubmitCompositorFrame">
     <summary>
       The time from when an activation is complete to the next
-      SubmitCompositorFrame.
+      SubmitCompositorFrame, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5327,7 +5500,7 @@
   <metric name="EndCommitToActivation">
     <summary>
       The time from when a commit is complete to the beginning of the next
-      activation.
+      activation, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5378,7 +5551,7 @@
   <metric name="SendBeginMainFrameToCommit">
     <summary>
       The time from when the BeginMainFrame is sent to the beginning of the
-      commit.
+      commit, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5392,7 +5565,52 @@
   <metric name="SubmitCompositorFrameToPresentationCompositorFrame">
     <summary>
       The time from when the a compositor frame is submitted to the display
-      compositor to when it is presented.
+      compositor to when it is presented, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.BufferAvailableToBufferReady">
+    <summary>
+      The time from when the target framebuffer is available to when the GPU has
+      finished drawing to it, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.BufferReadyToLatch">
+    <summary>
+      The time from when the target framebuffer is ready to be displayed to when
+      the buffer is latched on for presentation, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.LatchToSwapEnd">
+    <summary>
+      The time from when the target framebuffer is latched on to when the swap
+      ends, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5407,7 +5625,7 @@
       name="SubmitCompositorFrameToPresentationCompositorFrame.ReceivedCompositorFrameToStartDraw">
     <summary>
       The time from when a compositor frame is received to when it starts to
-      draw.
+      draw, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5427,7 +5645,7 @@
     </obsolete>
     <summary>
       The time from when the a compositor frame is started to draw to when it
-      ends swap.
+      ends swap, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5442,7 +5660,7 @@
       name="SubmitCompositorFrameToPresentationCompositorFrame.StartDrawToSwapStart">
     <summary>
       The time from when a compositor frame is started to draw to when it starts
-      swap.
+      swap, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5456,8 +5674,8 @@
   <metric
       name="SubmitCompositorFrameToPresentationCompositorFrame.SubmitToReceiveCompositorFrame">
     <summary>
-      The time from when the a compositor frame is submitted to when it is
-      received.
+      The time from when a compositor frame is submitted to when it is received,
+      in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5472,7 +5690,22 @@
       name="SubmitCompositorFrameToPresentationCompositorFrame.SwapEndToPresentationCompositorFrame">
     <summary>
       The time from when the a compositor frame ends swap to when it is
-      presented.
+      presented, in microseconds.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric
+      name="SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToBufferAvailable">
+    <summary>
+      The time from when the compositor frame starts to swap to when the target
+      framebuffer becomes available, in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5486,7 +5719,8 @@
   <metric
       name="SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd">
     <summary>
-      The time from when a compositor frame starts swap to when it ends swap.
+      The time from when a compositor frame starts swap to when it ends swap, in
+      microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5502,7 +5736,7 @@
       The total time starting from BeginImplFrame to when
       CompositorFramePresentation is done with updates from the MainThread (i.e.
       the time it takes for BeginImplFrame, BeginMainFrame, Commit, Activate,
-      SubmitCompositorFrame and PresentCompositorFrame).
+      SubmitCompositorFrame and PresentCompositorFrame), in microseconds.
     </summary>
     <aggregation>
       <history>
@@ -5520,7 +5754,7 @@
   </metric>
   <metric name="Unknown">
     <summary>
-      The time within a stage not attributed to any system.
+      The time within a stage not attributed to any system, in microseconds.
     </summary>
     <aggregation>
       <history>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 55b5109b..c22476a 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "30931e0f17242d862be9953aa7fd30a413469067",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/dd5f5806985f9140ee3011e2451676e2b677e880/trace_processor_shell.exe"
+            "hash": "eefb6f8ecaf2f44ba9f0bf8ebb65ff7af3604fea",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/6933c2e782d87f56e021d5a130d82771ce519179/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "b49e88972f0671da7a47a4445c0dc771b7896e97",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/dd5f5806985f9140ee3011e2451676e2b677e880/trace_processor_shell"
+            "hash": "30dda1f33aa3ecc06e767a3b732dc5e3b782db15",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/6933c2e782d87f56e021d5a130d82771ce519179/trace_processor_shell"
         },
         "linux": {
-            "hash": "9a16864b184669e2da07ef56b96962f88b57cd9a",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/77f491d9939951dd6f1804c451244d97c1954444/trace_processor_shell"
+            "hash": "617201d0dc04c42dfbab6bc868d176cc915a5c47",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/7551137d36dd06b5622959c02e06fd45d5d05459/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index a5359d94..5e06aa6 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -383,6 +383,8 @@
 crbug.com/1147969 [ fuchsia ] system_health.memory_desktop/multitab:misc:typical24 [ Skip ]
 crbug.com/1147969 [ fuchsia ] system_health.memory_desktop/multitab:misc:typical24:2018 [ Skip ]
 crbug.com/1156571 [ mac-10.12 ] system_health.memory_desktop/browse:news:nytimes:2020 [ Skip ]
+crbug.com/1173122 [ linux ] system_health.memory_desktop/load:tools:chat:2020 [ Skip ]
+crbug.com/1173122 [ linux ] system_health.memory_desktop/load:tools:gmail:2019 [ Skip ]
 
 # Memory dumps don't work at the moment for Google Earth and AutoCAD, see the issue.
 crbug.com/1057035 system_health.memory_desktop/browse:tools:earth:2020 [ Skip ]
diff --git a/tools/perf/page_sets/desktop_ui/desktop_ui_stories.py b/tools/perf/page_sets/desktop_ui/desktop_ui_stories.py
index c621e70..fc0eb7a2 100644
--- a/tools/perf/page_sets/desktop_ui/desktop_ui_stories.py
+++ b/tools/perf/page_sets/desktop_ui/desktop_ui_stories.py
@@ -21,6 +21,8 @@
       tab_search_story.TabSearchStoryMeasureMemoryBefore,
       tab_search_story.TabSearchStoryMeasureMemoryAfter,
       tab_search_story.TabSearchStoryMeasureMemoryMultiwindow,
+      tab_search_story.TabSearchStoryMeasureMemory2TabSearch,
+      tab_search_story.TabSearchStoryMeasureMemory3TabSearch,
   ]
 
   def __init__(self):
diff --git a/tools/perf/page_sets/desktop_ui/multitab_story.py b/tools/perf/page_sets/desktop_ui/multitab_story.py
index b91c1c6..84c2e024 100644
--- a/tools/perf/page_sets/desktop_ui/multitab_story.py
+++ b/tools/perf/page_sets/desktop_ui/multitab_story.py
@@ -46,4 +46,4 @@
     chrome_trace_config.category_filter.AddIncludedCategory('blink.user_timing')
 
   def GetExtraTracingMetrics(self):
-    return []
+    return ['customMetric']
diff --git a/tools/perf/page_sets/desktop_ui/tab_search_story.py b/tools/perf/page_sets/desktop_ui/tab_search_story.py
index d0d400bf..d83c0800 100644
--- a/tools/perf/page_sets/desktop_ui/tab_search_story.py
+++ b/tools/perf/page_sets/desktop_ui/tab_search_story.py
@@ -254,6 +254,31 @@
     action_runner.MeasureMemory(deterministic_mode=True)
 
 
+class TabSearchStoryMeasureMemory2TabSearch(TabSearchStoryMeasureMemory):
+  NAME = 'tab_search:measure_memory:2tab_search'
+
+  def RunNavigateSteps(self, action_runner):
+    tabs = action_runner.tab.browser.tabs
+    new_tab = tabs.New()
+    new_tab.Navigate(TAB_SEARCH_URL)
+
+  def InteractWithPage(self, action_runner):
+    action_runner.MeasureMemory(deterministic_mode=True)
+
+
+class TabSearchStoryMeasureMemory3TabSearch(TabSearchStoryMeasureMemory):
+  NAME = 'tab_search:measure_memory:3tab_search'
+
+  def RunNavigateSteps(self, action_runner):
+    tabs = action_runner.tab.browser.tabs
+    for _ in range(2):
+      new_tab = tabs.New()
+      new_tab.Navigate(TAB_SEARCH_URL)
+
+  def InteractWithPage(self, action_runner):
+    action_runner.MeasureMemory(deterministic_mode=True)
+
+
 SCROLL_ELEMENT_FUNCTION = '''
 document.querySelector('tab-search-app').shadowRoot.getElementById('tabsList')
 '''
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc
index 5fe682f..2d2632bc 100644
--- a/ui/accessibility/accessibility_switches.cc
+++ b/ui/accessibility/accessibility_switches.cc
@@ -13,6 +13,11 @@
 const char kEnableExperimentalAccessibilityAutoclick[] =
     "enable-experimental-accessibility-autoclick";
 
+// Enables the experimental dictation extension on Chrome OS that hasn't
+// launched yet.
+const char kEnableExperimentalAccessibilityDictationExtension[] =
+    "enable-experimental-accessibility-dictation-extension";
+
 // Enables support for visually debugging the accessibility labels
 // feature, which provides images descriptions for screen reader users.
 const char kEnableExperimentalAccessibilityLabelsDebugging[] =
@@ -40,6 +45,11 @@
 const char kEnableSwitchAccessPointScanning[] =
     "enable-switch-access-point-scanning";
 
+bool IsExperimentalAccessibilityDictationExtensionEnabled() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      ::switches::kEnableExperimentalAccessibilityDictationExtension);
+}
+
 bool IsExperimentalAccessibilityLanguageDetectionEnabled() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       ::switches::kEnableExperimentalAccessibilityLanguageDetection);
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h
index fa841fe..eb0882a 100644
--- a/ui/accessibility/accessibility_switches.h
+++ b/ui/accessibility/accessibility_switches.h
@@ -13,6 +13,8 @@
 
 AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[];
 AX_BASE_EXPORT extern const char
+    kEnableExperimentalAccessibilityDictationExtension[];
+AX_BASE_EXPORT extern const char
     kEnableExperimentalAccessibilityLabelsDebugging[];
 AX_BASE_EXPORT extern const char
     kEnableExperimentalAccessibilityLanguageDetection[];
@@ -24,6 +26,9 @@
     kEnableExperimentalAccessibilityChromeVoxAnnotations[];
 AX_BASE_EXPORT extern const char kEnableSwitchAccessPointScanning[];
 
+// Returns true if experimental accessibility dictation extension is enabled.
+AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationExtensionEnabled();
+
 // Returns true if experimental accessibility language detection is enabled.
 AX_BASE_EXPORT bool IsExperimentalAccessibilityLanguageDetectionEnabled();
 
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h
index 09f0c7b..cde801cc 100644
--- a/ui/accessibility/ax_tree_serializer.h
+++ b/ui/accessibility/ax_tree_serializer.h
@@ -646,7 +646,14 @@
       base::debug::SetCrashKeyString(reparent_err, error.str().substr(0, 230));
       CHECK(false) << error.str();
 #endif  // defined(AX_FAIL_FAST_BUILD)
-      base::debug::DumpWithoutCrashing();
+      static bool has_sent_reparent_err = false;
+      if (!has_sent_reparent_err) {
+        std::srand(std::time(nullptr));  // use current time as seed.
+        if (std::rand() % 50 == 0) {     // Roughly 2% of the time.
+          base::debug::DumpWithoutCrashing();
+          has_sent_reparent_err = true;  // Only send once.
+        }
+      }
       Reset();
       return false;
     }
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 80bdb11..00353bfc 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -308,6 +308,12 @@
 const base::Feature kSwipeToMoveCursor{"SwipeToMoveCursor",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC)
+const base::Feature kUIDebugTools{"ui-debug-tools",
+                                  base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 bool IsSwipeToMoveCursorEnabled() {
   static const bool enabled =
       base::FeatureList::IsEnabled(kSwipeToMoveCursor)
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index e12abf7..1f854ac 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -166,6 +166,12 @@
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kSwipeToMoveCursor;
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC)
+// Enables UI debugging tools such as shortcuts.
+COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kUIDebugTools;
+#endif
+
 COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsSwipeToMoveCursorEnabled();
 
 }  // namespace features
diff --git a/ui/base/x/x11_software_bitmap_presenter.cc b/ui/base/x/x11_software_bitmap_presenter.cc
index 530b9859..9f35bb1 100644
--- a/ui/base/x/x11_software_bitmap_presenter.cc
+++ b/ui/base/x/x11_software_bitmap_presenter.cc
@@ -106,7 +106,7 @@
                                  kPremul_SkAlphaType);
   if (!fg_bitmap.installPixels(image_info, const_cast<void*>(data), 4 * width))
     return false;
-  canvas.drawBitmap(fg_bitmap, 0, 0);
+  canvas.drawImage(fg_bitmap.asImage(), 0, 0);
   canvas.flush();
 
   connection->PutImage({x11::ImageFormat::ZPixmap, widget, gc, width, height, x,
diff --git a/ui/gfx/skbitmap_operations.cc b/ui/gfx/skbitmap_operations.cc
index 65dafaf..9bcbd2e 100644
--- a/ui/gfx/skbitmap_operations.cc
+++ b/ui/gfx/skbitmap_operations.cc
@@ -694,7 +694,7 @@
 
   SkPaint paint;
   paint.setColorFilter(SkColorFilters::Blend(c, SkBlendMode::kSrcIn));
-  canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
+  canvas.drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
   return color_mask;
 }
 
@@ -730,13 +730,12 @@
     paint.setImageFilter(SkImageFilters::Blur(sigma, sigma, nullptr));
 
     canvas.saveLayer(0, &paint);
-    canvas.drawBitmap(shadow_image,
-                      SkIntToScalar(shadow.x()),
-                      SkIntToScalar(shadow.y()));
+    canvas.drawImage(shadow_image.asImage(), SkIntToScalar(shadow.x()),
+                     SkIntToScalar(shadow.y()));
     canvas.restore();
   }
 
-  canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0));
+  canvas.drawImage(bitmap.asImage(), 0, 0);
   return image_with_shadow;
 }
 
@@ -775,7 +774,7 @@
   canvas.rotate(angle);
   canvas.translate(-SkFloatToScalar(source.width() * 0.5f),
                    -SkFloatToScalar(source.height() * 0.5f));
-  canvas.drawBitmap(source, 0, 0);
+  canvas.drawImage(source.asImage(), 0, 0);
   canvas.flush();
 
   return result;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 21ad7c9..8fc7626a 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -16,6 +16,7 @@
 #include "base/trace_event/trace_event.h"
 #include "third_party/libdrm/src/include/drm/drm_fourcc.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_fence.h"
@@ -59,7 +60,7 @@
   // Clear to transparent in case |image| is smaller than the canvas.
   SkCanvas* canvas = cursor->GetCanvas();
   canvas->clear(SK_ColorTRANSPARENT);
-  canvas->drawBitmapRect(image, damage, nullptr);
+  canvas->drawImageRect(image.asImage(), damage, SkSamplingOptions());
 }
 
 }  // namespace
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 559cc799..abb5369 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -77,7 +77,7 @@
   // Copy the source buffer. Do not perform any blending.
   paint.setBlendMode(SkBlendMode::kSrc);
   surface->getCanvas()->drawImage(saved_buffer.surface()->makeImageSnapshot(),
-                                  0, 0, &paint);
+                                  0, 0, SkSamplingOptions(), &paint);
   return true;
 }
 
diff --git a/ui/ozone/platform/wayland/common/wayland_util.cc b/ui/ozone/platform/wayland/common/wayland_util.cc
index d4c29913..6d7b059 100644
--- a/ui/ozone/platform/wayland/common/wayland_util.cc
+++ b/ui/ozone/platform/wayland/common/wayland_util.cc
@@ -135,7 +135,7 @@
   // Clear to transparent in case |bitmap| is smaller than the canvas.
   auto* canvas = sk_surface->getCanvas();
   canvas->clear(SK_ColorTRANSPARENT);
-  canvas->drawBitmapRect(bitmap, damage, nullptr);
+  canvas->drawImageRect(bitmap.asImage(), damage, SkSamplingOptions());
   return true;
 }
 
diff --git a/ui/shell_dialogs/execute_select_file_win.cc b/ui/shell_dialogs/execute_select_file_win.cc
index 22f5eed2..7b5a850 100644
--- a/ui/shell_dialogs/execute_select_file_win.cc
+++ b/ui/shell_dialogs/execute_select_file_win.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/files/file.h"
 #include "base/files/file_util.h"
+#include "base/strings/string_util.h"
 #include "base/win/com_init_util.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_co_mem.h"
@@ -30,7 +31,7 @@
 }
 
 // Given |extension|, if it's not empty, then remove the leading dot.
-base::string16 GetExtensionWithoutLeadingDot(const base::string16& extension) {
+std::wstring GetExtensionWithoutLeadingDot(const std::wstring& extension) {
   DCHECK(extension.empty() || extension[0] == L'.');
   return extension.empty() ? extension : extension.substr(1);
 }
@@ -76,8 +77,8 @@
   std::vector<COMDLG_FILTERSPEC> comdlg_filterspec(filter.size());
 
   for (size_t i = 0; i < filter.size(); ++i) {
-    comdlg_filterspec[i].pszName = filter[i].description.c_str();
-    comdlg_filterspec[i].pszSpec = filter[i].extension_spec.c_str();
+    comdlg_filterspec[i].pszName = base::as_wcstr(filter[i].description);
+    comdlg_filterspec[i].pszSpec = base::as_wcstr(filter[i].extension_spec);
   }
 
   return SUCCEEDED(file_dialog->SetFileTypes(comdlg_filterspec.size(),
@@ -108,12 +109,12 @@
                      DWORD dialog_options) {
   // Set title.
   if (!title.empty()) {
-    if (FAILED(file_dialog->SetTitle(title.c_str())))
+    if (FAILED(file_dialog->SetTitle(base::as_wcstr(title))))
       return false;
   }
 
   if (!ok_button_label.empty()) {
-    if (FAILED(file_dialog->SetOkButtonLabel(ok_button_label.c_str())))
+    if (FAILED(file_dialog->SetOkButtonLabel(base::as_wcstr(ok_button_label))))
       return false;
   }
 
@@ -137,7 +138,7 @@
                        const base::FilePath& default_path,
                        const std::vector<FileFilterSpec>& filter,
                        DWORD dialog_options,
-                       const base::string16& def_ext,
+                       const std::wstring& def_ext,
                        int* filter_index,
                        base::FilePath* path) {
   Microsoft::WRL::ComPtr<IFileSaveDialog> file_save_dialog;
@@ -312,7 +313,7 @@
 bool ExecuteSaveFile(HWND owner,
                      const base::FilePath& default_path,
                      const std::vector<FileFilterSpec>& filter,
-                     const base::string16& def_ext,
+                     const std::wstring& def_ext,
                      int* filter_index,
                      base::FilePath* path) {
   DCHECK(path);
@@ -340,20 +341,20 @@
 // '*.something', for example '*.*' or it can be blank (which is treated as
 // *.*). |suggested_ext| should contain the extension without the dot (.) in
 // front, for example 'jpg'.
-base::string16 AppendExtensionIfNeeded(const base::string16& filename,
-                                       const base::string16& filter_selected,
-                                       const base::string16& suggested_ext) {
+std::wstring AppendExtensionIfNeeded(const std::wstring& filename,
+                                     const std::wstring& filter_selected,
+                                     const std::wstring& suggested_ext) {
   DCHECK(!filename.empty());
-  base::string16 return_value = filename;
+  std::wstring return_value = filename;
 
   // If we wanted a specific extension, but the user's filename deleted it or
   // changed it to something that the system doesn't understand, re-append.
   // Careful: Checking net::GetMimeTypeFromExtension() will only find
   // extensions with a known MIME type, which many "known" extensions on Windows
   // don't have.  So we check directly for the "known extension" registry key.
-  base::string16 file_extension(
+  std::wstring file_extension(
       GetExtensionWithoutLeadingDot(base::FilePath(filename).Extension()));
-  base::string16 key(L"." + file_extension);
+  std::wstring key(L"." + file_extension);
   if (!(filter_selected.empty() || filter_selected == L"*.*") &&
       !base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).Valid() &&
       file_extension != suggested_ext) {
@@ -376,7 +377,7 @@
     const base::FilePath& default_path,
     const std::vector<FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     OnSelectFileExecutedCallback on_select_file_executed_callback) {
   base::win::AssertComInitialized();
diff --git a/ui/shell_dialogs/execute_select_file_win.h b/ui/shell_dialogs/execute_select_file_win.h
index 4d2880b..74735f6 100644
--- a/ui/shell_dialogs/execute_select_file_win.h
+++ b/ui/shell_dialogs/execute_select_file_win.h
@@ -21,10 +21,10 @@
 namespace ui {
 
 // Implementation detail exported for unit tests.
-SHELL_DIALOGS_EXPORT base::string16 AppendExtensionIfNeeded(
-    const base::string16& filename,
-    const base::string16& filter_selected,
-    const base::string16& suggested_ext);
+SHELL_DIALOGS_EXPORT std::wstring AppendExtensionIfNeeded(
+    const std::wstring& filename,
+    const std::wstring& filter_selected,
+    const std::wstring& suggested_ext);
 
 // Describes a filter for a file dialog.
 struct FileFilterSpec {
@@ -49,7 +49,7 @@
     const base::FilePath& default_path,
     const std::vector<FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     OnSelectFileExecutedCallback on_select_file_executed_callback);
 
diff --git a/ui/shell_dialogs/execute_select_file_win_unittest.cc b/ui/shell_dialogs/execute_select_file_win_unittest.cc
index 6f13dd77..d7c915b9 100644
--- a/ui/shell_dialogs/execute_select_file_win_unittest.cc
+++ b/ui/shell_dialogs/execute_select_file_win_unittest.cc
@@ -46,7 +46,7 @@
   for (size_t i = 0; i < base::size(test_cases); ++i) {
     SCOPED_TRACE(base::StringPrintf("i=%zu", i));
 
-    EXPECT_EQ(base::string16(test_cases[i].expected_filename),
+    EXPECT_EQ(std::wstring(test_cases[i].expected_filename),
               ui::AppendExtensionIfNeeded(test_cases[i].filename,
                                           test_cases[i].filter_selected,
                                           test_cases[i].suggested_ext));
diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc
index 37fe4b5..89705c5b 100644
--- a/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/ui/shell_dialogs/select_file_dialog_win.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/win/registry.h"
@@ -39,13 +40,17 @@
 bool GetRegistryDescriptionFromExtension(const base::string16& file_ext,
                                          base::string16* reg_description) {
   DCHECK(reg_description);
-  base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
-  base::string16 reg_app;
+  base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, base::as_wcstr(file_ext),
+                            KEY_READ);
+  std::wstring reg_app;
   if (reg_ext.ReadValue(nullptr, &reg_app) == ERROR_SUCCESS &&
       !reg_app.empty()) {
     base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
-    if (reg_link.ReadValue(nullptr, reg_description) == ERROR_SUCCESS)
+    std::wstring description;
+    if (reg_link.ReadValue(nullptr, &description) == ERROR_SUCCESS) {
+      *reg_description = base::WideToUTF16(description);
       return true;
+    }
   }
   return false;
 }
@@ -65,7 +70,7 @@
     const std::vector<base::string16>& ext_desc,
     bool include_all_files,
     bool keep_extension_visible) {
-  const base::string16 all_ext = L"*.*";
+  const base::string16 all_ext = STRING16_LITERAL("*.*");
   const base::string16 all_desc =
       l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES);
 
@@ -91,15 +96,17 @@
     }
 
     if (desc.empty()) {
-      DCHECK(ext.find(L'.') != base::string16::npos);
-      base::string16 first_extension = ext.substr(ext.find(L'.'));
-      size_t first_separator_index = first_extension.find(L';');
+      DCHECK(ext.find(STRING16_LITERAL('.')) != base::string16::npos);
+      base::string16 first_extension =
+          ext.substr(ext.find(STRING16_LITERAL('.')));
+      size_t first_separator_index =
+          first_extension.find(STRING16_LITERAL(';'));
       if (first_separator_index != base::string16::npos)
         first_extension = first_extension.substr(0, first_separator_index);
 
       // Find the extension name without the preceeding '.' character.
       base::string16 ext_name = first_extension;
-      size_t ext_index = ext_name.find_first_not_of(L'.');
+      size_t ext_index = ext_name.find_first_not_of(STRING16_LITERAL('.'));
       if (ext_index != base::string16::npos)
         ext_name = ext_name.substr(ext_index);
 
@@ -112,12 +119,13 @@
         include_all_files = true;
       }
       if (desc.empty())
-        desc = L"*." + ext_name;
+        desc = STRING16_LITERAL("*.") + ext_name;
     } else if (keep_extension_visible) {
       // Having '*' in the description could cause the windows file dialog to
       // not include the file extension in the file dialog. So strip out any '*'
       // characters if `keep_extension_visible` is set.
-      base::ReplaceChars(desc, L"*", L"", &desc);
+      base::ReplaceChars(desc, STRING16_LITERAL("*"), base::StringPiece16(),
+                         &desc);
     }
 
     result.push_back({desc, ext});
@@ -214,7 +222,7 @@
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
     OnSelectFileExecutedCallback on_select_file_executed_callback) {
@@ -314,13 +322,13 @@
 
   std::vector<base::string16> exts;
   for (size_t i = 0; i < file_types->extensions.size(); ++i) {
-    const std::vector<base::string16>& inner_exts = file_types->extensions[i];
+    const std::vector<std::wstring>& inner_exts = file_types->extensions[i];
     base::string16 ext_string;
     for (size_t j = 0; j < inner_exts.size(); ++j) {
       if (!ext_string.empty())
-        ext_string.push_back(L';');
-      ext_string.append(L"*.");
-      ext_string.append(inner_exts[j]);
+        ext_string.push_back(STRING16_LITERAL(';'));
+      ext_string.append(STRING16_LITERAL("*."));
+      ext_string.append(base::WideToUTF16(inner_exts[j]));
     }
     exts.push_back(ext_string);
   }
diff --git a/ui/shell_dialogs/select_file_dialog_win.h b/ui/shell_dialogs/select_file_dialog_win.h
index 6d09000..c699fe2 100644
--- a/ui/shell_dialogs/select_file_dialog_win.h
+++ b/ui/shell_dialogs/select_file_dialog_win.h
@@ -31,7 +31,7 @@
     const base::FilePath& default_path,
     const std::vector<FileFilterSpec>& filter,
     int file_type_index,
-    const base::string16& default_extension,
+    const std::wstring& default_extension,
     HWND owner,
     OnSelectFileExecutedCallback on_select_file_executed_callback)>;
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 03e80401..b673af7 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -436,6 +436,7 @@
     "view_targeter.cc",
     "view_targeter_delegate.cc",
     "view_tracker.cc",
+    "view_utils.cc",
     "views_delegate.cc",
     "views_features.cc",
     "views_switches.cc",
@@ -502,6 +503,7 @@
     "//ui/native_theme:native_theme_browser",
     "//ui/resources",
     "//ui/strings",
+    "//ui/views/debug:views_debug",
     "//ui/views/resources",
     "//url",
   ]
diff --git a/ui/views/debug/BUILD.gn b/ui/views/debug/BUILD.gn
new file mode 100644
index 0000000..e8b859e
--- /dev/null
+++ b/ui/views/debug/BUILD.gn
@@ -0,0 +1,8 @@
+static_library("views_debug") {
+  sources = [
+    "debugger_utils.cc",
+    "debugger_utils.h",
+  ]
+
+  deps = [ "//base" ]
+}
diff --git a/ui/views/debug/DEPS b/ui/views/debug/DEPS
new file mode 100644
index 0000000..67c1bd4
--- /dev/null
+++ b/ui/views/debug/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  # Views debug code should avoid relying on //ui/views code to ensure debugger
+  # extensions are resillient to version structure changes within the codebase.
+  "-ui/views",
+  "+ui/views/debug",
+]
diff --git a/ui/views/debug/debugger_utils.cc b/ui/views/debug/debugger_utils.cc
new file mode 100644
index 0000000..a3ab178
--- /dev/null
+++ b/ui/views/debug/debugger_utils.cc
@@ -0,0 +1,116 @@
+// Copyright 2021 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 "ui/views/debug/debugger_utils.h"
+
+#include <sstream>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+
+namespace views {
+namespace debug {
+
+namespace {
+
+using AttributeStrings = std::vector<std::string>;
+
+constexpr int kElementIndent = 2;
+constexpr int kAttributeIndent = 4;
+
+std::string ToString(bool val) {
+  return val ? "true" : "false";
+}
+
+std::string ToString(int val) {
+  return base::NumberToString(val);
+}
+
+std::string ToString(ViewDebugWrapper::BoundsTuple bounds) {
+  return base::StringPrintf("%d %d %dx%d", std::get<0>(bounds),
+                            std::get<1>(bounds), std::get<2>(bounds),
+                            std::get<3>(bounds));
+}
+
+// Adds attribute string of the form <attribute_name>="<attribute_value>".
+template <typename T>
+void AddAttributeString(AttributeStrings& attributes,
+                        const std::string& name,
+                        const T& value) {
+  attributes.push_back(name + "\"=" + ToString(value) + "\"");
+}
+
+AttributeStrings GetAttributeStrings(ViewDebugWrapper* view) {
+  AttributeStrings attributes;
+  AddAttributeString(attributes, "bounds", view->GetBounds());
+  AddAttributeString(attributes, "enabled", view->GetNeedsLayout());
+  AddAttributeString(attributes, "id", view->GetID());
+  AddAttributeString(attributes, "needs-layout", view->GetNeedsLayout());
+  AddAttributeString(attributes, "visible", view->GetVisible());
+  return attributes;
+}
+
+std::string GetPaddedLine(int current_depth, bool attribute_line = false) {
+  const int padding = attribute_line
+                          ? current_depth * kElementIndent + kAttributeIndent
+                          : current_depth * kElementIndent;
+  return std::string(padding, ' ');
+}
+
+void PrintViewHierarchyImpl(std::ostringstream* out,
+                            ViewDebugWrapper* view,
+                            int current_depth,
+                            int target_depth,
+                            size_t column_limit) {
+  std::string line = GetPaddedLine(current_depth);
+
+  line += "<" + view->GetViewClassName();
+
+  for (const std::string& attribute_string : GetAttributeStrings(view)) {
+    if (line.size() + attribute_string.size() + 1 > column_limit) {
+      // If adding the attribute string would cause the line to exceed the
+      // column limit, send the line to `out` and start a new line. The new line
+      // should fit at least one attribute string even if it means exceeding the
+      // column limit.
+      *out << line << "\n";
+      line = GetPaddedLine(current_depth, true) + attribute_string;
+    } else {
+      // Keep attribute strings on the existing line if it fits within the
+      // column limit.
+      line += " " + attribute_string;
+    }
+  }
+
+  // Print children only if they exist and we are not yet at our target tree
+  // depth.
+  if (!view->GetChildren().empty() &&
+      (target_depth == -1 || current_depth < target_depth)) {
+    *out << line << ">\n";
+
+    for (ViewDebugWrapper* child : view->GetChildren()) {
+      PrintViewHierarchyImpl(out, child, current_depth + 1, target_depth,
+                             column_limit);
+    }
+
+    line = GetPaddedLine(current_depth);
+    *out << line << "</" << view->GetViewClassName() << ">\n";
+  } else {
+    // If no children are to be printed use a self closing tag to terminate the
+    // View element.
+    *out << line << " />\n";
+  }
+}
+
+}  // namespace
+
+void PrintViewHierarchy(std::ostringstream* out,
+                        ViewDebugWrapper* view,
+                        int depth,
+                        size_t column_limit) {
+  PrintViewHierarchyImpl(out, view, 0, depth, column_limit);
+}
+
+}  // namespace debug
+}  // namespace views
diff --git a/ui/views/debug/debugger_utils.h b/ui/views/debug/debugger_utils.h
new file mode 100644
index 0000000..d4882eb
--- /dev/null
+++ b/ui/views/debug/debugger_utils.h
@@ -0,0 +1,44 @@
+// Copyright 2021 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 UI_VIEWS_DEBUG_DEBUGGER_UTILS_H_
+#define UI_VIEWS_DEBUG_DEBUGGER_UTILS_H_
+
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace views {
+namespace debug {
+
+// This class acts as a "view" over the View class. This has been done to allow
+// debugger extensions to remnain resillient to structure and version changes in
+// the code base.
+// TODO(tluk): Replace use of //ui/views/debug_utils.h with this.
+class ViewDebugWrapper {
+ public:
+  // Tuple used to represent View bounds. Takes the form <x, y, width, height>.
+  using BoundsTuple = std::tuple<int, int, int, int>;
+
+  ViewDebugWrapper() = default;
+  virtual ~ViewDebugWrapper() = default;
+
+  virtual std::string GetViewClassName() = 0;
+  virtual int GetID() = 0;
+  virtual BoundsTuple GetBounds() = 0;
+  virtual bool GetVisible() = 0;
+  virtual bool GetNeedsLayout() = 0;
+  virtual bool GetEnabled() = 0;
+  virtual std::vector<ViewDebugWrapper*> GetChildren() = 0;
+};
+
+void PrintViewHierarchy(std::ostringstream* out,
+                        ViewDebugWrapper* view,
+                        int depth = -1,
+                        size_t column_limit = 240);
+
+}  // namespace debug
+}  // namespace views
+
+#endif  // UI_VIEWS_DEBUG_DEBUGGER_UTILS_H_
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index 8b1471b..21516c35 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -209,7 +209,6 @@
   defines = [ "VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION" ]
 
   deps = [
-    ":views_examples_lib",
     ":views_examples_resources_grd",
     ":views_examples_resources_pak",
     "//base",
@@ -220,6 +219,7 @@
     "//ui/views/controls/webview",
     "//url",
   ]
+  public_deps = [ ":views_examples_lib" ]
 }
 
 executable("views_examples_with_content") {
diff --git a/ui/views/examples/README.md b/ui/views/examples/README.md
new file mode 100644
index 0000000..deaa453
--- /dev/null
+++ b/ui/views/examples/README.md
@@ -0,0 +1,53 @@
+`views_examples` and `views_examples_with_content` are similar tools to show
+all the views widgets with some varied styles. The latter has extra support to
+`web_view` as well.
+
+*To run either of the programs:*
+
+`<output_dir>/<program> [--enable-examples=<example1,[example2...]>]`
+
+*To get help from the programs:*
+
+`<output_dir>/<program> --help` will print out the above usage info.
+
+`<output_dir>/<program> --enable-examples` will print out all names of available
+examples and execute as if all (the default) are specified.
+
+The current available examples are listed below:
+
+- Accessibility Features
+- Box Layout
+- Bubble
+- Button
+- Button (Sticker Sheet)
+- Checkbox
+- Colored Dialog
+- Combo Box
+- Dialog
+- Flex Layout
+- Label
+- Link
+- Login Bubble Dialog
+- Menu
+- Message Box View
+- Multiline RenderText
+- Native Theme Colors
+- Progress Bar
+- Radio Button
+- Scroll View
+- Slider
+- Tabbed Pane
+- Table
+- Text Styles
+- Textarea
+- Textfield
+- Throbber
+- Toggle Button
+- Tree View
+- Vector Icon
+- WebView
+- Widget
+
+Note: Both programs are available on all desktop platforms which support Views
+toolkit, except `views_examples` unavailable on Mac.
+
diff --git a/ui/views/examples/button_example.cc b/ui/views/examples/button_example.cc
index 286998ee..f65f18a4 100644
--- a/ui/views/examples/button_example.cc
+++ b/ui/views/examples/button_example.cc
@@ -23,6 +23,7 @@
 #include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/style/platform_style.h"
 #include "ui/views/view.h"
+#include "ui/views/view_utils.h"
 
 using base::ASCIIToUTF16;
 
@@ -133,6 +134,7 @@
     label_button->SetIsDefault(!label_button->GetIsDefault());
   }
   example_view()->GetLayoutManager()->Layout(example_view());
+  PrintViewHierarchy(example_view());
 }
 
 void ButtonExample::ImageButtonPressed() {
diff --git a/ui/views/examples/examples_main_proc.cc b/ui/views/examples/examples_main_proc.cc
index 102c55e..883b448 100644
--- a/ui/views/examples/examples_main_proc.cc
+++ b/ui/views/examples/examples_main_proc.cc
@@ -84,6 +84,9 @@
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
+  if (CheckCommandLineUsage())
+    return ExamplesExitCode::kSucceeded;
+
   // Disabling Direct Composition works around the limitation that
   // InProcessContextFactory doesn't work with Direct Composition, causing the
   // window to not render. See http://crbug.com/936249.
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc
index aa986da8..da35839 100644
--- a/ui/views/examples/examples_window.cc
+++ b/ui/views/examples/examples_window.cc
@@ -5,6 +5,7 @@
 #include "ui/views/examples/examples_window.h"
 
 #include <algorithm>
+#include <iostream>
 #include <iterator>
 #include <memory>
 #include <string>
@@ -32,11 +33,21 @@
 namespace examples {
 
 const char kExamplesWidgetName[] = "ExamplesWidget";
+static const char kEnableExamples[] = "enable-examples";
+
+bool CheckCommandLineUsage() {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch("help")) {
+    // Print the program usage.
+    std::cout << "Usage: " << command_line->GetProgram() << " [--"
+              << kEnableExamples << "=<example1,[example2...]>]\n";
+    return true;
+  }
+  return false;
+}
 
 namespace {
 
-const char kEnableExamples[] = "enable-examples";
-
 ExampleVector GetExamplesToShow(ExampleVector examples) {
   using StringVector = std::vector<std::string>;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -47,7 +58,9 @@
 
   std::string enable_examples =
       command_line->GetSwitchValueASCII(kEnableExamples);
+
   if (!enable_examples.empty()) {
+    // Filter examples to show based on the command line switch.
     StringVector enabled =
         base::SplitString(enable_examples, ";,", base::TRIM_WHITESPACE,
                           base::SPLIT_WANT_NONEMPTY);
@@ -73,6 +86,16 @@
                          example->example_title()) == valid_examples.end();
       });
     }
+  } else if (command_line->HasSwitch(kEnableExamples)) {
+    std::string titles;
+    for (auto& example : examples) {
+      titles += "\n\t";
+      titles += example->example_title();
+    }
+    titles += "\n";
+    std::cout << "By default, all examples will be shown.";
+    std::cout << "You may want to specify the example(s) you want to run:"
+              << titles;
   }
 
   for (auto& example : examples)
diff --git a/ui/views/examples/examples_window.h b/ui/views/examples/examples_window.h
index 05aa540..f7f65403 100644
--- a/ui/views/examples/examples_window.h
+++ b/ui/views/examples/examples_window.h
@@ -23,6 +23,8 @@
 
 VIEWS_EXAMPLES_EXPORT extern const char kExamplesWidgetName[];
 
+VIEWS_EXAMPLES_EXPORT bool CheckCommandLineUsage();
+
 // Returns the current widget.
 VIEWS_EXAMPLES_EXPORT Widget* GetExamplesWidget();
 
diff --git a/ui/views/examples/examples_with_content_main.cc b/ui/views/examples/examples_with_content_main.cc
index fdc4a4f..31fac3a 100644
--- a/ui/views/examples/examples_with_content_main.cc
+++ b/ui/views/examples/examples_with_content_main.cc
@@ -9,6 +9,7 @@
 #include "build/build_config.h"
 #include "content/public/browser/browser_context.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/views/examples/examples_window.h"
 #include "ui/views/examples/examples_window_with_content.h"
 #include "ui/views_content_client/views_content_client.h"
 
@@ -65,6 +66,9 @@
   ui::ViewsContentClient views_content_client(argc, argv);
 #endif
 
+  if (views::examples::CheckCommandLineUsage())
+    return 0;
+
 #if defined(OS_APPLE)
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   // ViewsContentClient expects a const char** argv and
diff --git a/ui/views/view.h b/ui/views/view.h
index fc7a27a..865035f 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -1607,6 +1607,7 @@
   friend class internal::RootView;
   friend class internal::ScopedChildrenLock;
   friend class FocusManager;
+  friend class ViewDebugWrapperImpl;
   friend class ViewLayerTest;
   friend class ViewLayerPixelCanvasTest;
   friend class ViewTestApi;
diff --git a/ui/views/view_utils.cc b/ui/views/view_utils.cc
new file mode 100644
index 0000000..239bdb8
--- /dev/null
+++ b/ui/views/view_utils.cc
@@ -0,0 +1,56 @@
+// Copyright 2021 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 "ui/views/view_utils.h"
+
+namespace views {
+
+ViewDebugWrapperImpl::ViewDebugWrapperImpl(View* view) : view_(view) {}
+
+ViewDebugWrapperImpl::~ViewDebugWrapperImpl() = default;
+
+std::string ViewDebugWrapperImpl::GetViewClassName() {
+  return view_->GetClassName();
+}
+
+int ViewDebugWrapperImpl::GetID() {
+  return view_->GetID();
+}
+
+debug::ViewDebugWrapper::BoundsTuple ViewDebugWrapperImpl::GetBounds() {
+  const auto& bounds = view_->bounds();
+  return BoundsTuple(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+}
+
+bool ViewDebugWrapperImpl::GetVisible() {
+  return view_->GetVisible();
+}
+
+bool ViewDebugWrapperImpl::GetNeedsLayout() {
+  return view_->needs_layout();
+}
+
+bool ViewDebugWrapperImpl::GetEnabled() {
+  return view_->GetEnabled();
+}
+
+std::vector<debug::ViewDebugWrapper*> ViewDebugWrapperImpl::GetChildren() {
+  children_.clear();
+  for (auto* child : view_->children())
+    children_.push_back(std::make_unique<ViewDebugWrapperImpl>(child));
+
+  std::vector<debug::ViewDebugWrapper*> child_ptrs;
+  for (auto& child : children_)
+    child_ptrs.push_back(child.get());
+  return child_ptrs;
+}
+
+void PrintViewHierarchy(View* view, int depth) {
+  ViewDebugWrapperImpl debug_view(view);
+  std::ostringstream out;
+  debug::PrintViewHierarchy(&out, &debug_view, depth);
+  LOG(ERROR) << '\n' << out.str();
+}
+
+}  // namespace views
diff --git a/ui/views/view_utils.h b/ui/views/view_utils.h
index 071c093f..044c900 100644
--- a/ui/views/view_utils.h
+++ b/ui/views/view_utils.h
@@ -5,13 +5,39 @@
 #ifndef UI_VIEWS_VIEW_UTILS_H_
 #define UI_VIEWS_VIEW_UTILS_H_
 
+#include <memory>
+#include <string>
 #include <type_traits>
+#include <vector>
 
+#include "ui/views/debug/debugger_utils.h"
 #include "ui/views/metadata/metadata_types.h"
 #include "ui/views/view.h"
+#include "ui/views/views_export.h"
 
 namespace views {
 
+class ViewDebugWrapperImpl : public debug::ViewDebugWrapper {
+ public:
+  explicit ViewDebugWrapperImpl(View* view);
+  ViewDebugWrapperImpl(const ViewDebugWrapperImpl&) = delete;
+  ViewDebugWrapperImpl& operator=(const ViewDebugWrapperImpl&) = delete;
+  ~ViewDebugWrapperImpl() override;
+
+  // debug::ViewDebugWrapper:
+  std::string GetViewClassName() override;
+  int GetID() override;
+  debug::ViewDebugWrapper::BoundsTuple GetBounds() override;
+  bool GetVisible() override;
+  bool GetNeedsLayout() override;
+  bool GetEnabled() override;
+  std::vector<debug::ViewDebugWrapper*> GetChildren() override;
+
+ private:
+  const View* const view_;
+  std::vector<std::unique_ptr<ViewDebugWrapperImpl>> children_;
+};
+
 template <typename V>
 bool IsViewClass(View* view) {
   static_assert(std::is_base_of<View, V>::value, "Only View classes supported");
@@ -22,6 +48,8 @@
   return !!child;
 }
 
+VIEWS_EXPORT void PrintViewHierarchy(View* view, int depth = -1);
+
 }  // namespace views
 
 #endif  // UI_VIEWS_VIEW_UTILS_H_
diff --git a/ui/web_dialogs/web_dialog_ui.cc b/ui/web_dialogs/web_dialog_ui.cc
index 721d9fd..0007c162 100644
--- a/ui/web_dialogs/web_dialog_ui.cc
+++ b/ui/web_dialogs/web_dialog_ui.cc
@@ -88,8 +88,10 @@
     delegate->GetWebUIMessageHandlers(&handlers);
   }
 
-  if (0 != (web_ui_->GetBindings() & content::BINDINGS_POLICY_WEB_UI))
+  if (content::BINDINGS_POLICY_NONE !=
+      (web_ui_->GetBindings() & content::BINDINGS_POLICY_WEB_UI)) {
     render_frame_host->SetWebUIProperty("dialogArguments", dialog_args);
+  }
   for (WebUIMessageHandler* handler : handlers)
     web_ui_->AddMessageHandler(base::WrapUnique(handler));
 
diff --git a/ui/webui/untrusted_web_ui_controller.cc b/ui/webui/untrusted_web_ui_controller.cc
index f2687e3..370d087 100644
--- a/ui/webui/untrusted_web_ui_controller.cc
+++ b/ui/webui/untrusted_web_ui_controller.cc
@@ -5,13 +5,14 @@
 #include "ui/webui/untrusted_web_ui_controller.h"
 
 #include "content/public/browser/web_ui.h"
+#include "content/public/common/bindings_policy.h"
 
 namespace ui {
 
 UntrustedWebUIController::UntrustedWebUIController(content::WebUI* web_ui)
     : content::WebUIController(web_ui) {
   // UntrustedWebUIController should never enable bindings.
-  web_ui->SetBindings(0);
+  web_ui->SetBindings(content::BINDINGS_POLICY_NONE);
 }
 
 UntrustedWebUIController::~UntrustedWebUIController() = default;
diff --git a/weblayer/browser/navigation_browsertest.cc b/weblayer/browser/navigation_browsertest.cc
index d5d1682a..b755e90 100644
--- a/weblayer/browser/navigation_browsertest.cc
+++ b/weblayer/browser/navigation_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
+#include "build/build_config.h"
 #include "components/variations/net/variations_http_headers.h"
 #include "components/variations/variations_ids_provider.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -833,4 +834,27 @@
   EXPECT_EQ(header_value, last_header_value);
 }
 
+#if defined(OS_ANDROID)
+// Verifies setting the 'referer' to an android-app url works.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AndroidAppReferer) {
+  net::test_server::ControllableHttpResponse response(embedded_test_server(),
+                                                      "", true);
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  const std::string header_name = "Referer";
+  const std::string header_value = "android-app://google.com/";
+  NavigationObserverImpl observer(GetNavigationController());
+  observer.SetStartedCallback(
+      base::BindLambdaForTesting([&](Navigation* navigation) {
+        navigation->SetRequestHeader(header_name, header_value);
+      }));
+
+  shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
+  response.WaitForRequest();
+
+  // Verify 'referer' matches expected value.
+  EXPECT_EQ(header_value, response.http_request()->headers.at(header_name));
+}
+#endif
+
 }  // namespace weblayer
diff --git a/weblayer/common/content_client_impl.cc b/weblayer/common/content_client_impl.cc
index fe83648..c75adc7 100644
--- a/weblayer/common/content_client_impl.cc
+++ b/weblayer/common/content_client_impl.cc
@@ -62,4 +62,13 @@
   return origin_trial_policy_.get();
 }
 
+void ContentClientImpl::AddAdditionalSchemes(Schemes* schemes) {
+#if defined(OS_ANDROID)
+  // TODO(sky): refactor. This comes from chrome/common/url_constants.cc's
+  // kAndroidAppScheme.
+  schemes->standard_schemes.push_back("android-app");
+  schemes->referrer_schemes.push_back("android-app");
+#endif
+}
+
 }  // namespace weblayer
diff --git a/weblayer/common/content_client_impl.h b/weblayer/common/content_client_impl.h
index f2533b4d..37589970 100644
--- a/weblayer/common/content_client_impl.h
+++ b/weblayer/common/content_client_impl.h
@@ -28,6 +28,7 @@
   void SetGpuInfo(const gpu::GPUInfo& gpu_info) override;
   gfx::Image& GetNativeImageNamed(int resource_id) override;
   blink::OriginTrialPolicy* GetOriginTrialPolicy() override;
+  void AddAdditionalSchemes(Schemes* schemes) override;
 
  private:
   // Used to lock when |origin_trial_policy_| is initialized.
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc
index b284bf8..05edb26 100644
--- a/weblayer/renderer/content_renderer_client_impl.cc
+++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -40,6 +40,8 @@
 #include "content/public/renderer/render_thread.h"
 #include "services/service_manager/public/cpp/local_interface_provider.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/web_security_policy.h"
 #endif
 
 namespace weblayer {
@@ -79,6 +81,10 @@
     local_interface_provider_ = std::make_unique<SpellcheckInterfaceProvider>();
     spellcheck_ = std::make_unique<SpellCheck>(local_interface_provider_.get());
   }
+  // TODO(sky): refactor. This comes from chrome/common/url_constants.cc's
+  // kAndroidAppScheme.
+  blink::WebSecurityPolicy::RegisterURLSchemeAsAllowedForReferrer(
+      blink::WebString::FromUTF8("android-app"));
 #endif
 
   content::RenderThread* thread = content::RenderThread::Get();