diff --git a/BUILD.gn b/BUILD.gn
index 5edf3f6..f93a89e0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -207,7 +207,7 @@
     ]
   }
 
-  if (is_win || (is_linux && !is_chromeos) || is_android) {
+  if (is_win || (is_linux && !is_chromeos_lacros) || is_android) {
     deps += [
       "//weblayer/shell:weblayer_shell",
       "//weblayer/test:weblayer_browsertests",
diff --git a/DEPS b/DEPS
index 6cd0aeb1..e1bacdaa 100644
--- a/DEPS
+++ b/DEPS
@@ -181,7 +181,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:1a022d3a4c50be4207ee93451255d71896416596',
+  'luci_go': 'git_revision:67aba6e3373bb0b9e3ef9871362045736cd29b6e',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -200,11 +200,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': '48a99420a2495a665a732a7fe335e93ec7a83418',
+  'skia_revision': '3f522b2688cef5010faa12fde9fa10a511086db0',
   # 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': '8040ad59abd7119457d5acbde8602fde8a5291e5',
+  'v8_revision': '961f93287f84e7e7a7f5ff8a43c7adf14ca7fc42',
   # 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.
@@ -212,7 +212,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '8420c5acaa568cacb7283116fce3ad283075166e',
+  'angle_revision': 'fcb6b5a5c55ee35d232f35bcfa9c35aefc00f89e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -275,7 +275,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': '3383020812d40c5b2839233c6817d2d8f84eff43',
+  'devtools_frontend_revision': 'a91304b7b16006cbf084e5cb7da6080b0c1cf62d',
   # 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.
@@ -327,7 +327,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.
-  'dawn_revision': '71279dcde7cd1b718b137b9ed0384803f347a359',
+  'dawn_revision': '4814bdbdeae40186a61dfb7494390e64820daa4f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -919,7 +919,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e62621d2eb8687b1677d9d3c7a0123298f9ecdea',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'dc7b108da629de39f923d510fc76ea2f58efa521',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1291,7 +1291,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8f8e2dc7d50fac8d40137e49c39d1a0c2cc10ed7',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '254ea334b65f8a7d5d4ab087f861df0572fa6af7',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1623,7 +1623,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d90991c959bad057c3109394079ce08097d66e43',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2a242a6da146fbdfc29108e7f663f8af10c4fe08',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 05fb2f7d..6b8ecb62 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3471,6 +3471,15 @@
     "//build/config/compiler:no_size_t_to_int_warning",
     "//build/config/compiler:noshadowing",
   ]
+
+  if (current_cpu == "arm64" &&
+      (is_linux || is_chromeos || is_android || is_fuchsia)) {
+    # base/ has access to the MTE intrinsics because it needs to use them,
+    # but they're not backwards compatible. Use base::CPU::has_mte()
+    # beforehand to confirm or use indirect functions (ifuncs) to select
+    # an MTE-specific implementation via at dynamic link-time.
+    cflags = [ "-march=armv8-a+memtag" ]
+  }
 }
 
 action("build_date") {
diff --git a/base/cpu.cc b/base/cpu.cc
index f2c52cb..b3d29a79 100644
--- a/base/cpu.cc
+++ b/base/cpu.cc
@@ -32,7 +32,12 @@
 
 #if defined(ARCH_CPU_ARM_FAMILY) && \
     (defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS))
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
 #include "base/files/file_util.h"
+// Temporary definitions until a new hwcap.h is pulled in.
+#define HWCAP2_MTE (1 << 18)
+#define HWCAP2_BTI (1 << 17)
 #endif
 
 #if defined(ARCH_CPU_X86_FAMILY)
@@ -82,28 +87,7 @@
 }  // namespace internal
 #endif  // defined(ARCH_CPU_X86_FAMILY)
 
-CPU::CPU()
-  : signature_(0),
-    type_(0),
-    family_(0),
-    model_(0),
-    stepping_(0),
-    ext_model_(0),
-    ext_family_(0),
-    has_mmx_(false),
-    has_sse_(false),
-    has_sse2_(false),
-    has_sse3_(false),
-    has_ssse3_(false),
-    has_sse41_(false),
-    has_sse42_(false),
-    has_popcnt_(false),
-    has_avx_(false),
-    has_avx2_(false),
-    has_aesni_(false),
-    has_non_stop_time_stamp_counter_(false),
-    is_running_in_vm_(false),
-    cpu_vendor_("unknown") {
+CPU::CPU() {
   Initialize();
 }
 
@@ -307,6 +291,14 @@
 #elif defined(ARCH_CPU_ARM_FAMILY)
 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
   cpu_brand_ = *CpuInfoBrand();
+
+#if defined(ARCH_CPU_ARM64)
+  // Check for Armv8.5-A BTI/MTE support, exposed via HWCAP2
+  unsigned long hwcap2 = getauxval(AT_HWCAP2);
+  has_mte_ = hwcap2 & HWCAP2_MTE;
+  has_bti_ = hwcap2 & HWCAP2_BTI;
+#endif
+
 #elif defined(OS_WIN)
   // Windows makes high-resolution thread timing information available in
   // user-space.
diff --git a/base/cpu.h b/base/cpu.h
index 2e2d29a..c66d053 100644
--- a/base/cpu.h
+++ b/base/cpu.h
@@ -30,7 +30,7 @@
 // Query information about the processor.
 class BASE_EXPORT CPU final {
  public:
-  CPU();
+  explicit CPU();
 
   enum IntelMicroArchitecture {
     PENTIUM,
@@ -70,6 +70,10 @@
   }
   bool is_running_in_vm() const { return is_running_in_vm_; }
 
+  // Armv8.5-A extensions for control flow and memory safety.
+  bool has_mte() const { return has_mte_; }
+  bool has_bti() const { return has_bti_; }
+
   IntelMicroArchitecture GetIntelMicroArchitecture() const;
   const std::string& cpu_brand() const { return cpu_brand_; }
 
@@ -131,27 +135,29 @@
   // Query the processor for CPUID information.
   void Initialize();
 
-  int signature_;  // raw form of type, family, model, and stepping
-  int type_;  // process type
-  int family_;  // family of the processor
-  int model_;  // model of processor
-  int stepping_;  // processor revision number
-  int ext_model_;
-  int ext_family_;
-  bool has_mmx_;
-  bool has_sse_;
-  bool has_sse2_;
-  bool has_sse3_;
-  bool has_ssse3_;
-  bool has_sse41_;
-  bool has_sse42_;
-  bool has_popcnt_;
-  bool has_avx_;
-  bool has_avx2_;
-  bool has_aesni_;
-  bool has_non_stop_time_stamp_counter_;
-  bool is_running_in_vm_;
-  std::string cpu_vendor_;
+  int signature_ = 0;  // raw form of type, family, model, and stepping
+  int type_ = 0;       // process type
+  int family_ = 0;     // family of the processor
+  int model_ = 0;      // model of processor
+  int stepping_ = 0;   // processor revision number
+  int ext_model_ = 0;
+  int ext_family_ = 0;
+  bool has_mmx_ = false;
+  bool has_sse_ = false;
+  bool has_sse2_ = false;
+  bool has_sse3_ = false;
+  bool has_ssse3_ = false;
+  bool has_sse41_ = false;
+  bool has_sse42_ = false;
+  bool has_popcnt_ = false;
+  bool has_avx_ = false;
+  bool has_avx2_ = false;
+  bool has_aesni_ = false;
+  bool has_mte_ = false;  // Armv8.5-A MTE (Memory Taggging Extension)
+  bool has_bti_ = false;  // Armv8.5-A BTI (Branch Target Identification)
+  bool has_non_stop_time_stamp_counter_ = false;
+  bool is_running_in_vm_ = false;
+  std::string cpu_vendor_ = "unknown";
   std::string cpu_brand_;
 };
 
diff --git a/base/cpu_unittest.cc b/base/cpu_unittest.cc
index fa245a1..b0403ef 100644
--- a/base/cpu_unittest.cc
+++ b/base/cpu_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/cpu.h"
+#include "base/logging.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -13,9 +14,9 @@
 // "undefined instruction" exceptions. That is, this test succeeds when this
 // test finishes without a crash.
 TEST(CPU, RunExtendedInstructions) {
-#if defined(ARCH_CPU_X86_FAMILY)
   // Retrieve the CPU information.
   base::CPU cpu;
+#if defined(ARCH_CPU_X86_FAMILY)
 
   ASSERT_TRUE(cpu.has_mmx());
   ASSERT_TRUE(cpu.has_sse());
@@ -65,7 +66,6 @@
     // Execute an AVX 2 instruction.
     __asm__ __volatile__("vpunpcklbw %%ymm0, %%ymm0, %%ymm0\n" : : : "xmm0");
   }
-
 // Visual C 32 bit and ClangCL 32/64 bit test.
 #elif defined(COMPILER_MSVC) && (defined(ARCH_CPU_32_BITS) || \
       (defined(ARCH_CPU_64_BITS) && defined(__clang__)))
@@ -113,6 +113,34 @@
   }
 #endif  // defined(COMPILER_GCC)
 #endif  // defined(ARCH_CPU_X86_FAMILY)
+
+#if defined(ARCH_CPU_ARM64)
+  // Check that the CPU is correctly reporting support for the Armv8.5-A memory
+  // tagging extension. The new MTE instructions aren't encoded in NOP space
+  // like BTI/Pointer Authentication and will crash older cores with a SIGILL if
+  // used incorrectly. This test demonstrates how it should be done and that
+  // this approach works.
+  if (cpu.has_mte()) {
+#if !defined(__ARM_FEATURE_MEMORY_TAGGING)
+    // In this section, we're running on an MTE-compatible core, but we're
+    // building this file without MTE support. Fail this test to indicate that
+    // there's a problem with the base/ build configuration.
+    GTEST_FAIL()
+        << "MTE support detected (but base/ built without MTE support)";
+#else
+    char ptr[32];
+    uint64_t val;
+    // Execute a trivial MTE instruction. Normally, MTE should be used via the
+    // intrinsics documented at
+    // https://developer.arm.com/documentation/101028/0012/10--Memory-tagging-intrinsics,
+    // this test uses the irg (Insert Random Tag) instruction directly to make
+    // sure that it's not optimized out by the compiler.
+    __asm__ __volatile__("irg %0, %1" : "=r"(val) : "r"(ptr));
+#endif  // __ARM_FEATURE_MEMORY_TAGGING
+  } else {
+    GTEST_SKIP();
+  }
+#endif  // ARCH_CPU_ARM64
 }
 
 // For https://crbug.com/249713
diff --git a/base/files/important_file_writer.h b/base/files/important_file_writer.h
index 6358d5b..9713150b3 100644
--- a/base/files/important_file_writer.h
+++ b/base/files/important_file_writer.h
@@ -120,6 +120,9 @@
 #if defined(UNIT_TEST)
   size_t previous_data_size() const { return previous_data_size_; }
 #endif
+  void set_previous_data_size(size_t previous_data_size) {
+    previous_data_size_ = previous_data_size;
+  }
 
  private:
   const OneShotTimer& timer() const {
diff --git a/base/json/json_file_value_serializer.cc b/base/json/json_file_value_serializer.cc
index 683259d7..9ff0737 100644
--- a/base/json/json_file_value_serializer.cc
+++ b/base/json/json_file_value_serializer.cc
@@ -55,12 +55,13 @@
 JSONFileValueDeserializer::JSONFileValueDeserializer(
     const base::FilePath& json_file_path,
     int options)
-    : json_file_path_(json_file_path), options_(options), last_read_size_(0U) {}
+    : json_file_path_(json_file_path), options_(options) {}
 
 JSONFileValueDeserializer::~JSONFileValueDeserializer() = default;
 
 int JSONFileValueDeserializer::ReadFileToString(std::string* json_string) {
   DCHECK(json_string);
+  last_read_size_ = 0u;
   if (!base::ReadFileToString(json_file_path_, json_string)) {
 #if defined(OS_WIN)
     int error = ::GetLastError();
diff --git a/base/json/json_file_value_serializer.h b/base/json/json_file_value_serializer.h
index f38cec2..11e37ce 100644
--- a/base/json/json_file_value_serializer.h
+++ b/base/json/json_file_value_serializer.h
@@ -94,7 +94,7 @@
 
   const base::FilePath json_file_path_;
   const int options_;
-  size_t last_read_size_;
+  size_t last_read_size_ = 0u;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueDeserializer);
 };
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 46281c9..a4b528b 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -3941,8 +3941,7 @@
       assert(_build_host_jar || _build_device_jar,
              "A host or device jar must be created to use bytecode rewriting")
 
-      _rewritten_jar =
-          string_replace(_unprocessed_jar_path, ".jar", "_rewritten.jar")
+      _rewritten_jar = "$target_out_dir/${target_name}_rewritten.jar"
       _rewritten_jar_target_name = "${target_name}__rewritten"
       _rewriter_path = root_build_dir + "/bin/helper/" +
                        get_label_info(invoker.bytecode_rewriter_target, "name")
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b31e75c..f1e0572 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1948,10 +1948,7 @@
   }
 
   if (is_apple) {
-    if (symbol_level == 2) {
-      # Mac dead code stripping requires symbols.
-      common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
-    }
+    common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
 
     if (is_official_build) {
       common_optimize_on_ldflags += [
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 12ca7df..7cf2363 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -233,8 +233,9 @@
     use_debug_fission == "default" || use_debug_fission || !use_debug_fission,
     "Invalid use_debug_fission.")
 if (use_debug_fission == "default") {
-  use_debug_fission = is_debug && !is_android && !is_fuchsia && !is_apple &&
-                      !is_win && (use_gold || use_lld) && cc_wrapper == ""
+  use_debug_fission = (is_android && is_official_build) ||
+                      (is_debug && !is_android && !is_fuchsia && !is_apple &&
+                       !is_win && (use_gold || use_lld) && cc_wrapper == "")
 }
 
 # If it wasn't manually set, set to an appropriate default.
diff --git a/build/config/mac/plist_util.py b/build/config/mac/plist_util.py
index e975083..4517788 100644
--- a/build/config/mac/plist_util.py
+++ b/build/config/mac/plist_util.py
@@ -126,7 +126,7 @@
   else:
     with open(path, 'wb') as f:
       plist_format = {'binary1': plistlib.FMT_BINARY, 'xml1': plistlib.FMT_XML}
-      plistlib.dump(data, f, fmt=plist_format[options.format])
+      plistlib.dump(data, f, fmt=plist_format[format])
 
 
 def MergePList(plist1, plist2):
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 3208790d..265801d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201126.0.1
+0.20201126.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 3208790d..e61f1e3 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201126.0.1
+0.20201126.2.1
diff --git a/build/nocompile.gni b/build/nocompile.gni
index 262b79b..0b5bf35 100644
--- a/build/nocompile.gni
+++ b/build/nocompile.gni
@@ -109,6 +109,10 @@
         "-Wno-implicit-int-float-conversion",
       ]
 
+      if (is_apple && host_os != "mac") {
+        args += [ "--target=x86_64-apple-macos" ]
+      }
+
       # Iterate over any extra include dirs and append them to the command line.
       if (defined(invoker.include_dirs)) {
         foreach(include_dir, invoker.include_dirs) {
diff --git a/chrome/VERSION b/chrome/VERSION
index d1470e58..f9d41dd6 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=89
 MINOR=0
-BUILD=4338
+BUILD=4339
 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml
index 5c438e7..293a922 100644
--- a/chrome/android/features/tab_ui/java/res/values/dimens.xml
+++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -38,7 +38,6 @@
     <dimen name="selection_tab_grid_toggle_button_inset">14dp</dimen>
     <dimen name="selection_tab_list_toggle_button_lateral_inset">18dp</dimen>
     <dimen name="selection_tab_list_toggle_button_vertical_inset">22dp</dimen>
-    <dimen name="tab_carousel_height">192dp</dimen>
     <dimen name="tab_carousel_card_width">168dp</dimen>
     <dimen name="tab_carousel_start_margin">-3dp</dimen>
     <dimen name="tasks_view_items_vertical_spacing">8dp</dimen>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index c0da234..457644b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -222,11 +222,9 @@
         }
 
         if (mode == TabListMode.CAROUSEL) {
-            // TODO(mattsimmons): Remove this height and let the parent determine the correct
-            //  height. This can be done once the width is dynamic as well in
-            //  TabCarouselViewHolder.
-            mRecyclerView.getLayoutParams().height =
-                    context.getResources().getDimensionPixelSize(R.dimen.tab_carousel_height);
+            ViewGroup.LayoutParams layoutParams = mRecyclerView.getLayoutParams();
+            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            mRecyclerView.setLayoutParams(layoutParams);
         }
 
         mRecyclerView.setAdapter(mAdapter);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
index 8e88132..0bc2cefb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
@@ -113,17 +113,17 @@
      * @param targetLanguage The language to translate into, in case translation might be needed.
      * @param fluentLanguages An ordered comma-separated list of ISO 639 language codes that
      *        the user can read fluently, or an empty string.
-     * @param doRelatedSearches Whether the activate the Related Searches functionality too.
      */
     void setResolveProperties(@NonNull String homeCountry, boolean doSendBasePageUrl,
             long previousEventId, int previousUserInteractions, @NonNull String targetLanguage,
-            @NonNull String fluentLanguages, boolean doRelatedSearches) {
+            @NonNull String fluentLanguages) {
+        // TODO(donnd): consider making this a constructor variation.
         mHasSetResolveProperties = true;
         mHomeCountry = homeCountry;
         mPreviousEventId = previousEventId;
         mPreviousUserInteractions = previousUserInteractions;
         ContextualSearchContextJni.get().setResolveProperties(getNativePointer(), this, homeCountry,
-                doSendBasePageUrl, previousEventId, previousUserInteractions, doRelatedSearches);
+                doSendBasePageUrl, previousEventId, previousUserInteractions);
         mTargetLanguage = targetLanguage;
         mFluentLanguages = fluentLanguages;
     }
@@ -271,10 +271,18 @@
     }
 
     /**
-     * Specifies that this search must be exact so the resolve must return a non-expanding result.
+     * Prepares the Context to be used in a Resolve request by supplying last minute parameters.
+     * If this call is not made before a Resolve then defaults are used (not exact and not a
+     * Related Search).
+     * @param isExactSearch Specifies whether this search must be exact -- meaning the resolve must
+     *        return a non-expanding result that matches the selection exactly.
+     * @param relatedSearchesStamp Information to be attached to the Resolve request that is needed
+     *        for Related Searches. If this string is empty then no Related Searches results will
+     *        be requested.
      */
-    void setExactResolve() {
-        ContextualSearchContextJni.get().setExactResolve(mNativePointer, this);
+    void prepareToResolve(boolean isExactSearch, String relatedSearchesStamp) {
+        ContextualSearchContextJni.get().prepareToResolve(
+                mNativePointer, this, isExactSearch, relatedSearchesStamp);
     }
 
     /**
@@ -587,7 +595,7 @@
         void destroy(long nativeContextualSearchContext, ContextualSearchContext caller);
         void setResolveProperties(long nativeContextualSearchContext,
                 ContextualSearchContext caller, String homeCountry, boolean doSendBasePageUrl,
-                long previousEventId, int previousEventResults, boolean doRelatedSearches);
+                long previousEventId, int previousEventResults);
         void adjustSelection(long nativeContextualSearchContext, ContextualSearchContext caller,
                 int startAdjust, int endAdjust);
         void setContent(long nativeContextualSearchContext, ContextualSearchContext caller,
@@ -596,6 +604,7 @@
         void setTranslationLanguages(long nativeContextualSearchContext,
                 ContextualSearchContext caller, String detectedLanguage, String targetLanguage,
                 String fluentLanguages);
-        void setExactResolve(long nativeContextualSearchContext, ContextualSearchContext caller);
+        void prepareToResolve(long nativeContextualSearchContext, ContextualSearchContext caller,
+                boolean isExactSearch, String relatedSearchesStamp);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index 825cd18..12407f3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -33,6 +33,17 @@
     private static final String DISABLED_PARAM = "disabled";
     private static final String ENABLED_VALUE = "true";
 
+    //==========================================================================================
+    // Related Searches FieldTrial and parameter names.
+    //==========================================================================================
+    // Params used elsewhere but gathered here since they may be present in FieldTrial configs.
+    static final String RELATED_SEARCHES_NEEDS_URL_PARAM_NAME = "needs_url";
+    static final String RELATED_SEARCHES_NEEDS_CONTENT_PARAM_NAME = "needs_content";
+    // A comma-separated list of lower-case ISO 639 language codes.
+    static final String RELATED_SEARCHES_LANGUAGE_ALLOWLIST_PARAM_NAME = "language_allowlist";
+    private static final String RELATED_SEARCHES_CONFIG_STAMP_PARAM_NAME = "stamp";
+
+    // Deprecated.
     private static final int MANDATORY_PROMO_DEFAULT_LIMIT = 10;
 
     // Cached values to avoid repeated and redundant JNI operations.
@@ -271,6 +282,37 @@
         return sSettings[value].intValue();
     }
 
+    /**
+     * Gets the "stamp" parameter from the RelatedSearches FieldTrial feature.
+     * @return The stamp parameter from the feature. If no stamp param is present then an empty
+     *         string is returned.
+     */
+    static String getRelatedSearchesExperiementConfigurationStamp() {
+        return getRelatedSearchesParam(RELATED_SEARCHES_CONFIG_STAMP_PARAM_NAME);
+    }
+
+    /**
+     * Gets the given parameter from the RelatedSearches FieldTrial feature.
+     * @param paramName The name of the parameter to get.
+     * @return The value of the parameter from the feature. If no param is present then an empty
+     *         string is returned.
+     */
+    static String getRelatedSearchesParam(String paramName) {
+        return ChromeFeatureList.getFieldTrialParamByFeature(
+                ChromeFeatureList.RELATED_SEARCHES, paramName);
+    }
+
+    /**
+     * Determines whether the specified parameter is present and enabled in the RelatedSearches
+     * Feature.
+     * @param relatedSearchesParamName The name of the param to get from the Feature.
+     * @return Whether the given parameter is enabled or not (has a value of "true").
+     */
+    static boolean isRelatedSearchesParamEnabled(String relatedSearchesParamName) {
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                ChromeFeatureList.RELATED_SEARCHES, relatedSearchesParamName, false);
+    }
+
     // --------------------------------------------------------------------------------------------
     // Helpers.
     // --------------------------------------------------------------------------------------------
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 84509ce..fa4df33 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -526,7 +526,8 @@
     public void startSearchTermResolutionRequest(String selection, boolean isExactResolve) {
         WebContents baseWebContents = getBaseWebContents();
         if (baseWebContents != null && mContext != null && mContext.canResolve()) {
-            if (isExactResolve) mContext.setExactResolve();
+            mContext.prepareToResolve(
+                    isExactResolve, mPolicy.getRelatedSearchesStamp((getBasePageLanguage())));
             ContextualSearchManagerJni.get().startSearchTermResolutionRequest(
                     mNativeContextualSearchManagerPtr, this, mContext, getBaseWebContents());
             ContextualSearchUma.logResolveRequested(mSelectionController.isTapSelection());
@@ -644,6 +645,7 @@
                 mInternalStateController.reset(StateChangeReason.UNKNOWN);
             } else {
                 mContext.setSurroundingText(encoding, surroundingText, startOffset, endOffset);
+                mPolicy.logRelatedSearchesQualifiedUsers(getBasePageLanguage());
                 mInternalStateController.notifyFinishedWorkOn(InternalState.GATHERING_SURROUNDINGS);
             }
         }
@@ -1617,7 +1619,7 @@
                     mContext.setResolveProperties(mPolicy.getHomeCountry(mActivity),
                             mPolicy.doSendBasePageUrl(), interaction.getEventId(),
                             interaction.getEncodedUserInteractions(), targetLanguage,
-                            fluentLanguages, mPolicy.doRelatedSearches());
+                            fluentLanguages);
                 }
                 WebContents webContents = getBaseWebContents();
                 if (webContents != null) {
@@ -1832,6 +1834,13 @@
                 enabled ? CONTEXTUAL_SEARCH_ENABLED : CONTEXTUAL_SEARCH_DISABLED);
     }
 
+    // Private helper functions
+
+    /** @return The language of the base page being viewed by the user. */
+    private String getBasePageLanguage() {
+        return mContext.getDetectedLanguage();
+    }
+
     private static PrefService getPrefService() {
         return UserPrefs.get(Profile.getLastUsedRegularProfile());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
index fdc50666..6fe3ad6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -42,7 +42,16 @@
     private static final String PATH_AMP = "/amp/";
     private static final int REMAINING_NOT_APPLICABLE = -1;
     private static final int TAP_TRIGGERED_PROMO_LIMIT = 50;
+    // Related Searches "stamp" building and accessing details.
+    private static final String RELATED_SEARCHES_STAMP_VERSION = "1";
+    private static final String RELATED_SEARCHES_EXPERIMENT_RECIPE_STAGE = "R";
+    private static final String RELATED_SEARCHES_NO_EXPERIMENT = "n";
+    private static final String RELATED_SEARCHES_LANGUAGE_RESTRICTION = "l";
+    private static final String RELATED_SEARCHES_DARK_LAUNCH = "d";
+    private static final String NO_EXPERIMENT_STAMP = RELATED_SEARCHES_STAMP_VERSION
+            + RELATED_SEARCHES_EXPERIMENT_RECIPE_STAGE + RELATED_SEARCHES_NO_EXPERIMENT;
 
+    // TODO(donnd): remove -- deprecated.
     private static final HashSet<String> PREDOMINENTLY_ENGLISH_SPEAKING_COUNTRIES =
             CollectionUtil.newHashSet("GB", "US");
 
@@ -296,6 +305,8 @@
      */
     void logCurrentState() {
         ContextualSearchUma.logPreferenceState();
+        ContextualSearchUma.logRelatedSearchesPermissionsForAllUsers(
+                hasSendUrlPermissions(), canSendSurroundings());
 
         // Log the number of promo taps remaining.
         int promoTapsRemaining = getPromoTapsRemaining();
@@ -333,6 +344,19 @@
     }
 
     /**
+     * Logs whether the current user is qualified to do Related Searches requests. This does not
+     * check if Related Searches is actually enabled for the current user, only whether they are
+     * qualified. We use this to gauge whether each group has a balanced number of qualified users.
+     * Can be logged multiple times since we'll just look at the user-count of this histogram.
+     * @param basePageLanguage The language of the page, to check if supported by the server.
+     */
+    void logRelatedSearchesQualifiedUsers(String basePageLanguage) {
+        if (isQualifiedForRelatedSearches(basePageLanguage)) {
+            ContextualSearchUma.logRelatedSearchesQualifiedUsers();
+        }
+    }
+
+    /**
      * Whether this request should include sending the URL of the base page to the server.
      * Several conditions are checked to make sure it's OK to send the URL, but primarily this is
      * based on whether the user has checked the setting for "Make searches and browsing better".
@@ -358,6 +382,15 @@
             return false;
         }
 
+        return hasSendUrlPermissions();
+    }
+
+    /**
+     * Determines whether the user has given permission to send URLs through the "Make searches and
+     * browsing better" user setting.
+     * @return Whether we can send a URL.
+     */
+    private boolean hasSendUrlPermissions() {
         // Check whether the user has enabled anonymous URL-keyed data collection.
         // This is surfaced on the relatively new "Make searches and browsing better" user setting.
         // In case an experiment is active for the legacy UI call through the unified consent
@@ -440,6 +473,10 @@
                 ChromePreferenceKeys.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_COUNT);
     }
 
+    // --------------------------------------------------------------------------------------------
+    // Additional considerations.
+    // --------------------------------------------------------------------------------------------
+
     /**
      * @return The ISO country code for the user's home country, or an empty string if not
      *         available or privacy-enabled.
@@ -482,15 +519,130 @@
     // --------------------------------------------------------------------------------------------
 
     /**
-     * @return Whether the experimental Feature for Related Searches is enabled.
+     * Gets the runtime processing stamp for Related Searches. This typically gets the value from
+     * a param from a Field Trial Feature.
+     * @param basePageLanguage The language of the page, to check for server support.
+     * @return A {@code String} whose value describes the schema version and current processing
+     *         of Related Searches, or an empty string if the user is not qualified to request
+     *         Related Searches or the feature is not enabled.
      */
-    boolean isRelatedSearchesEnabled() {
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES);
+    String getRelatedSearchesStamp(String basePageLanguage) {
+        if (!isRelatedSearchesQualifiedAndEnabled(basePageLanguage)) return "";
+
+        boolean isLanguageRestricted =
+                !TextUtils.isEmpty(ContextualSearchFieldTrial.getRelatedSearchesParam(
+                        ContextualSearchFieldTrial.RELATED_SEARCHES_LANGUAGE_ALLOWLIST_PARAM_NAME));
+        return buildRelatedSearchesStamp(isLanguageRestricted);
     }
 
-    /** @return whether doing Related Searches should be part of processing the current request. */
-    boolean doRelatedSearches() {
-        return isRelatedSearchesEnabled();
+    /**
+     * Checks if the current user is both qualified to do Related Searches and has the feature
+     * enabled. Qualifications may include restrictions on language during early development.
+     * @param basePageLanguage The language of the page, to check for server support.
+     * @return Whether the user is qualified to get Related Searches suggestions and the
+     *         experimental feature is enabled.
+     */
+    boolean isRelatedSearchesQualifiedAndEnabled(String basePageLanguage) {
+        return isQualifiedForRelatedSearches(basePageLanguage)
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES);
+    }
+
+    /**
+     * Determines if the current user is qualified for Related Searches. There may be language
+     * and privacy restrictions on whether users can activate Related Searches, and some of these
+     * requirements are determined at runtime based on Variations params.
+     * @param basePageLanguage The language of the page, to check for server support.
+     * @return Whether the user could do a Related Searches request if Feature-enabled.
+     */
+    private boolean isQualifiedForRelatedSearches(String basePageLanguage) {
+        return isLanguageQualified(basePageLanguage) && canSendUrlIfNeeded()
+                && canSendContentIfNeeded();
+    }
+
+    /**
+     * Checks if the language of the page qualifies for Related Searches.
+     * We check the Variations config for a parameter that lists allowed languages so we can know
+     * what the server currently supports. If there's no allow list then any language will work.
+     * @param basePageLanguage The language of the page, to check for server support.
+     * @return whether the supplied parameter satisfies the current language requirement.
+     */
+    private boolean isLanguageQualified(String basePageLanguage) {
+        String allowedLanguages = ContextualSearchFieldTrial.getRelatedSearchesParam(
+                ContextualSearchFieldTrial.RELATED_SEARCHES_LANGUAGE_ALLOWLIST_PARAM_NAME);
+        return TextUtils.isEmpty(allowedLanguages) || allowedLanguages.contains(basePageLanguage);
+    }
+
+    /**
+     * @return whether the user's privacy setting for URL sending satisfies the configured
+     *         requirement.
+     */
+    private boolean canSendUrlIfNeeded() {
+        return !isRelatedSearchesUrlNeeded() || hasSendUrlPermissions();
+    }
+
+    /**
+     * @return whether the user's privacy setting for page content sending satisfies the configured
+     *         requirement.
+     */
+    private boolean canSendContentIfNeeded() {
+        return !isRelatedSearchesContentNeeded() || !isUserUndecided();
+    }
+
+    /** @return whether the runtime configuration has a URL sending permissions requirement. */
+    private boolean isRelatedSearchesUrlNeeded() {
+        return isRelatedSearchesParamEnabled(
+                       ContextualSearchFieldTrial.RELATED_SEARCHES_NEEDS_URL_PARAM_NAME)
+                || isMissingRelatedSearchesConfiguration();
+    }
+
+    /**
+     * @return whether the runtime configuration has a page content sending permissions
+     *         requirement.
+     */
+    private boolean isRelatedSearchesContentNeeded() {
+        return isRelatedSearchesParamEnabled(
+                       ContextualSearchFieldTrial.RELATED_SEARCHES_NEEDS_CONTENT_PARAM_NAME)
+                || isMissingRelatedSearchesConfiguration();
+    }
+
+    /**
+     * @return whether the given parameter is currently enabled in the Related Searches Variation
+     *         configuration.
+     */
+    private boolean isRelatedSearchesParamEnabled(String paramName) {
+        return ContextualSearchFieldTrial.isRelatedSearchesParamEnabled(paramName);
+    }
+
+    /** @return whether we're missing the Related Searches configuration stamp. */
+    private boolean isMissingRelatedSearchesConfiguration() {
+        return TextUtils.isEmpty(
+                ContextualSearchFieldTrial.getRelatedSearchesExperiementConfigurationStamp());
+    }
+
+    /**
+     * Builds the "stamp" that tracks the processing of Related Searches and describes what was
+     * done at each stage using a shorthand notation. The notation is described in go/rsearches-dd
+     * here: http://doc/1DryD8NAP5LQAo326LnxbqkIDCNfiCOB7ak3gAYaNWAM#bookmark=id.nx7ivu2upqw
+     * <p>The first stage is built here: "1" for schema version one, "R" for the configuration
+     * Recipe which has a character describing how we'll formulate the search. Typically all of
+     * this comes from the Variations config at runtime. We programmatically append an "l" that
+     * indicates a language restriction (when present), and currently a "d" for "dark launch" so
+     * the server knows to return normal Contextual Search results for this older client.
+     * @param isLanguageRestricted Whether there are any language restrictions needed by the
+     *        server.
+     * @return A string that represents and encoded description of the current request processing.
+     */
+    private String buildRelatedSearchesStamp(boolean isLanguageRestricted) {
+        String experimentConfigStamp =
+                ContextualSearchFieldTrial.getRelatedSearchesExperiementConfigurationStamp();
+        if (TextUtils.isEmpty(experimentConfigStamp)) experimentConfigStamp = NO_EXPERIMENT_STAMP;
+        // TODO(donnd): Consider supporting URL-only requests -- for now content is required.
+        StringBuilder stampBuilder = new StringBuilder().append(experimentConfigStamp);
+        if (isLanguageRestricted) stampBuilder.append(RELATED_SEARCHES_LANGUAGE_RESTRICTION);
+        // Hard code a tag so the server knows this version of the client is doing a dark launch
+        // and cannot decode Related Searches.
+        stampBuilder.append(RELATED_SEARCHES_DARK_LAUNCH);
+        return stampBuilder.toString();
     }
 
     // --------------------------------------------------------------------------------------------
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
index f1ef739..053b5a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -333,6 +333,22 @@
         int NUM_ENTRIES = 3;
     }
 
+    // Constants for user permissions histogram.
+    @IntDef({
+            Permissions.SEND_NOTHING,
+            Permissions.SEND_URL,
+            Permissions.SEND_CONTENT,
+            Permissions.SEND_URL_AND_CONTENT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Permissions {
+        int SEND_NOTHING = 0;
+        int SEND_URL = 1;
+        int SEND_CONTENT = 2;
+        int SEND_URL_AND_CONTENT = 3;
+        int NUM_ENTRIES = 4;
+    }
+
     /**
      * Key used in maps from {state, reason} to state entry (exit) logging code.
      */
@@ -1615,6 +1631,43 @@
     }
 
     /**
+     * Logs a histogram indicating which privacy permissions are available that Related Searches
+     * cares about. This ignores any language constraint.
+     * <p>This can be called multiple times for each user from any part of the code that's freqently
+     * executed.
+     * @param canSendUrl Whether this user has allowed sending page URL info to Google.
+     * @param canSendContent Whether the user can send page content to Google (has accepted the
+     *        Contextual Search opt-in).
+     */
+    static void logRelatedSearchesPermissionsForAllUsers(
+            boolean canSendUrl, boolean canSendContent) {
+        @Permissions
+        int permissionsEnum;
+        if (canSendUrl) {
+            permissionsEnum =
+                    canSendContent ? Permissions.SEND_URL_AND_CONTENT : Permissions.SEND_URL;
+        } else {
+            permissionsEnum = canSendContent ? Permissions.SEND_CONTENT : Permissions.SEND_NOTHING;
+        }
+        RecordHistogram.recordEnumeratedHistogram("Search.RelatedSearches.AllUserPermissions",
+                permissionsEnum, Permissions.NUM_ENTRIES);
+    }
+
+    /**
+     * Logs a histogram indicating that a user is qualified for the Related Searches experiment
+     * regardless of whether that feature is enabled. This uses a boolean histogram but always
+     * logs true in order to get a raw bucket count (without using a user action, as suggested
+     * in the User Action Guidelines doc).
+     * <p>We use this to gauge whether each group has a balanced number of qualified users.
+     * Can be logged multiple times since we'll just look at the user-count of this histogram.
+     * This should be called any time a gesture is detected that could trigger a Related Search
+     * if the feature were enabled.
+     */
+    static void logRelatedSearchesQualifiedUsers() {
+        RecordHistogram.recordBooleanHistogram("Search.RelatedSearches.QualifiedUsers", true);
+    }
+
+    /**
      * Gets the state-change code for the given parameters by doing a lookup in the given map.
      * @param state The panel state.
      * @param reason The reason the state changed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestFactory.java
index 9ba08ff..62c31d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestFactory.java
@@ -162,8 +162,7 @@
         WebContents webContents = WebContentsStatics.fromRenderFrameHost(mRenderFrameHost);
         if (webContents == null || webContents.isDestroyed()) return new InvalidPaymentRequest();
 
-        return PaymentRequestService.createPaymentRequest(mRenderFrameHost,
-                /*isOffTheRecord=*/delegate.isOffTheRecord(), delegate,
+        return PaymentRequestService.createPaymentRequest(mRenderFrameHost, delegate,
                 (paymentRequestService)
                         -> new ChromePaymentRequestService(paymentRequestService, delegate));
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
index e42ddaf..c4a596e2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
@@ -9,17 +9,20 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.util.concurrent.TimeoutException;
@@ -30,9 +33,15 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@Batch(Batch.PER_CLASS)
 public class LevelDBPersistedTabDataStorageTest {
+    @ClassRule
+    public static ChromeTabbedActivityTestRule mActivityTestRule =
+            new ChromeTabbedActivityTestRule();
+
     @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+    public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule =
+            new BlankCTATabInitialStateRule(mActivityTestRule, false);
 
     private static final int TAB_ID_1 = 1;
     private static final String DATA_ID_1 = "DataId1";
@@ -47,7 +56,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mActivityTestRule.startMainActivityOnBlankPage();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mPersistedTabDataStorage =
                     new LevelDBPersistedTabDataStorage(Profile.getLastUsedRegularProfile());
@@ -121,13 +129,12 @@
         CallbackHelper ch = new CallbackHelper();
         int chCount = ch.getCallCount();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mPersistedTabDataStorage.setOnCompleteForTesting(new Runnable() {
+            mPersistedTabDataStorage.saveForTesting(tabId, dataId, data, new Runnable() {
                 @Override
                 public void run() {
                     ch.notifyCalled();
                 }
             });
-            mPersistedTabDataStorage.save(tabId, dataId, data);
         });
         ch.waitForCallback(chCount);
     }
@@ -147,13 +154,12 @@
         CallbackHelper ch = new CallbackHelper();
         int chCount = ch.getCallCount();
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            mPersistedTabDataStorage.setOnCompleteForTesting(new Runnable() {
+            mPersistedTabDataStorage.deleteForTesting(tabId, dataId, new Runnable() {
                 @Override
                 public void run() {
                     ch.notifyCalled();
                 }
             });
-            mPersistedTabDataStorage.delete(tabId, dataId);
         });
         ch.waitForCallback(chCount);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContextTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContextTest.java
index 18d2b740..987892e 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContextTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContextTest.java
@@ -84,13 +84,13 @@
 
     private void setupResolvingTapInBarak() {
         setupTapInBarack();
-        mContext.setResolveProperties(HOME_COUNTRY, true, 0, 0, "", "", false);
+        mContext.setResolveProperties(HOME_COUNTRY, true, 0, 0, "", "");
     }
 
     private void setupResolvingTapInObama() {
         int obamaBeforeMOffset = "Now Barack Oba".length();
         mContext.setSurroundingText(SAMPLE_TEXT, obamaBeforeMOffset, obamaBeforeMOffset);
-        mContext.setResolveProperties(HOME_COUNTRY, true, 0, 0, "", "", false);
+        mContext.setResolveProperties(HOME_COUNTRY, true, 0, 0, "", "");
     }
 
     @Test
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8e92d67..fccea13 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -6306,10 +6306,6 @@
     deps += [ "//device/udev_linux" ]
   }
 
-  if (tpm_fallback) {
-    defines += [ "TPM_FALLBACK" ]
-  }
-
   if (!is_android && !is_official_build) {
     deps += [ "//chrome/browser/ui/webui/new_tab_page/foo:mojo_bindings" ]
   }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index fdbf07f..cea464ec 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3708,6 +3708,14 @@
      flag_descriptions::kCrosLanguageSettingsUpdateName,
      flag_descriptions::kCrosLanguageSettingsUpdateDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kLanguageSettingsUpdate)},
+    {"enable-cros-multilingual-typing",
+     flag_descriptions::kMultilingualTypingName,
+     flag_descriptions::kMultilingualTypingDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kMultilingualTyping)},
+    {"enable-cros-on-device-grammar-check",
+     flag_descriptions::kCrosOnDeviceGrammarCheckName,
+     flag_descriptions::kCrosOnDeviceGrammarCheckDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kOnDeviceGrammarCheck)},
     {"enable-cros-system-latin-physical-typing",
      flag_descriptions::kSystemLatinPhysicalTypingName,
      flag_descriptions::kSystemLatinPhysicalTypingDescription, kOsCrOS,
diff --git a/chrome/browser/android/contextualsearch/contextual_search_context.cc b/chrome/browser/android/contextualsearch/contextual_search_context.cc
index b97dffb75..2c7a8598 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_context.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_context.cc
@@ -51,14 +51,12 @@
     const base::android::JavaParamRef<jstring>& j_home_country,
     jboolean j_may_send_base_page_url,
     jlong j_previous_event_id,
-    jint j_previous_event_results,
-    jboolean j_do_related_searches) {
+    jint j_previous_event_results) {
   can_resolve_ = true;
   home_country_ = base::android::ConvertJavaStringToUTF8(env, j_home_country);
   can_send_base_page_url_ = j_may_send_base_page_url;
   previous_event_id_ = j_previous_event_id;
   previous_event_results_ = j_previous_event_results;
-  do_related_searches_ = j_do_related_searches;
 }
 
 void ContextualSearchContext::SetContent(
@@ -144,20 +142,25 @@
   return end_offset_;
 }
 
-void ContextualSearchContext::SetExactResolve(
+void ContextualSearchContext::PrepareToResolve(
     JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
-  is_exact_resolve_ = true;
+    const base::android::JavaParamRef<jobject>& obj,
+    jboolean j_is_exact_resolve,
+    const base::android::JavaParamRef<jstring>& j_related_searches_stamp) {
+  is_exact_resolve_ = j_is_exact_resolve;
+  related_searches_stamp_ =
+      base::android::ConvertJavaStringToUTF8(env, j_related_searches_stamp);
+  do_related_searches_ = !related_searches_stamp_.empty();
 }
 
-bool ContextualSearchContext::GetExactResolve() {
+bool ContextualSearchContext::GetExactResolve() const {
   return is_exact_resolve_;
 }
 
 base::android::ScopedJavaLocalRef<jstring>
 ContextualSearchContext::DetectLanguage(
     JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
+    const base::android::JavaParamRef<jobject>& obj) const {
   std::string language = GetReliableLanguage(GetSelection());
   if (language.empty())
     language = GetReliableLanguage(this->surrounding_text_);
@@ -181,12 +184,12 @@
 }
 
 const ContextualSearchContext::TranslationLanguages&
-ContextualSearchContext::GetTranslationLanguages() {
+ContextualSearchContext::GetTranslationLanguages() const {
   return translation_languages_;
 }
 
 std::string ContextualSearchContext::GetReliableLanguage(
-    const base::string16& contents) {
+    const base::string16& contents) const {
   std::string content_language;
   std::string html_lang;
   std::string cld_language;
@@ -199,7 +202,7 @@
   return language;
 }
 
-base::string16 ContextualSearchContext::GetSelection() {
+base::string16 ContextualSearchContext::GetSelection() const {
   int start = this->start_offset_;
   int end = this->end_offset_;
   DCHECK(start >= 0);
@@ -209,10 +212,14 @@
   return this->surrounding_text_.substr(start, end - start);
 }
 
-bool ContextualSearchContext::GetRelatedSearches() {
+bool ContextualSearchContext::GetRelatedSearches() const {
   return do_related_searches_;
 }
 
+const std::string ContextualSearchContext::GetRelatedSearchesStamp() const {
+  return related_searches_stamp_;
+}
+
 // Boilerplate.
 
 base::WeakPtr<ContextualSearchContext> ContextualSearchContext::GetWeakPtr() {
diff --git a/chrome/browser/android/contextualsearch/contextual_search_context.h b/chrome/browser/android/contextualsearch/contextual_search_context.h
index 9b25497..798e50d1 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_context.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_context.h
@@ -53,8 +53,7 @@
       const base::android::JavaParamRef<jstring>& j_home_country,
       jboolean j_may_send_base_page_url,
       jlong j_previous_event_id,
-      jint j_previous_event_results,
-      jboolean j_do_related_searches);
+      jint j_previous_event_results);
 
   // Adjust the current selection offsets by the given signed amounts.
   void AdjustSelection(JNIEnv* env,
@@ -100,19 +99,27 @@
   int64_t GetPreviousEventId() const;
   int GetPreviousEventResults() const;
 
-  // Causes resolve requests to be for an exact match instead of an expandable
-  // term.
-  void SetExactResolve(JNIEnv* env,
-                       const base::android::JavaParamRef<jobject>& obj);
+  // Prepares the context to be used in a resolve request by supplying last
+  // minute parameters.
+  // |j_is_exact_resolve| indicates if the resolved term should be an exact
+  // match for the selection range instead of an expandable selection.
+  // |j_related_searches_stamp| is a value to stamp onto search URLs to
+  // identify related searches. If the string is empty then Related Searches
+  // are not being requested.
+  void PrepareToResolve(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean j_is_exact_resolve,
+      const base::android::JavaParamRef<jstring>& j_related_searches_stamp);
 
   // Returns whether the resolve request is for an exact match instead of an
   // expandable term.
-  bool GetExactResolve();
+  bool GetExactResolve() const;
 
   // Detects the language of the context using CLD from the translate utility.
   base::android::ScopedJavaLocalRef<jstring> DetectLanguage(
       JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj);
+      const base::android::JavaParamRef<jobject>& obj) const;
 
   // Sets the languages to remember for use in translation.
   // See |GetTranslationLanguages|.
@@ -125,11 +132,15 @@
 
   // Returns the languages to use for translation, as set by
   // |SetTranslationLanguages|.
-  const TranslationLanguages& GetTranslationLanguages();
+  const TranslationLanguages& GetTranslationLanguages() const;
 
   // Returns whether this request should include Related Searches in the
   // response.
-  bool GetRelatedSearches();
+  bool GetRelatedSearches() const;
+
+  // Get the logging information stamp for Related Searches requests or the
+  // empty string if the feature is not enabled.
+  const std::string GetRelatedSearchesStamp() const;
 
   // Gets a WeakPtr to this instance.
   base::WeakPtr<ContextualSearchContext> GetWeakPtr();
@@ -137,10 +148,10 @@
  private:
   // Gets the reliable language of the given |contents| using CLD, or an empty
   // string if none can reliably be determined.
-  std::string GetReliableLanguage(const base::string16& contents);
+  std::string GetReliableLanguage(const base::string16& contents) const;
 
   // Gets the selection, or an empty string if none.
-  base::string16 GetSelection();
+  base::string16 GetSelection() const;
 
   bool can_resolve_ = false;
   bool can_send_base_page_url_ = false;
@@ -155,6 +166,7 @@
   bool is_exact_resolve_ = false;
   TranslationLanguages translation_languages_;
   bool do_related_searches_ = false;
+  std::string related_searches_stamp_;
 
   // The linked Java object.
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index 2754381..a18cad2 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -63,6 +63,7 @@
 const char kContextualSearchCardTag[] = "card_tag";
 const char kContextualSearchSearchUrlFull[] = "search_url_full";
 const char kContextualSearchSearchUrlPreload[] = "search_url_preload";
+const char kRelatedSearchesQueryList[] = "searches";
 
 const char kActionCategoryAddress[] = "ADDRESS";
 const char kActionCategoryEmail[] = "EMAIL";
@@ -332,7 +333,8 @@
       context->GetExactResolve(),
       context->GetTranslationLanguages().detected_language,
       context->GetTranslationLanguages().target_language,
-      context->GetTranslationLanguages().fluent_languages, std::string());
+      context->GetTranslationLanguages().fluent_languages,
+      context->GetRelatedSearchesStamp());
 
   search_terms_args.contextual_search_params = params;
 
@@ -544,6 +546,23 @@
   if (!logged_event_id_string.empty()) {
     *logged_event_id = std::stoll(logged_event_id_string, nullptr);
   }
+
+  // Do minimal decoding of Related Searches.
+  // This should not be needed because the server shouldn't return any
+  // Related Searches to this client because it should know that it's
+  // too old to display them properly. As a fallback we just display
+  // the first one.
+  base::ListValue* search_query_list = nullptr;
+  dict->GetList(kRelatedSearchesQueryList, &search_query_list);
+  if (search_query_list && search_query_list->GetSize() >= 1) {
+    // For now, just use the first search from the list as the text to
+    // display and the query to search for.
+    // TODO(donnd): Decode the searches and associated metadata once the
+    // server sends all of that. Also use the non-deprecated ListValue
+    // accessors.
+    search_query_list->GetString(0, display_text);
+    search_query_list->GetString(0, search_term);
+  }
 }
 
 // Extract the Start/End of the mentions in the surrounding text
diff --git a/chrome/browser/android/customtabs/detached_resource_request.cc b/chrome/browser/android/customtabs/detached_resource_request.cc
index dd6aa4d..1131220c 100644
--- a/chrome/browser/android/customtabs/detached_resource_request.cc
+++ b/chrome/browser/android/customtabs/detached_resource_request.cc
@@ -175,13 +175,14 @@
                    network::SimpleURLLoader::RETRY_ON_NAME_NOT_RESOLVED;
   request->url_loader_->SetRetryOptions(1 /* max_retries */, retry_mode);
 
-  // |url_loader_| is owned by the request, and must be kept alive to not cancel
+  // |url_loader| is owned by the request, and must be kept alive to not cancel
   // the request. Pass the ownership of the request to the response callback,
   // ensuring that it stays alive, yet is freed upon completion or failure.
   //
   // This is also the reason for this function to be a static member function
   // instead of a regular function.
-  request->url_loader_->DownloadToString(
+  network::SimpleURLLoader* const url_loader = request->url_loader_.get();
+  url_loader->DownloadToString(
       storage_partition->GetURLLoaderFactoryForBrowserProcess().get(),
       base::BindOnce(&DetachedResourceRequest::OnResponseCallback,
                      std::move(request)),
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
index 76b8f77..6fa54ea5 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -188,7 +188,19 @@
   EXPECT_EQ(6, NumOuterFinishedCallbacks());
 }
 
-TEST_F(AppServiceProxyTest, ProxyAccessPerProfile) {
+class GuestAppServiceProxyTest : public AppServiceProxyTest,
+                                 public ::testing::WithParamInterface<bool> {
+ public:
+  GuestAppServiceProxyTest() {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_P(GuestAppServiceProxyTest, ProxyAccessPerProfile) {
   TestingProfile::Builder profile_builder;
 
   // We expect an App Service in a regular profile.
@@ -215,7 +227,7 @@
   EXPECT_NE(guest_proxy, proxy);
 }
 
-TEST_F(AppServiceProxyTest, RedirectInIncognitoProxyAccessPerProfile) {
+TEST_P(GuestAppServiceProxyTest, RedirectInIncognitoProxyAccessPerProfile) {
   TestingProfile::Builder profile_builder;
 
   // We expect an App Service in a regular profile.
@@ -248,3 +260,7 @@
   EXPECT_TRUE(guest_proxy);
   EXPECT_NE(guest_proxy, proxy);
 }
+
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         GuestAppServiceProxyTest,
+                         /*is_ephemeral=*/testing::Bool());
diff --git a/chrome/browser/apps/user_type_filter_unittest.cc b/chrome/browser/apps/user_type_filter_unittest.cc
index 5d1338a3..fc25f42 100644
--- a/chrome/browser/apps/user_type_filter_unittest.cc
+++ b/chrome/browser/apps/user_type_filter_unittest.cc
@@ -74,6 +74,18 @@
   content::BrowserTaskEnvironment task_environment_;
 };
 
+class GuestUserTypeFilterTest : public UserTypeFilterTest,
+                                public ::testing::WithParamInterface<bool> {
+ public:
+  GuestUserTypeFilterTest() {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
 TEST_F(UserTypeFilterTest, ChildUser) {
   const auto profile = CreateProfile();
@@ -85,7 +97,7 @@
 }
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
 
-TEST_F(UserTypeFilterTest, GuestUser) {
+TEST_P(GuestUserTypeFilterTest, GuestUser) {
   auto profile = CreateGuestProfile();
   EXPECT_FALSE(Match(profile, CreateJsonWithFilter({kUserTypeUnmanaged})));
   EXPECT_TRUE(Match(profile, CreateJsonWithFilter({kUserTypeGuest})));
@@ -120,7 +132,7 @@
   EXPECT_FALSE(Match(CreateProfile(), CreateJsonWithFilter({})));
 }
 
-TEST_F(UserTypeFilterTest, DefaultFilter) {
+TEST_P(GuestUserTypeFilterTest, DefaultFilter) {
   auto profile = CreateProfile();
   base::ListValue default_filter;
   default_filter.Append(base::Value(kUserTypeUnmanaged));
@@ -146,4 +158,8 @@
   EXPECT_FALSE(MatchDefault(profile, default_filter));
 }
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         GuestUserTypeFilterTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace apps
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index 5991e1e..a961344e 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -21,6 +21,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browsing_data/browsing_data_file_system_util.h"
 #include "chrome/browser/browsing_data/browsing_data_remover_browsertest_base.h"
@@ -97,13 +98,13 @@
 #include "chrome/browser/media/library_cdm_test_helper.h"
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/policy/system_proxy_manager.h"
 #include "chromeos/dbus/system_proxy/system_proxy_client.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 using content::BrowserThread;
 using content::BrowsingDataFilterBuilder;
@@ -1334,7 +1335,7 @@
 }
 
 // PRE_StorageRemovedFromDisk fails on Chrome OS. http://crbug.com/1035156.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_PRE_StorageRemovedFromDisk DISABLED_PRE_StorageRemovedFromDisk
 #define MAYBE_StorageRemovedFromDisk DISABLED_StorageRemovedFromDisk
 #else
@@ -1365,7 +1366,7 @@
   // but there are a few bugs that need to be fixed.
   // Any addition to this list must have an associated TODO().
   static const std::vector<std::string> ignore_file_patterns = {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // TODO(crbug.com/846297): Many leveldb files remain on ChromeOS. I couldn't
     // reproduce this in manual testing, so it might be a timing issue when
     // Chrome is closed after the second test?
@@ -1421,7 +1422,7 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Test that removing passwords, when System-proxy is enabled on Chrome OS,
 // sends a request to System-proxy to clear the cached user credentials.
 IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest,
@@ -1439,7 +1440,7 @@
                    ->GetTestInterface()
                    ->GetClearUserCredentialsCount());
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Some storage backend use a different code path for full deletions and
 // partial deletions, so we need to test both.
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 2e87543..2cf6e4a 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -22,6 +22,7 @@
 #include "base/task/thread_pool.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/android/feed/feed_host_service_factory.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/autofill/strike_database_factory.h"
@@ -157,7 +158,7 @@
 #include "extensions/common/constants.h"
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -169,7 +170,7 @@
 #include "chromeos/dbus/constants/attestation_constants.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/user_manager/user.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
 #include "device/fido/mac/credential_store.h"
@@ -829,7 +830,7 @@
             delete_end_.is_null() ? base::Time::Max() : delete_end_,
             CreateTaskCompletionClosureForMojo(
                 TracingDataType::kHttpAuthCache));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     policy::SystemProxyManager* system_proxy_manager =
         g_browser_process->platform_part()
             ->browser_policy_connector_chromeos()
@@ -844,7 +845,7 @@
       // them from the NetworkService when needed.
       system_proxy_manager->ClearUserCredentials();
     }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
     device::fido::mac::TouchIdCredentialStore(
@@ -1063,7 +1064,7 @@
     // Licenses.
     base::RecordAction(UserMetricsAction("ClearBrowsingData_ContentLicenses"));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // On Chrome OS, delete any content protection platform keys.
     // Platform keys do not support filtering by domain, so skip this if
     // clearing only a specified set of sites.
@@ -1096,7 +1097,7 @@
                          std::move(callback)));
       }
     }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_ANDROID)
     cdm::MediaDrmStorageImpl::ClearMatchingLicenses(
@@ -1332,7 +1333,7 @@
   return delete_begin_ == base::Time() && delete_end_ == base::Time::Max();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void ChromeBrowsingDataRemoverDelegate::OnClearPlatformKeys(
     base::OnceClosure done,
     bool result) {
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
index 2ce2018..314fb77 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
@@ -14,6 +14,7 @@
 #include "base/synchronization/waitable_event_watcher.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/buildflags.h"
 #include "components/browsing_data/core/browsing_data_utils.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -159,7 +160,7 @@
   // A helper method that checks if time period is for "all time".
   bool IsForAllTime() const;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnClearPlatformKeys(base::OnceClosure done, bool);
 #endif
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 2a9ad91f..4b3517d0 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -30,6 +30,7 @@
 #include "base/time/time.h"
 #include "base/util/values/values_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/autofill/strike_database_factory.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -142,12 +143,12 @@
 #include "content/public/browser/host_zoom_map.h"
 #endif  // !defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
 #include "chromeos/dbus/attestation/fake_attestation_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/scoped_user_manager.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
 #include "chrome/common/chrome_paths.h"
@@ -1703,7 +1704,7 @@
             GetOriginTypeMask());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(ChromeBrowsingDataRemoverDelegateTest,
        ContentProtectionPlatformKeysRemoval) {
   chromeos::MockUserManager* mock_user_manager =
@@ -2920,7 +2921,7 @@
 
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
 TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeCrashData) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // This test applies only when using a logfile of Crash uploads. Chrome Linux
   // will use Crashpad's database instead of the logfile. Chrome Chrome OS
   // continues to use the logfile even when Crashpad is enabled.
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index bd78ec4..7d786b2 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browsing_data/browsing_data_file_system_util.h"
 #include "chrome/browser/browsing_data/browsing_data_quota_helper.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -1933,7 +1934,7 @@
 // static
 browsing_data::CookieHelper::IsDeletionDisabledCallback
 CookiesTreeModel::GetCookieDeletionDisabledCallback(Profile* profile) {
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
   if (profile->IsChild()) {
     return base::BindRepeating(
         [](permissions::PermissionsClient* client,
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
index 83a1755e..7fa002d 100644
--- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h"
 #include "chrome/browser/browsing_data/mock_browsing_data_quota_helper.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -1903,7 +1904,7 @@
   EXPECT_FALSE(callback);
 }
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(CookiesTreeModelTest, CookieDeletionFilterChildUser) {
   profile_->SetSupervisedUserId(supervised_users::kChildAccountSUID);
   auto callback =
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
index bad18b69dd..3626615 100644
--- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h"
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
@@ -15,7 +16,7 @@
 #include "components/sync/test/fake_server/fake_server_network_resources.h"
 #include "content/public/test/browser_test.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #endif
@@ -59,7 +60,7 @@
   // Sign the profile in.
   EXPECT_TRUE(harness->SignInPrimaryAccount());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS sync in turned on by default.
   EXPECT_TRUE(ShouldShowCookieException(profile));
 #else
@@ -73,13 +74,13 @@
   // Now that we're syncing, we should offer to retain the cookie.
   EXPECT_TRUE(ShouldShowCookieException(profile));
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Pause sync.
   harness->SignOutPrimaryAccount();
 
   // There's no point in showing the cookie exception.
   EXPECT_FALSE(ShouldShowCookieException(profile));
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 }  // namespace browsing_data_counter_utils
diff --git a/chrome/browser/buildflags.gni b/chrome/browser/buildflags.gni
index 0be94bd90..1d464d6 100644
--- a/chrome/browser/buildflags.gni
+++ b/chrome/browser/buildflags.gni
@@ -16,6 +16,4 @@
   # integration with the open source, cross-platform Chromium updater.
   # TODO(crbug.com/1054060)
   enable_chromium_updater = false
-
-  tpm_fallback = false
 }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index d6ef2dc..bdcec705 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/python.gni")
 import("//build/config/ui.gni")
@@ -13,7 +14,7 @@
 import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 import("//third_party/protobuf/proto_library.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 assert(use_ozone)
 
 source_set("chromeos") {
@@ -3960,6 +3961,7 @@
     "//ash/public/cpp/external_arc",
     "//ash/public/cpp/external_arc:test_support",
     "//base",
+    "//build:chromeos_buildflags",
     "//chrome/app:command_ids",
     "//chrome/browser/resources/chromeos/zip_archiver:char_coding",
     "//chrome/browser/ui",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
index 30bfbc5..f99eecb 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/test/guest_session_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
@@ -585,7 +586,7 @@
   EXPECT_TRUE(IsSpokenFeedbackEnabled());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_Login DISABLED_Login
 #else
 #define MAYBE_Login Login
diff --git a/chrome/browser/chromeos/accessibility/magnification_controller_browsertest.cc b/chrome/browser/chromeos/accessibility/magnification_controller_browsertest.cc
index 3a19b027..bbc5030e 100644
--- a/chrome/browser/chromeos/accessibility/magnification_controller_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/magnification_controller_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/ui/browser.h"
@@ -160,7 +161,7 @@
 };
 
 // Test is flaky on ChromeOS: crbug.com/1150753
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_FollowFocusOnWebButtonContained \
   DISABLED_FollowFocusOnWebButtonContained
 #else
diff --git a/chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc b/chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc
index 7c906ca..5e31644 100644
--- a/chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -70,7 +71,7 @@
   DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
 };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // crbug.com/422943
 #define MAYBE_NoRewritingEventsWhenOff DISABLED_NoRewritingEventsWhenOff
 #else
diff --git a/chrome/browser/chromeos/crosapi/browser_util.cc b/chrome/browser/chromeos/crosapi/browser_util.cc
index 9acf05d..f89b81dc 100644
--- a/chrome/browser/chromeos/crosapi/browser_util.cc
+++ b/chrome/browser/chromeos/crosapi/browser_util.cc
@@ -84,6 +84,8 @@
   params->device_mode = environment_provider->GetDeviceMode();
   params->interface_versions = GetInterfaceVersions();
   params->default_paths = environment_provider->GetDefaultPaths();
+  params->device_account_gaia_id =
+      environment_provider->GetDeviceAccountGaiaId();
 
   return params;
 }
diff --git a/chrome/browser/chromeos/crosapi/environment_provider.cc b/chrome/browser/chromeos/crosapi/environment_provider.cc
index e0e1f27a..be0969ad 100644
--- a/chrome/browser/chromeos/crosapi/environment_provider.cc
+++ b/chrome/browser/chromeos/crosapi/environment_provider.cc
@@ -23,7 +23,7 @@
 
 mojom::SessionType EnvironmentProvider::GetSessionType() {
   const user_manager::User* const user =
-      user_manager::UserManager::Get()->GetActiveUser();
+      user_manager::UserManager::Get()->GetPrimaryUser();
   const Profile* const profile =
       chromeos::ProfileHelper::Get()->GetProfileByUser(user);
   if (profile->IsGuestSession()) {
@@ -84,4 +84,18 @@
   return default_paths;
 }
 
+std::string EnvironmentProvider::GetDeviceAccountGaiaId() {
+  const user_manager::User* const user =
+      user_manager::UserManager::Get()->GetPrimaryUser();
+  if (!user)
+    return std::string();
+
+  const AccountId& account_id = user->GetAccountId();
+  if (account_id.GetAccountType() != AccountType::GOOGLE)
+    return std::string();
+
+  DCHECK(!account_id.GetGaiaId().empty());
+  return account_id.GetGaiaId();
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/environment_provider.h b/chrome/browser/chromeos/crosapi/environment_provider.h
index d90609b..0417191 100644
--- a/chrome/browser/chromeos/crosapi/environment_provider.h
+++ b/chrome/browser/chromeos/crosapi/environment_provider.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_CROSAPI_ENVIRONMENT_PROVIDER_H_
 #define CHROME_BROWSER_CHROMEOS_CROSAPI_ENVIRONMENT_PROVIDER_H_
 
+#include <string>
+
 #include "chromeos/crosapi/mojom/crosapi.mojom.h"
 
 namespace crosapi {
@@ -25,6 +27,7 @@
   // These are provided by ash because they are part of the device account,
   // not the Lacros profile.
   virtual crosapi::mojom::DefaultPathsPtr GetDefaultPaths();
+  virtual std::string GetDeviceAccountGaiaId();
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc
index 06a79c2..6c110867 100644
--- a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc
+++ b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc
@@ -26,6 +26,8 @@
 
 namespace {
 
+constexpr char kFakeGaiaId[] = "fake-gaia-id";
+
 class FakeEnvironmentProvider : public EnvironmentProvider {
   crosapi::mojom::SessionType GetSessionType() override {
     return crosapi::mojom::SessionType::kRegularSession;
@@ -39,6 +41,7 @@
     base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &paths->downloads);
     return paths;
   }
+  std::string GetDeviceAccountGaiaId() override { return kFakeGaiaId; }
 };
 
 // TODO(crbug.com/1124494): Refactor the code to share with ARC.
diff --git a/chrome/browser/chromeos/crostini/crostini_terminal.cc b/chrome/browser/chromeos/crostini/crostini_terminal.cc
index 9ae0f3e..344623d 100644
--- a/chrome/browser/chromeos/crostini/crostini_terminal.cc
+++ b/chrome/browser/chromeos/crostini/crostini_terminal.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/crostini/crostini_terminal.h"
 
-#include "base/containers/flat_map.h"
+#include "base/containers/fixed_flat_map.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "base/strings/strcat.h"
@@ -114,89 +114,85 @@
 }
 
 void RecordTerminalSettingsChangesUMAs(Profile* profile) {
-  static const base::NoDestructor<base::flat_map<std::string, TerminalSetting>>
-      kSettingsMap({
-          {"alt-gr-mode", TerminalSetting::kAltGrMode},
-          {"alt-backspace-is-meta-backspace",
-           TerminalSetting::kAltBackspaceIsMetaBackspace},
-          {"alt-is-meta", TerminalSetting::kAltIsMeta},
-          {"alt-sends-what", TerminalSetting::kAltSendsWhat},
-          {"audible-bell-sound", TerminalSetting::kAudibleBellSound},
-          {"desktop-notification-bell",
-           TerminalSetting::kDesktopNotificationBell},
-          {"background-color", TerminalSetting::kBackgroundColor},
-          {"background-image", TerminalSetting::kBackgroundImage},
-          {"background-size", TerminalSetting::kBackgroundSize},
-          {"background-position", TerminalSetting::kBackgroundPosition},
-          {"backspace-sends-backspace",
-           TerminalSetting::kBackspaceSendsBackspace},
-          {"character-map-overrides", TerminalSetting::kCharacterMapOverrides},
-          {"close-on-exit", TerminalSetting::kCloseOnExit},
-          {"cursor-blink", TerminalSetting::kCursorBlink},
-          {"cursor-blink-cycle", TerminalSetting::kCursorBlinkCycle},
-          {"cursor-shape", TerminalSetting::kCursorShape},
-          {"cursor-color", TerminalSetting::kCursorColor},
-          {"color-palette-overrides", TerminalSetting::kColorPaletteOverrides},
-          {"copy-on-select", TerminalSetting::kCopyOnSelect},
-          {"use-default-window-copy", TerminalSetting::kUseDefaultWindowCopy},
-          {"clear-selection-after-copy",
-           TerminalSetting::kClearSelectionAfterCopy},
-          {"ctrl-plus-minus-zero-zoom",
-           TerminalSetting::kCtrlPlusMinusZeroZoom},
-          {"ctrl-c-copy", TerminalSetting::kCtrlCCopy},
-          {"ctrl-v-paste", TerminalSetting::kCtrlVPaste},
-          {"east-asian-ambiguous-as-two-column",
-           TerminalSetting::kEastAsianAmbiguousAsTwoColumn},
-          {"enable-8-bit-control", TerminalSetting::kEnable8BitControl},
-          {"enable-bold", TerminalSetting::kEnableBold},
-          {"enable-bold-as-bright", TerminalSetting::kEnableBoldAsBright},
-          {"enable-blink", TerminalSetting::kEnableBlink},
-          {"enable-clipboard-notice", TerminalSetting::kEnableClipboardNotice},
-          {"enable-clipboard-write", TerminalSetting::kEnableClipboardWrite},
-          {"enable-dec12", TerminalSetting::kEnableDec12},
-          {"enable-csi-j-3", TerminalSetting::kEnableCsiJ3},
-          {"environment", TerminalSetting::kEnvironment},
-          {"font-family", TerminalSetting::kFontFamily},
-          {"font-size", TerminalSetting::kFontSize},
-          {"font-smoothing", TerminalSetting::kFontSmoothing},
-          {"foreground-color", TerminalSetting::kForegroundColor},
-          {"enable-resize-status", TerminalSetting::kEnableResizeStatus},
-          {"hide-mouse-while-typing", TerminalSetting::kHideMouseWhileTyping},
-          {"home-keys-scroll", TerminalSetting::kHomeKeysScroll},
-          {"keybindings", TerminalSetting::kKeybindings},
-          {"media-keys-are-fkeys", TerminalSetting::kMediaKeysAreFkeys},
-          {"meta-sends-escape", TerminalSetting::kMetaSendsEscape},
-          {"mouse-right-click-paste", TerminalSetting::kMouseRightClickPaste},
-          {"mouse-paste-button", TerminalSetting::kMousePasteButton},
-          {"word-break-match-left", TerminalSetting::kWordBreakMatchLeft},
-          {"word-break-match-right", TerminalSetting::kWordBreakMatchRight},
-          {"word-break-match-middle", TerminalSetting::kWordBreakMatchMiddle},
-          {"page-keys-scroll", TerminalSetting::kPageKeysScroll},
-          {"pass-alt-number", TerminalSetting::kPassAltNumber},
-          {"pass-ctrl-number", TerminalSetting::kPassCtrlNumber},
-          {"pass-ctrl-n", TerminalSetting::kPassCtrlN},
-          {"pass-ctrl-t", TerminalSetting::kPassCtrlT},
-          {"pass-ctrl-tab", TerminalSetting::kPassCtrlTab},
-          {"pass-ctrl-w", TerminalSetting::kPassCtrlW},
-          {"pass-meta-number", TerminalSetting::kPassMetaNumber},
-          {"pass-meta-v", TerminalSetting::kPassMetaV},
-          {"paste-on-drop", TerminalSetting::kPasteOnDrop},
-          {"receive-encoding", TerminalSetting::kReceiveEncoding},
-          {"scroll-on-keystroke", TerminalSetting::kScrollOnKeystroke},
-          {"scroll-on-output", TerminalSetting::kScrollOnOutput},
-          {"scrollbar-visible", TerminalSetting::kScrollbarVisible},
-          {"scroll-wheel-may-send-arrow-keys",
-           TerminalSetting::kScrollWheelMaySendArrowKeys},
-          {"scroll-wheel-move-multiplier",
-           TerminalSetting::kScrollWheelMoveMultiplier},
-          {"terminal-encoding", TerminalSetting::kTerminalEncoding},
-          {"shift-insert-paste", TerminalSetting::kShiftInsertPaste},
-          {"user-css", TerminalSetting::kUserCss},
-          {"user-css-text", TerminalSetting::kUserCssText},
-          {"allow-images-inline", TerminalSetting::kAllowImagesInline},
-          {"theme", TerminalSetting::kTheme},
-          {"theme-variations", TerminalSetting::kThemeVariations},
-      });
+  static constexpr auto kSettingsMap = base::MakeFixedFlatMap<base::StringPiece,
+                                                              TerminalSetting>({
+      {"alt-gr-mode", TerminalSetting::kAltGrMode},
+      {"alt-backspace-is-meta-backspace",
+       TerminalSetting::kAltBackspaceIsMetaBackspace},
+      {"alt-is-meta", TerminalSetting::kAltIsMeta},
+      {"alt-sends-what", TerminalSetting::kAltSendsWhat},
+      {"audible-bell-sound", TerminalSetting::kAudibleBellSound},
+      {"desktop-notification-bell", TerminalSetting::kDesktopNotificationBell},
+      {"background-color", TerminalSetting::kBackgroundColor},
+      {"background-image", TerminalSetting::kBackgroundImage},
+      {"background-size", TerminalSetting::kBackgroundSize},
+      {"background-position", TerminalSetting::kBackgroundPosition},
+      {"backspace-sends-backspace", TerminalSetting::kBackspaceSendsBackspace},
+      {"character-map-overrides", TerminalSetting::kCharacterMapOverrides},
+      {"close-on-exit", TerminalSetting::kCloseOnExit},
+      {"cursor-blink", TerminalSetting::kCursorBlink},
+      {"cursor-blink-cycle", TerminalSetting::kCursorBlinkCycle},
+      {"cursor-shape", TerminalSetting::kCursorShape},
+      {"cursor-color", TerminalSetting::kCursorColor},
+      {"color-palette-overrides", TerminalSetting::kColorPaletteOverrides},
+      {"copy-on-select", TerminalSetting::kCopyOnSelect},
+      {"use-default-window-copy", TerminalSetting::kUseDefaultWindowCopy},
+      {"clear-selection-after-copy", TerminalSetting::kClearSelectionAfterCopy},
+      {"ctrl-plus-minus-zero-zoom", TerminalSetting::kCtrlPlusMinusZeroZoom},
+      {"ctrl-c-copy", TerminalSetting::kCtrlCCopy},
+      {"ctrl-v-paste", TerminalSetting::kCtrlVPaste},
+      {"east-asian-ambiguous-as-two-column",
+       TerminalSetting::kEastAsianAmbiguousAsTwoColumn},
+      {"enable-8-bit-control", TerminalSetting::kEnable8BitControl},
+      {"enable-bold", TerminalSetting::kEnableBold},
+      {"enable-bold-as-bright", TerminalSetting::kEnableBoldAsBright},
+      {"enable-blink", TerminalSetting::kEnableBlink},
+      {"enable-clipboard-notice", TerminalSetting::kEnableClipboardNotice},
+      {"enable-clipboard-write", TerminalSetting::kEnableClipboardWrite},
+      {"enable-dec12", TerminalSetting::kEnableDec12},
+      {"enable-csi-j-3", TerminalSetting::kEnableCsiJ3},
+      {"environment", TerminalSetting::kEnvironment},
+      {"font-family", TerminalSetting::kFontFamily},
+      {"font-size", TerminalSetting::kFontSize},
+      {"font-smoothing", TerminalSetting::kFontSmoothing},
+      {"foreground-color", TerminalSetting::kForegroundColor},
+      {"enable-resize-status", TerminalSetting::kEnableResizeStatus},
+      {"hide-mouse-while-typing", TerminalSetting::kHideMouseWhileTyping},
+      {"home-keys-scroll", TerminalSetting::kHomeKeysScroll},
+      {"keybindings", TerminalSetting::kKeybindings},
+      {"media-keys-are-fkeys", TerminalSetting::kMediaKeysAreFkeys},
+      {"meta-sends-escape", TerminalSetting::kMetaSendsEscape},
+      {"mouse-right-click-paste", TerminalSetting::kMouseRightClickPaste},
+      {"mouse-paste-button", TerminalSetting::kMousePasteButton},
+      {"word-break-match-left", TerminalSetting::kWordBreakMatchLeft},
+      {"word-break-match-right", TerminalSetting::kWordBreakMatchRight},
+      {"word-break-match-middle", TerminalSetting::kWordBreakMatchMiddle},
+      {"page-keys-scroll", TerminalSetting::kPageKeysScroll},
+      {"pass-alt-number", TerminalSetting::kPassAltNumber},
+      {"pass-ctrl-number", TerminalSetting::kPassCtrlNumber},
+      {"pass-ctrl-n", TerminalSetting::kPassCtrlN},
+      {"pass-ctrl-t", TerminalSetting::kPassCtrlT},
+      {"pass-ctrl-tab", TerminalSetting::kPassCtrlTab},
+      {"pass-ctrl-w", TerminalSetting::kPassCtrlW},
+      {"pass-meta-number", TerminalSetting::kPassMetaNumber},
+      {"pass-meta-v", TerminalSetting::kPassMetaV},
+      {"paste-on-drop", TerminalSetting::kPasteOnDrop},
+      {"receive-encoding", TerminalSetting::kReceiveEncoding},
+      {"scroll-on-keystroke", TerminalSetting::kScrollOnKeystroke},
+      {"scroll-on-output", TerminalSetting::kScrollOnOutput},
+      {"scrollbar-visible", TerminalSetting::kScrollbarVisible},
+      {"scroll-wheel-may-send-arrow-keys",
+       TerminalSetting::kScrollWheelMaySendArrowKeys},
+      {"scroll-wheel-move-multiplier",
+       TerminalSetting::kScrollWheelMoveMultiplier},
+      {"terminal-encoding", TerminalSetting::kTerminalEncoding},
+      {"shift-insert-paste", TerminalSetting::kShiftInsertPaste},
+      {"user-css", TerminalSetting::kUserCss},
+      {"user-css-text", TerminalSetting::kUserCssText},
+      {"allow-images-inline", TerminalSetting::kAllowImagesInline},
+      {"theme", TerminalSetting::kTheme},
+      {"theme-variations", TerminalSetting::kThemeVariations},
+  });
 
   const base::DictionaryValue* settings = profile->GetPrefs()->GetDictionary(
       crostini::prefs::kCrostiniTerminalSettings);
@@ -206,12 +202,11 @@
                           base::CompareCase::SENSITIVE)) {
       continue;
     }
-    TerminalSetting setting = TerminalSetting::kUnknown;
-    auto it = kSettingsMap->find(item.first.substr(kSettingPrefixSize));
-    if (it != kSettingsMap->end()) {
-      setting = it->second;
-    }
-    base::UmaHistogramEnumeration("Crostini.TerminalSettingsChanged", setting);
+    const auto* it = kSettingsMap.find(
+        base::StringPiece(item.first).substr(kSettingPrefixSize));
+    base::UmaHistogramEnumeration(
+        "Crostini.TerminalSettingsChanged",
+        it != kSettingsMap.end() ? it->second : TerminalSetting::kUnknown);
   }
 }
 
diff --git a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
index 7c14293..ca258cd4 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/values.h"
 #include "base/version.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/external_provider_impl.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -47,9 +48,9 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 using ::testing::Field;
 using ::testing::InvokeWithoutArgs;
@@ -183,9 +184,9 @@
 
   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
-#endif // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 DeviceLocalAccountExternalPolicyLoaderTest::
diff --git a/chrome/browser/chromeos/file_manager/file_manager_string_util.cc b/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
index 21cfd7e..1f37f159 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
@@ -925,6 +925,7 @@
   SET_STRING("MEDIA_TITLE_COLUMN_LABEL",
              IDS_FILE_BROWSER_MEDIA_TITLE_COLUMN_LABEL);
   SET_STRING("RECENT_ROOT_LABEL", IDS_FILE_BROWSER_RECENT_ROOT_LABEL);
+  SET_STRING("TRASH_ROOT_LABEL", IDS_FILE_BROWSER_TRASH_ROOT_LABEL);
   SET_STRING("SUGGEST_DIALOG_INSTALLATION_FAILED",
              IDS_FILE_BROWSER_SUGGEST_DIALOG_INSTALLATION_FAILED);
   SET_STRING("SUGGEST_DIALOG_LINK_TO_WEBSTORE",
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index acca0d5..dc9ff1f 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -1255,13 +1255,6 @@
   keyboard_.reset(keyboard);
 }
 
-void InputMethodManagerImpl::InitializeComponentExtensionForTesting(
-    std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
-  component_extension_ime_manager_->Initialize(std::move(delegate));
-  util_.ResetInputMethods(
-      component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
-}
-
 void InputMethodManagerImpl::Observe(
     int type,
     const content::NotificationSource& source,
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index 87255e73..69f2094 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -249,9 +249,6 @@
       CandidateWindowController* candidate_window_controller);
   // Sets |keyboard_|.
   void SetImeKeyboardForTesting(ImeKeyboard* keyboard);
-  // Initialize |component_extension_manager_|.
-  void InitializeComponentExtensionForTesting(
-      std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate);
 
   // content::NotificationObserver overrides:
   void Observe(int type,
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index 0b7a9f0..cc51d21d 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.h"
 #include "chrome/browser/chromeos/input_method/mock_candidate_window_controller.h"
 #include "chrome/browser/chromeos/input_method/mock_input_method_engine.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -139,9 +138,15 @@
   void SetUp() override {
     ui::InitializeInputMethodForTesting();
 
+    InitImeList();
+
+    auto mock_delegate =
+        std::make_unique<MockComponentExtensionIMEManagerDelegate>();
+    mock_delegate->set_ime_list(ime_list_);
+
     manager_ = std::make_unique<InputMethodManagerImpl>(
-        std::make_unique<FakeInputMethodDelegate>(),
-        std::make_unique<ComponentExtensionIMEManagerDelegateImpl>(), false);
+        std::make_unique<FakeInputMethodDelegate>(), std::move(mock_delegate),
+        false);
     manager_->GetInputMethodUtil()->UpdateHardwareLayoutCache();
     candidate_window_controller_ = new MockCandidateWindowController;
     manager_->SetCandidateWindowControllerForTesting(
@@ -154,32 +159,12 @@
 
     menu_manager_ = ui::ime::InputMethodMenuManager::GetInstance();
 
-    InitImeList();
-
     BrowserWithTestWindowTest::SetUp();
 
     // Needs ash::Shell keyboard to be created first.
     chrome_keyboard_controller_client_test_helper_ =
         ChromeKeyboardControllerClientTestHelper::InitializeForAsh();
 
-    InitComponentExtension();
-  }
-
-  void TearDown() override {
-    // Needs to destroyed before ash::Shell keyboard.
-    chrome_keyboard_controller_client_test_helper_.reset();
-
-    BrowserWithTestWindowTest::TearDown();
-    ui::ShutdownInputMethodForTesting();
-
-    candidate_window_controller_ = nullptr;
-    keyboard_ = nullptr;
-    manager_.reset();
-  }
-
- private:
-  // Helper function to initialize component extension stuff for testing.
-  void InitComponentExtension() {
     // CreateNewState(nullptr) returns state with non-empty
     // current_input_method. So SetState() triggers ChangeInputMethod().
     InputMethodDescriptors descriptors;
@@ -192,17 +177,18 @@
     state->AddInputMethodExtension(extension_ime_util::kT13nExtensionId,
                                    descriptors, mock_engine_handler_.get());
     manager_->SetState(state);
+  }
 
-    MockComponentExtensionIMEManagerDelegate* mock_delegate =
-        new MockComponentExtensionIMEManagerDelegate();
-    mock_delegate->set_ime_list(ime_list_);
-    std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate(
-        mock_delegate);
+  void TearDown() override {
+    // Needs to destroyed before ash::Shell keyboard.
+    chrome_keyboard_controller_client_test_helper_.reset();
 
-    // Note, for production, these SetEngineHandler are called when
-    // IMEEngineHandlerInterface is initialized via
-    // InitializeComponentextension.
-    manager_->InitializeComponentExtensionForTesting(std::move(delegate));
+    BrowserWithTestWindowTest::TearDown();
+    ui::ShutdownInputMethodForTesting();
+
+    candidate_window_controller_ = nullptr;
+    keyboard_ = nullptr;
+    manager_.reset();
   }
 
   void InitImeList() {
diff --git a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc
index 0282848a..b682cc5 100644
--- a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc
+++ b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc
@@ -16,6 +16,7 @@
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/platform_keys/key_permissions/extension_key_permissions_service.h"
 #include "chrome/browser/chromeos/platform_keys/key_permissions/extension_key_permissions_service_factory.h"
 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_service.h"
@@ -40,7 +41,7 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Verify the allowlisted kKeyPermissionsInLoginScreen feature behaviors.
 bool IsExtensionAllowlisted(const extensions::Extension* extension) {
@@ -56,7 +57,7 @@
   return key_permissions_in_login_screen->IsAvailableToExtension(extension)
       .is_available();
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
 
diff --git a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
index c4ee2291..aacdf45 100644
--- a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
+++ b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/task/current_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
@@ -83,7 +84,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -317,7 +318,7 @@
       const MultiProfilePolicyProviderHelper& other) = delete;
 
   void SetUpCommandLine(base::CommandLine* command_line) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     command_line->AppendSwitch(
         chromeos::switches::kIgnoreUserProfileMappingForTests);
 #endif
diff --git a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
index 5ee662c..d8180bd43 100644
--- a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -161,7 +162,7 @@
 
   chrome::ShowHelp(browser(), chrome::HELP_SOURCE_KEYBOARD);
 
-#if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   EXPECT_NO_FATAL_FAILURE(WaitForAppToOpen(GURL("chrome://help-app/")));
 #else
   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
@@ -185,7 +186,7 @@
 
   chrome::LaunchReleaseNotes(profile(),
                              apps::mojom::LaunchSource::kFromOtherApp);
-#if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   // If no navigation happens, then this test will time out due to the wait.
   navigation_observer.Wait();
 
@@ -211,7 +212,7 @@
   base::UserActionTester user_action_tester;
   chrome::LaunchReleaseNotes(profile(),
                              apps::mojom::LaunchSource::kFromOtherApp);
-#if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   EXPECT_EQ(1,
             user_action_tester.GetActionCount("ReleaseNotes.ShowReleaseNotes"));
 #else
@@ -249,7 +250,7 @@
       1, user_action_tester.GetActionCount("ReleaseNotes.NotificationShown"));
   EXPECT_EQ(1, user_action_tester.GetActionCount(
                    "ReleaseNotes.LaunchedNotification"));
-#if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   EXPECT_NO_FATAL_FAILURE(WaitForAppToOpen(GURL("chrome://help-app/updates")));
   EXPECT_EQ(1,
             user_action_tester.GetActionCount("ReleaseNotes.ShowReleaseNotes"));
@@ -419,7 +420,7 @@
       browser(), ui::VKEY_OEM_2, /*control=*/true,
       /*shift=*/false, /*alt=*/false, /*command=*/false));
 
-#if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   // Default browser tab and Help app are open.
   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   EXPECT_EQ("chrome://help-app/", GetActiveWebContents()->GetVisibleURL());
diff --git a/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc
index d9e190a..4f9c7f8 100644
--- a/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/strings/string_util.h"
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_test_util.h"
 #include "chrome/browser/chromeos/file_manager/web_file_tasks.h"
@@ -215,7 +216,7 @@
 // Test that the MediaApp can load RAW files passed on launch params.
 // Disabled on ChromeOS because it fails randomly on linux-chromeos-chrome.
 // See: https://crbug.com/1152318
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_HandleRawFiles DISABLED_HandleRawFiles
 #else
 #define MAYBE_HandleRawFiles HandleRawFiles
diff --git a/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_client.cc b/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
index 6e726518..24a1f55 100644
--- a/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
+++ b/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_client.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/memory/weak_ptr.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h"
 #include "chrome/common/chrome_features.h"
 #include "dbus/bus.h"
@@ -90,7 +91,7 @@
 // static
 void WilcoDtcSupportdClient::Initialize(dbus::Bus* bus) {
   DCHECK(bus);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(::features::kWilcoDtc)) {
     (new WilcoDtcSupportdClientImpl())->Init(bus);
   }
diff --git a/chrome/browser/device_identity/device_oauth2_token_service.cc b/chrome/browser/device_identity/device_oauth2_token_service.cc
index 4842b1a..cb3b6993 100644
--- a/chrome/browser/device_identity/device_oauth2_token_service.cc
+++ b/chrome/browser/device_identity/device_oauth2_token_service.cc
@@ -14,6 +14,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/device_identity/device_oauth2_token_store.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_service.h"
@@ -127,7 +128,7 @@
   return token_manager_.get();
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void DeviceOAuth2TokenService::SetServiceAccountEmail(
     const std::string& account_email) {
   store_->SetAccountEmail(account_email);
diff --git a/chrome/browser/device_identity/device_oauth2_token_service.h b/chrome/browser/device_identity/device_oauth2_token_service.h
index c4101d3..8dc16bf 100644
--- a/chrome/browser/device_identity/device_oauth2_token_service.h
+++ b/chrome/browser/device_identity/device_oauth2_token_service.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/device_identity/device_oauth2_token_store.h"
 #include "google_apis/gaia/core_account_id.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
@@ -74,7 +75,7 @@
 
   OAuth2AccessTokenManager* GetAccessTokenManager();
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Used on non-ChromeOS platforms to set the email associated with the
   // current service account. On ChromeOS, this function isn't used because
   // the service account identity comes from CrosSettings.
diff --git a/chrome/browser/device_identity/device_oauth2_token_service_factory.cc b/chrome/browser/device_identity/device_oauth2_token_service_factory.cc
index eae8a7d6..513ef3a 100644
--- a/chrome/browser/device_identity/device_oauth2_token_service_factory.cc
+++ b/chrome/browser/device_identity/device_oauth2_token_service_factory.cc
@@ -8,11 +8,12 @@
 
 #include "build/build_config.h"
 #include "chrome/browser/chromeos/settings/token_encryptor.h"
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos.h"
 #else
 #include "chrome/browser/device_identity/device_oauth2_token_store_desktop.h"
 #endif
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "components/policy/core/common/features.h"
@@ -25,10 +26,11 @@
 
 std::unique_ptr<DeviceOAuth2TokenStore> CreatePlatformTokenStore(
     PrefService* local_state) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return std::make_unique<chromeos::DeviceOAuth2TokenStoreChromeOS>(
       local_state);
-#elif defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX)
+#elif defined(OS_WIN) || defined(OS_MAC) || \
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   DCHECK(
       base::FeatureList::IsEnabled(policy::features::kCBCMPolicyInvalidations));
   return std::make_unique<DeviceOAuth2TokenStoreDesktop>(local_state);
diff --git a/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc b/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc
index 90860b2..08cad24 100644
--- a/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc
+++ b/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -53,7 +54,7 @@
     TriggerTrustedAccountIdCallback(true);
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void SetAccountEmail(const std::string& account_email) override {
     account_id_ = CoreAccountId::FromEmail(account_email);
   }
diff --git a/chrome/browser/device_identity/device_oauth2_token_store.h b/chrome/browser/device_identity/device_oauth2_token_store.h
index 44bde45..59614187 100644
--- a/chrome/browser/device_identity/device_oauth2_token_store.h
+++ b/chrome/browser/device_identity/device_oauth2_token_store.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "build/chromeos_buildflags.h"
 #include "google_apis/gaia/core_account_id.h"
 
 // An interface to be implemented per-platform that represents an
@@ -73,7 +74,7 @@
   // Invokes |callback| when the operation completes.
   virtual void PrepareTrustedAccountId(TrustedAccountIdCallback callback) = 0;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Requests that this store persist the current service account's associated
   // email.
   // On ChromeOS, the account email comes from CrosSettings so this should never
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn
index cf8e2db..21dc465 100644
--- a/chrome/browser/devtools/BUILD.gn
+++ b/chrome/browser/devtools/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//extensions/buildflags/buildflags.gni")
 
 if (!is_android) {
@@ -32,7 +33,7 @@
     "protocol/target.h",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     _protocol_generated += [
       "protocol/window_manager.cc",
       "protocol/window_manager.h",
@@ -53,7 +54,7 @@
     outputs = [ output_file ]
 
     args = [ rebase_path(_blink_protocol_path, root_build_dir) ]
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       inputs += [ "cros_protocol.pdl" ]
       args += [ rebase_path("cros_protocol.pdl", root_build_dir) ]
     }
@@ -220,7 +221,7 @@
       "protocol/target_handler.cc",
       "protocol/target_handler.h",
     ]
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       sources += [
         "protocol/window_manager_handler.cc",
         "protocol/window_manager_handler.h",
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index 2355ca7..bbf9a08 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -11,6 +11,7 @@
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/chrome_devtools_session.h"
 #include "chrome/browser/devtools/device/android_device_manager.h"
 #include "chrome/browser/devtools/device/tcp_device_provider.h"
@@ -43,7 +44,7 @@
 #include "extensions/common/manifest.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/command_line.h"
 #include "chromeos/constants/chromeos_switches.h"
 #endif
@@ -181,7 +182,7 @@
 bool ChromeDevToolsManagerDelegate::AllowInspection(
     Profile* profile,
     const extensions::Extension* extension) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(chromeos::switches::kForceDevToolsAvailable))
     return true;
@@ -191,7 +192,7 @@
   Availability availability =
       policy::DeveloperToolsPolicyHandler::GetDevToolsAvailability(
           profile->GetPrefs());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Do not create DevTools if it's disabled for primary profile.
   Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
   if (primary_profile &&
diff --git a/chrome/browser/devtools/chrome_devtools_session.cc b/chrome/browser/devtools/chrome_devtools_session.cc
index 018463f..ebbf5ec 100644
--- a/chrome/browser/devtools/chrome_devtools_session.cc
+++ b/chrome/browser/devtools/chrome_devtools_session.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include "base/strings/string_number_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/protocol/browser_handler.h"
 #include "chrome/browser/devtools/protocol/cast_handler.h"
 #include "chrome/browser/devtools/protocol/page_handler.h"
@@ -17,7 +18,7 @@
 #include "content/public/browser/devtools_manager_delegate.h"
 #include "third_party/inspector_protocol/crdtp/dispatch.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/devtools/protocol/window_manager_handler.h"
 #endif
 
@@ -41,7 +42,7 @@
     browser_handler_ =
         std::make_unique<BrowserHandler>(&dispatcher_, agent_host->GetId());
   }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   window_manager_handler_ =
       std::make_unique<WindowManagerHandler>(&dispatcher_);
 #endif
diff --git a/chrome/browser/devtools/chrome_devtools_session.h b/chrome/browser/devtools/chrome_devtools_session.h
index 1e67e00..1678e52 100644
--- a/chrome/browser/devtools/chrome_devtools_session.h
+++ b/chrome/browser/devtools/chrome_devtools_session.h
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/protocol/forward.h"
 #include "chrome/browser/devtools/protocol/protocol.h"
 #include "content/public/browser/devtools_manager_delegate.h"
@@ -58,7 +59,7 @@
   std::unique_ptr<PageHandler> page_handler_;
   std::unique_ptr<SecurityHandler> security_handler_;
   std::unique_ptr<TargetHandler> target_handler_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<WindowManagerHandler> window_manager_handler_;
 #endif
   content::DevToolsAgentHostClientChannel* client_channel_;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 210a9c2..f2f8381 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -28,6 +28,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/devtools/device/tcp_device_provider.h"
@@ -113,7 +114,7 @@
 #include "ui/gl/gl_switches.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -1582,7 +1583,8 @@
 
 // Tests that pressing 'Pause' will pause script execution if the script
 // is already running.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+    defined(ARCH_CPU_ARM_FAMILY)
 // Timing out on linux ARM bot: https://crbug/238453
 #define MAYBE_TestPauseWhenScriptIsRunning DISABLED_TestPauseWhenScriptIsRunning
 #else
@@ -2017,7 +2019,7 @@
 };
 
 // Fails on CrOS. crbug.com/431399
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_RemoteDebugger DISABLED_RemoteDebugger
 #else
 // TODO(crbug.com/997911): Flaky on all platforms.
@@ -2119,7 +2121,7 @@
     // literal here so it's possible to verify that the switch does not apply on
     // non-ChromeOS platforms.
     const std::string kForceDevToolsAvailableBase = "force-devtools-available";
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     ASSERT_EQ(kForceDevToolsAvailableBase,
               chromeos::switches::kForceDevToolsAvailable);
 #endif
@@ -2139,7 +2141,7 @@
 
   DevToolsWindow::OpenDevToolsWindow(web_contents);
   auto agent_host = content::DevToolsAgentHost::GetOrCreateFor(web_contents);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
 #else
   ASSERT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index d02bbd89..ca4ac34 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -620,7 +620,7 @@
   switch (status) {
     case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
 #endif
     case base::TERMINATION_STATUS_PROCESS_CRASHED:
diff --git a/chrome/browser/diagnostics/diagnostics_controller.cc b/chrome/browser/diagnostics/diagnostics_controller.cc
index d25885d..9f7b1cc 100644
--- a/chrome/browser/diagnostics/diagnostics_controller.cc
+++ b/chrome/browser/diagnostics/diagnostics_controller.cc
@@ -11,12 +11,13 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/diagnostics/diagnostics_model.h"
 #include "chrome/browser/diagnostics/diagnostics_test.h"
 #include "chrome/browser/diagnostics/diagnostics_writer.h"
 #include "chrome/common/chrome_switches.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -41,7 +42,7 @@
 void DiagnosticsController::ClearResults() { model_.reset(); }
 
 void DiagnosticsController::RecordRegularStartup() {
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
   // Count the number of normal starts, so we can compare that with the number
   // of recovery runs to get a percentage.
   UMA_HISTOGRAM_ENUMERATION(
@@ -74,7 +75,7 @@
                                        DiagnosticsWriter* writer) {
 // Separate out recoveries that we execute automatically as a result of a
 // crash from user-run recoveries.
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
   if (command_line.HasSwitch(chromeos::switches::kLoginUser)) {
     UMA_HISTOGRAM_ENUMERATION("Diagnostics.RecoveryRun",
                               diagnostics::RECOVERY_CRASH_RUN,
diff --git a/chrome/browser/diagnostics/diagnostics_controller_unittest.cc b/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
index 5e4d77c1..eddc1dc 100644
--- a/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
+++ b/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/diagnostics/diagnostics_model.h"
 #include "chrome/browser/diagnostics/diagnostics_writer.h"
 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
@@ -20,9 +21,9 @@
 #include "chrome/common/chrome_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_constants.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace diagnostics {
 
@@ -43,7 +44,7 @@
     base::CopyDirectory(test_data, temp_dir_.GetPath(), true);
     profile_dir_ = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("user"));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // Redirect the home dir to the profile directory. We have to do this
     // because NSS uses the HOME directory to find where to store it's database,
     // so that's where the diagnostics and recovery code looks for it.
@@ -62,7 +63,7 @@
 
   void TearDown() override {
     DiagnosticsController::GetInstance()->ClearResults();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     base::PathService::Override(base::DIR_HOME, old_home_dir_);
     old_home_dir_.clear();
 #endif
@@ -81,7 +82,7 @@
   std::unique_ptr<DiagnosticsWriter> writer_;
   base::FilePath profile_dir_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   base::FilePath old_home_dir_;
 #endif
 
@@ -117,7 +118,7 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(DiagnosticsControllerTest, RecoverFromNssCertDbFailure) {
   base::FilePath db_path = profile_dir_.Append(chromeos::kNssCertDbPath);
   EXPECT_TRUE(base::PathExists(db_path));
diff --git a/chrome/browser/diagnostics/diagnostics_model.cc b/chrome/browser/diagnostics/diagnostics_model.cc
index 0383f7e5..7bd0102 100644
--- a/chrome/browser/diagnostics/diagnostics_model.cc
+++ b/chrome/browser/diagnostics/diagnostics_model.cc
@@ -14,6 +14,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/diagnostics/diagnostics_test.h"
 #include "chrome/browser/diagnostics/recon_diagnostics.h"
 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
@@ -29,7 +30,7 @@
 #elif defined(OS_MAC)
 const int DiagnosticsModel::kDiagnosticsTestCount = 14;
 #elif defined(OS_POSIX)
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const int DiagnosticsModel::kDiagnosticsTestCount = 18;
 #else
 const int DiagnosticsModel::kDiagnosticsTestCount = 16;
@@ -66,7 +67,7 @@
         continue_running = RunTest(tests_[i].get(), observer, i);
         ++tests_run_;
       } else {
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
         RecordUMATestResult(static_cast<DiagnosticsTestId>(tests_[i]->GetId()),
                             RESULT_SKIPPED);
 #else
@@ -89,7 +90,7 @@
       if (continue_running) {
         continue_running = RunRecovery(tests_[i].get(), observer, i);
       } else {
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
         RecordUMARecoveryResult(
             static_cast<DiagnosticsTestId>(tests_[i]->GetId()), RESULT_SKIPPED);
 #else
@@ -216,7 +217,7 @@
     tests_.push_back(MakeSqliteHistoryDbTest());
     tests_.push_back(MakeSqliteTopSitesDbTest());
     tests_.push_back(MakeSqliteWebDatabaseTrackerDbTest());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     tests_.push_back(MakeSqliteNssCertDbTest());
     tests_.push_back(MakeSqliteNssKeyDbTest());
 #endif
diff --git a/chrome/browser/diagnostics/diagnostics_test.cc b/chrome/browser/diagnostics/diagnostics_test.cc
index 73cf0606..d919de6ff 100644
--- a/chrome/browser/diagnostics/diagnostics_test.cc
+++ b/chrome/browser/diagnostics/diagnostics_test.cc
@@ -8,6 +8,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 
@@ -36,7 +37,7 @@
   bool keep_going = RecoveryImpl(observer);
   result_ = keep_going ? DiagnosticsModel::RECOVERY_OK
                        : DiagnosticsModel::RECOVERY_FAIL_STOP;
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
   if (result_ == DiagnosticsModel::RECOVERY_OK) {
     RecordUMARecoveryResult(static_cast<DiagnosticsTestId>(GetId()),
                             RESULT_SUCCESS);
@@ -57,7 +58,7 @@
   outcome_code_ = outcome_code;
   additional_info_ = additional_info;
   result_ = result;
-#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // Only collecting UMA stats on ChromeOS
   DiagnosticsTestId id = static_cast<DiagnosticsTestId>(GetId());
   if (result_ == DiagnosticsModel::TEST_OK) {
     // Record individual test success.
diff --git a/chrome/browser/diagnostics/sqlite_diagnostics.cc b/chrome/browser/diagnostics/sqlite_diagnostics.cc
index 6e6b8951..8c3d45c 100644
--- a/chrome/browser/diagnostics/sqlite_diagnostics.cc
+++ b/chrome/browser/diagnostics/sqlite_diagnostics.cc
@@ -20,6 +20,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/history/core/browser/history_constants.h"
@@ -30,9 +31,9 @@
 #include "storage/browser/database/database_tracker.h"
 #include "third_party/sqlite/sqlite3.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_constants.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace diagnostics {
 
@@ -229,7 +230,7 @@
       base::FilePath(history::kHistoryFilename));
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<DiagnosticsTest> MakeSqliteNssCertDbTest() {
   base::FilePath home_dir;
   base::PathService::Get(base::DIR_HOME, &home_dir);
@@ -247,7 +248,7 @@
       DIAGNOSTICS_SQLITE_INTEGRITY_NSS_KEY_TEST,
       home_dir.Append(chromeos::kNssKeyDbPath));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::unique_ptr<DiagnosticsTest> MakeSqliteFaviconsDbTest() {
   return std::make_unique<SqliteIntegrityTest>(
diff --git a/chrome/browser/diagnostics/sqlite_diagnostics.h b/chrome/browser/diagnostics/sqlite_diagnostics.h
index 07af7ec..2c3d253 100644
--- a/chrome/browser/diagnostics/sqlite_diagnostics.h
+++ b/chrome/browser/diagnostics/sqlite_diagnostics.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/diagnostics/diagnostics_test.h"
 
 namespace diagnostics {
@@ -29,10 +30,10 @@
 std::unique_ptr<DiagnosticsTest> MakeSqliteHistoryDbTest();
 std::unique_ptr<DiagnosticsTest> MakeSqliteTopSitesDbTest();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<DiagnosticsTest> MakeSqliteNssCertDbTest();
 std::unique_ptr<DiagnosticsTest> MakeSqliteNssKeyDbTest();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::unique_ptr<DiagnosticsTest> MakeSqliteWebDatabaseTrackerDbTest();
 std::unique_ptr<DiagnosticsTest> MakeSqliteWebDataDbTest();
diff --git a/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc b/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc
index 90703dad..c02d7df3 100644
--- a/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc
+++ b/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/enterprise/browser_management/browser_management_status_provider.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
@@ -22,7 +23,7 @@
     default;
 
 bool BrowserCloudManagementStatusProvider::IsManaged() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return policy::BrowserDMTokenStorage::Get()->RetrieveDMToken().is_valid();
 #elif !defined(OS_ANDROID)
   // A machine level user cloud policy manager is only created if the browser is
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
index ab7a839..d6f92a0 100644
--- a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
+++ b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
@@ -11,6 +11,7 @@
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -22,9 +23,9 @@
 #include "components/version_info/version_info.h"
 #include "ppapi/buildflags/buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "content/public/browser/plugin_service.h"
@@ -51,7 +52,7 @@
 
 void BrowserReportGeneratorDesktop::GenerateBuildStateInfo(
     em::BrowserReport* report) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   const auto* const build_state = g_browser_process->GetBuildState();
   if (build_state->update_type() != BuildState::UpdateType::kNone) {
     const auto& installed_version = build_state->installed_version();
@@ -78,13 +79,13 @@
   for (const auto* entry : g_browser_process->profile_manager()
                                ->GetProfileAttributesStorage()
                                .GetAllProfilesAttributes()) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // Skip sign-in and lock screen app profile on Chrome OS.
     if (!chromeos::ProfileHelper::IsRegularProfilePath(
             entry->GetPath().BaseName())) {
       continue;
     }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     base::FilePath profile_path = entry->GetPath();
     if (is_extension_request_report &&
@@ -107,7 +108,7 @@
 void BrowserReportGeneratorDesktop::GeneratePluginsIfNeeded(
     ReportCallback callback,
     std::unique_ptr<em::BrowserReport> report) {
-#if defined(OS_CHROMEOS) || !BUILDFLAG(ENABLE_PLUGINS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || !BUILDFLAG(ENABLE_PLUGINS)
   std::move(callback).Run(std::move(report));
 #else
   content::PluginService::GetInstance()->GetPlugins(base::BindOnce(
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
index 037522b8..4d966b9a 100644
--- a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/bind.h"
 #include "base/time/time.h"
 #include "base/version.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler_test.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
@@ -27,9 +28,9 @@
 #include "device_management_backend.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/common/chrome_constants.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace em = enterprise_management;
 
@@ -76,10 +77,10 @@
     profile_manager_.CreateGuestProfile();
     profile_manager_.CreateSystemProfile();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     profile_manager_.CreateTestingProfile(chrome::kInitialProfile);
     profile_manager_.CreateTestingProfile(chrome::kLockScreenAppProfile);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   void InitializePlugin() {
@@ -112,7 +113,7 @@
             [&run_loop](std::unique_ptr<em::BrowserReport> report) {
               EXPECT_TRUE(report.get());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
               EXPECT_FALSE(report->has_browser_version());
               EXPECT_FALSE(report->has_channel());
               EXPECT_FALSE(report->has_installed_browser_version());
@@ -138,7 +139,7 @@
               EXPECT_EQ(kProfileName, profile.name());
               EXPECT_FALSE(profile.is_detail_available());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
               EXPECT_EQ(0, report->plugins_size());
 #else
               EXPECT_LE(1, report->plugins_size());
@@ -202,7 +203,7 @@
   GenerateAndVerify();
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(BrowserReportGeneratorTest, GenerateBasicReportWithUpdate) {
   InitializeUpdate();
   InitializeProfile();
diff --git a/chrome/browser/enterprise/reporting/policy_info_unittest.cc b/chrome/browser/enterprise/reporting/policy_info_unittest.cc
index f7600e51..ab2a63e 100644
--- a/chrome/browser/enterprise/reporting/policy_info_unittest.cc
+++ b/chrome/browser/enterprise/reporting/policy_info_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/chrome_policy_conversions_client.h"
 #include "chrome/common/chrome_constants.h"
@@ -173,11 +174,11 @@
 
 TEST_F(PolicyInfoTest, MachineLevelUserCloudPolicyFetchTimestamp) {
   em::ChromeUserProfileInfo profile_info;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   AppendMachineLevelUserCloudPolicyFetchTimestamp(
       &profile_info, g_browser_process->browser_policy_connector()
                          ->machine_level_user_cloud_policy_manager());
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(0, profile_info.policy_fetched_timestamps_size());
 }
 
diff --git a/chrome/browser/enterprise/reporting/prefs.cc b/chrome/browser/enterprise/reporting/prefs.cc
index 141d49cb..b08cbbb 100644
--- a/chrome/browser/enterprise/reporting/prefs.cc
+++ b/chrome/browser/enterprise/reporting/prefs.cc
@@ -6,6 +6,7 @@
 
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/pref_names.h"
 #include "components/enterprise/browser/reporting/common_pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -21,7 +22,7 @@
   // the migration.
   registry->RegisterBooleanPref(kCloudReportingEnabled, false);
   registry->RegisterTimePref(kLastUploadTimestamp, base::Time());
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterStringPref(kLastUploadVersion, std::string());
 #endif
 }
diff --git a/chrome/browser/enterprise/reporting/profile_report_generator_desktop.cc b/chrome/browser/enterprise/reporting/profile_report_generator_desktop.cc
index 05e27cb..ded5e65 100644
--- a/chrome/browser/enterprise/reporting/profile_report_generator_desktop.cc
+++ b/chrome/browser/enterprise/reporting/profile_report_generator_desktop.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/util/values/values_util.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/extension_info.h"
 #include "chrome/browser/extensions/extension_management.h"
@@ -125,12 +126,12 @@
 
 policy::MachineLevelUserCloudPolicyManager*
 ProfileReportGeneratorDesktop::GetCloudPolicyManager() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return nullptr;
 #else
   return g_browser_process->browser_policy_connector()
       ->machine_level_user_cloud_policy_manager();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
index 107fea1..52d6f2e 100644
--- a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/util/values/values_util.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
@@ -285,7 +286,7 @@
   // users info are included on CrOS only.
   EXPECT_TRUE(report);
   EXPECT_EQ(profile()->GetPath().AsUTF8Unsafe(), report->id());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(profile()->GetProfileUserName(), report->name());
   EXPECT_TRUE(report->has_chrome_signed_in_user());
 #else
diff --git a/chrome/browser/enterprise/reporting/report_generator_desktop.cc b/chrome/browser/enterprise/reporting/report_generator_desktop.cc
index 45f28f556..f964ca8 100644
--- a/chrome/browser/enterprise/reporting/report_generator_desktop.cc
+++ b/chrome/browser/enterprise/reporting/report_generator_desktop.cc
@@ -6,7 +6,9 @@
 
 #include <utility>
 
-#if defined(OS_CHROMEOS)
+#include "build/chromeos_buildflags.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/browser_process.h"
@@ -16,7 +18,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace em = enterprise_management;
 
@@ -26,7 +28,7 @@
 // delegates, then move this method's implementation to ReportGeneratorChromeOS.
 void ReportGeneratorDesktop::SetAndroidAppInfos(
     ReportGenerator::ReportRequest* basic_request) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   DCHECK(basic_request);
   basic_request->clear_android_app_infos();
 
@@ -52,7 +54,7 @@
     basic_request->mutable_android_app_infos()->AddAllocated(
         generator.Generate(prefs, app_id).release());
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/report_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
index f890144..5e7b546 100644
--- a/chrome/browser/enterprise/reporting/report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -28,7 +29,7 @@
 #include "extensions/common/extension_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "components/arc/arc_prefs.h"
@@ -47,7 +48,7 @@
 const char kPluginDescription[] = "This is a plugin.";
 const char kPluginFileName[] = "file_name";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kArcAppName1[] = "app_name1";
 const char kArcPackageName1[] = "package_name1";
 const char kArcActivityName1[] = "activity_name1";
@@ -56,7 +57,7 @@
 const char kArcActivityName2[] = "activity_name2";
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // We only upload serial number on Windows.
 void VerifySerialNumber(const std::string& serial_number) {
 #if defined(OS_WIN)
@@ -97,7 +98,7 @@
                                      .Build());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 arc::mojom::AppInfo CreateArcApp(const std::string& app_name,
                                  const std::string& package_name,
@@ -301,7 +302,7 @@
 
   // In the ChromeOsUserReportRequest for Chrome OS, these fields are not
   // existing. Therefore, they are skipped according to current environment.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_NE(std::string(), basic_request->computer_name());
   EXPECT_NE(std::string(), basic_request->os_user_name());
   VerifySerialNumber(basic_request->serial_number());
@@ -320,7 +321,7 @@
 
   EXPECT_TRUE(basic_request->has_browser_report());
   auto& browser_report = basic_request->browser_report();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(browser_report.has_browser_version());
   EXPECT_FALSE(browser_report.has_channel());
 #else
@@ -329,7 +330,7 @@
 #endif
   EXPECT_NE(std::string(), browser_report.executable_path());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(0, browser_report.plugins_size());
 #else
   // There might be other plugins like PDF plugin, however, our fake plugin
@@ -356,7 +357,7 @@
 
   // In the ChromeOsUserReportRequest for Chrome OS, these fields are not
   // existing. Therefore, they are skipped according to current environment.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_NE(std::string(), basic_request->computer_name());
   EXPECT_NE(std::string(), basic_request->os_user_name());
   VerifySerialNumber(basic_request->serial_number());
@@ -370,7 +371,7 @@
 
   EXPECT_TRUE(basic_request->has_browser_report());
   auto& browser_report = basic_request->browser_report();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(browser_report.has_browser_version());
   EXPECT_FALSE(browser_report.has_channel());
 #else
@@ -379,7 +380,7 @@
 #endif
   EXPECT_NE(std::string(), browser_report.executable_path());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(0, browser_report.plugins_size());
 #else
   // There might be other plugins like PDF plugin, however, our fake plugin
@@ -404,7 +405,7 @@
 
   auto* basic_request = requests[0].get();
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(basic_request->has_computer_name());
   EXPECT_FALSE(basic_request->has_os_user_name());
   EXPECT_FALSE(basic_request->has_os_report());
@@ -419,7 +420,7 @@
             basic_request->partial_report_types(0));
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(ReportGeneratorTest, ReportArcAppInChromeOS) {
   ArcAppTest arc_app_test;
diff --git a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
index e4570fc5b..33d0038 100644
--- a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -321,7 +322,7 @@
 
   auto profile_info = browser_report.chrome_user_profile_infos(0);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // In Chrome OS, the collection of policies is disabled.
   EXPECT_EQ(0, profile_info.chrome_policies_size());
 #else
diff --git a/chrome/browser/enterprise/reporting/report_scheduler_desktop.cc b/chrome/browser/enterprise/reporting/report_scheduler_desktop.cc
index 140f92b..836862d2 100644
--- a/chrome/browser/enterprise/reporting/report_scheduler_desktop.cc
+++ b/chrome/browser/enterprise/reporting/report_scheduler_desktop.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler.h"
 #include "chrome/browser/enterprise/reporting/prefs.h"
@@ -28,7 +29,7 @@
 // TODO(crbug.com/1102047): Get rid of this function after Chrome OS reporting
 // logic has been split to its own delegates.
 constexpr bool ShouldReportUpdates() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return false;
 #else
   return true;
diff --git a/chrome/browser/enterprise/reporting/report_scheduler_desktop_unittest.cc b/chrome/browser/enterprise/reporting/report_scheduler_desktop_unittest.cc
index e41a360..d9da9e81 100644
--- a/chrome/browser/enterprise/reporting/report_scheduler_desktop_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_scheduler_desktop_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler.h"
 #include "chrome/browser/enterprise/reporting/prefs.h"
@@ -105,7 +106,7 @@
     generator_ = generator_ptr_.get();
     uploader_ptr_ = std::make_unique<MockReportUploader>();
     uploader_ = uploader_ptr_.get();
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     SetLastUploadVersion(chrome::kChromeVersion);
 #endif
     Init(true, kDMToken, kClientId);
@@ -136,7 +137,7 @@
                                        std::make_unique<base::Value>(enabled));
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void SetLastUploadVersion(const std::string& version) {
     local_state_.Get()->SetString(kLastUploadVersion, version);
   }
@@ -144,7 +145,7 @@
   void ExpectLastUploadVersion(const std::string& version) {
     EXPECT_EQ(local_state_.Get()->GetString(kLastUploadVersion), version);
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // If lastUploadTimestamp is updated recently, it should be updated as Now().
   // Otherwise, it should be same as previous set timestamp.
@@ -168,7 +169,7 @@
 
   // Chrome OS needn't setup registration.
   void EXPECT_CALL_SetupRegistration() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     EXPECT_CALL(*client_, SetupRegistration(_, _, _)).Times(0);
 #else
     EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _));
@@ -176,7 +177,7 @@
   }
 
   void EXPECT_CALL_SetupRegistrationWithSetDMToken() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     EXPECT_CALL(*client_, SetupRegistration(_, _, _)).Times(0);
 #else
     EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _))
@@ -237,7 +238,7 @@
 }
 
 // Chrome OS needn't set dm token and client id in the report scheduler.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_P(ReportSchedulerFeatureTest, NoReportWithoutDMToken) {
   Init(true, "", kClientId);
   CreateScheduler();
@@ -431,7 +432,7 @@
   ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Tests that a basic report is generated and uploaded when a browser update is
 // detected.
@@ -599,7 +600,7 @@
   histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 1, 1);
 }
 
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(ReportSchedulerTest, OnExtensionRequest) {
   SetLastUploadInHour(base::TimeDelta::FromHours(1));
@@ -656,7 +657,7 @@
   ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(ReportSchedulerTest, OnExtensionRequestAndUpdate) {
   SetLastUploadInHour(base::TimeDelta::FromHours(1));
@@ -703,6 +704,6 @@
   histogram_tester_.ExpectBucketCount(kUploadTriggerMetricName, 4, 1);
 }
 
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/util/managed_browser_utils.cc b/chrome/browser/enterprise/util/managed_browser_utils.cc
index 8389538..5ca457d2 100644
--- a/chrome/browser/enterprise/util/managed_browser_utils.cc
+++ b/chrome/browser/enterprise/util/managed_browser_utils.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/enterprise/util/managed_browser_utils.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
@@ -18,12 +19,12 @@
 #include "chrome/browser/profiles/profile_android.h"
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "components/user_manager/user_manager.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace chrome {
 namespace enterprise_util {
@@ -34,7 +35,7 @@
   if (profile_connector->IsManaged())
     return true;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // This session's primary user may also have policies, and those policies may
   // not have per-profile support.
   auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser();
diff --git a/chrome/browser/enterprise/util/managed_browser_utils_unittest.cc b/chrome/browser/enterprise/util/managed_browser_utils_unittest.cc
index b3fd5d22..75047330 100644
--- a/chrome/browser/enterprise/util/managed_browser_utils_unittest.cc
+++ b/chrome/browser/enterprise/util/managed_browser_utils_unittest.cc
@@ -7,17 +7,18 @@
 #include <memory>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/values.h"
 #include "components/policy/core/browser/browser_policy_connector_base.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST(ManagedBrowserUtils, NoPolicies) {
   content::BrowserTaskEnvironment task_environment;
@@ -35,7 +36,7 @@
       chrome::enterprise_util::HasBrowserPoliciesApplied(profile.get()));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 class ManagedBrowserUtilsTest : public testing::Test {
  protected:
   void SetUp() override {
@@ -64,4 +65,4 @@
 
   EXPECT_TRUE(chrome::enterprise_util::HasBrowserPoliciesApplied(&profile));
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 07ba5a3..304b245 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -442,6 +442,9 @@
       GenerateFeatureFlag("languagesettingsupdate",
                           base::FeatureList::IsEnabled(
                               chromeos::features::kLanguageSettingsUpdate)));
+  features->AppendString(GenerateFeatureFlag(
+      "multilingualtyping",
+      base::FeatureList::IsEnabled(chromeos::features::kMultilingualTyping)));
 
   results->Set("features", std::move(features));
 
diff --git a/chrome/browser/feedback/feedback_dialog_utils.cc b/chrome/browser/feedback/feedback_dialog_utils.cc
index eef5f088..e1375b95 100644
--- a/chrome/browser/feedback/feedback_dialog_utils.cc
+++ b/chrome/browser/feedback/feedback_dialog_utils.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/feedback/feedback_dialog_utils.h"
 
 #include "ash/public/cpp/multi_user_window_manager.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -15,7 +16,7 @@
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -59,7 +60,7 @@
   profile = profile->GetOriginalProfile();
   DCHECK(profile);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Obtains the display profile ID on which the Feedback window should show.
   auto* const window_manager = MultiUserWindowManagerHelper::GetWindowManager();
   const AccountId display_account_id =
diff --git a/chrome/browser/feedback/feedback_uploader_chrome.cc b/chrome/browser/feedback/feedback_uploader_chrome.cc
index a1cafd1..3e1c731 100644
--- a/chrome/browser/feedback/feedback_uploader_chrome.cc
+++ b/chrome/browser/feedback/feedback_uploader_chrome.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/feedback/feedback_report.h"
@@ -16,14 +17,14 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/chromebox_for_meetings/buildflags/buildflags.h"
 #if BUILDFLAG(PLATFORM_CFM)
 #include "chrome/browser/chromeos/policy/enrollment_requisition_manager.h"
 #include "chrome/browser/device_identity/device_identity_provider.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
 #endif  // BUILDFLAG(PLATFORM_CFM)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace feedback {
 
@@ -68,7 +69,7 @@
   AccessTokenAvailable(error, access_token_info.token);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #if BUILDFLAG(PLATFORM_CFM)
 void FeedbackUploaderChrome::ActiveAccountAccessTokenAvailable(
     GoogleServiceAuthError error,
@@ -78,7 +79,7 @@
   AccessTokenAvailable(error, token);
 }
 #endif  // BUILDFLAG(PLATFORM_CFM)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void FeedbackUploaderChrome::AccessTokenAvailable(GoogleServiceAuthError error,
                                                   std::string token) {
@@ -124,7 +125,7 @@
     return;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #if BUILDFLAG(PLATFORM_CFM)
   // CFM Devices may need to acquire the auth token for their robot account
   // before they submit feedback.
@@ -148,7 +149,7 @@
     return;
   }
 #endif  // BUILDFLAG(PLATFORM_CFM)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   LOG(ERROR) << "Failed to request oauth access token. "
              << kAuthenticationErrorLogMessage;
diff --git a/chrome/browser/feedback/feedback_uploader_chrome.h b/chrome/browser/feedback/feedback_uploader_chrome.h
index cf98f653..592d606 100644
--- a/chrome/browser/feedback/feedback_uploader_chrome.h
+++ b/chrome/browser/feedback/feedback_uploader_chrome.h
@@ -9,15 +9,16 @@
 
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
+#include "build/chromeos_buildflags.h"
 #include "components/feedback/feedback_uploader.h"
 #include "components/signin/public/identity_manager/access_token_info.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/chromebox_for_meetings/buildflags/buildflags.h"
 #if BUILDFLAG(PLATFORM_CFM)
 #include "components/invalidation/public/identity_provider.h"
 #endif  // BUILDFLAG(PLATFORM_CFM)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace signin {
 class PrimaryAccountAccessTokenFetcher;
@@ -59,7 +60,7 @@
 
   void AccessTokenAvailable(GoogleServiceAuthError error, std::string token);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #if BUILDFLAG(PLATFORM_CFM)
   void ActiveAccountAccessTokenAvailable(GoogleServiceAuthError error,
                                          std::string token);
@@ -67,7 +68,7 @@
   std::unique_ptr<invalidation::ActiveAccountAccessTokenFetcher>
       active_account_token_fetcher_;
 #endif  // BUILDFLAG(PLATFORM_CFM)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
       primary_account_token_fetcher_;
diff --git a/chrome/browser/feedback/show_feedback_page.cc b/chrome/browser/feedback/show_feedback_page.cc
index abccf18..24b5255 100644
--- a/chrome/browser/feedback/show_feedback_page.cc
+++ b/chrome/browser/feedback/show_feedback_page.cc
@@ -7,6 +7,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/feedback/feedback_dialog_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -18,7 +19,7 @@
 #include "components/signin/public/identity_manager/consent_level.h"
 #include "extensions/browser/api/feedback_private/feedback_private_api.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/bind.h"
 #include "chrome/browser/chromeos/crosapi/browser_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -26,7 +27,7 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #endif
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chromeos/lacros/lacros_chrome_service_impl.h"
 #endif
 
@@ -36,7 +37,7 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Returns whether the user has an internal Google account (e.g. @google.com).
 bool IsGoogleInternalAccount(Profile* profile) {
   auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
@@ -81,7 +82,7 @@
                            description_placeholder_text, category_tag,
                            extra_diagnostics);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // TODO(http://crbug.com/1132106): Include the following code only in
 // non-lacros builds after M87 beta when Feedback crosapi is available in all
@@ -103,7 +104,7 @@
           : feedback_private::FeedbackFlow::FEEDBACK_FLOW_REGULAR;
 
   bool include_bluetooth_logs = false;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (IsGoogleInternalAccount(profile)) {
     flow = feedback_private::FeedbackFlow::FEEDBACK_FLOW_GOOGLEINTERNAL;
     include_bluetooth_logs = IsFromUserInteraction(source);
@@ -118,7 +119,7 @@
 
 }  // namespace
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 namespace internal {
 // Requests to show Feedback ui remotely in ash via crosapi mojo call.
 void ShowFeedbackPageLacros(const GURL& page_url,
@@ -144,7 +145,7 @@
 
   Profile* profile = GetFeedbackProfile(browser);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // When users invoke the feedback dialog by pressing alt-shift-i without
   // an active ash window, we need to check if there is an active lacros window
   // and show its Url in the feedback dialog if there is any.
@@ -162,7 +163,7 @@
   ShowFeedbackPage(page_url, profile, source, description_template,
                    description_placeholder_text, category_tag,
                    extra_diagnostics);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void ShowFeedbackPage(const GURL& page_url,
@@ -183,7 +184,7 @@
   UMA_HISTOGRAM_ENUMERATION("Feedback.RequestSource", source,
                             kFeedbackSourceCount);
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   if (chromeos::LacrosChromeServiceImpl::Get()->IsFeedbackAvailable()) {
     // Send request to ash via crosapi mojo to show Feedback ui from ash.
     internal::ShowFeedbackPageLacros(page_url, source, description_template,
@@ -204,7 +205,7 @@
   RequestFeedbackFlow(page_url, profile, source, description_template,
                       description_placeholder_text, category_tag,
                       extra_diagnostics);
-#endif  //  BUILDFLAG(IS_LACROS)
+#endif  //  BUILDFLAG(IS_CHROMEOS_LACROS)
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/feedback/show_feedback_page_unittest.cc b/chrome/browser/feedback/show_feedback_page_unittest.cc
index 3135aac..806491fe 100644
--- a/chrome/browser/feedback/show_feedback_page_unittest.cc
+++ b/chrome/browser/feedback/show_feedback_page_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
@@ -12,7 +13,7 @@
 using ShowFeedbackPageTest = BrowserWithTestWindowTest;
 
 // TODO(crbug.com/1128855): Fix the test for Lacros build.
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 #define MAYBE_UserFeedbackDisallowed DISABLED_UserFeedbackDisallowed
 #else
 #define MAYBE_UserFeedbackDisallowed UserFeedbackDisallowed
diff --git a/chrome/browser/feedback/system_logs/about_system_logs_fetcher.cc b/chrome/browser/feedback/system_logs/about_system_logs_fetcher.cc
index 5f709955..e44f52b 100644
--- a/chrome/browser/feedback/system_logs/about_system_logs_fetcher.cc
+++ b/chrome/browser/feedback/system_logs/about_system_logs_fetcher.cc
@@ -7,11 +7,12 @@
 #include <memory>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h"
 #include "chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.h"
 #include "components/feedback/system_logs/system_logs_fetcher.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
 #include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
 #include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
@@ -32,7 +33,7 @@
   fetcher->AddSource(std::make_unique<ChromeInternalLogSource>());
   fetcher->AddSource(std::make_unique<MemoryDetailsLogSource>());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // These sources rely on scrubbing in SystemLogsFetcher.
   fetcher->AddSource(std::make_unique<CommandLineLogSource>());
   fetcher->AddSource(std::make_unique<DBusLogSource>());
diff --git a/chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.cc b/chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.cc
index 528e746..906510a 100644
--- a/chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.cc
+++ b/chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "components/feedback/system_logs/system_logs_fetcher.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/crosapi/browser_manager.h"
 #include "chrome/browser/chromeos/crosapi/browser_util.h"
 #include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
@@ -29,13 +29,13 @@
 #include "chrome/browser/chromeos/system_logs/ui_hierarchy_log_source.h"
 #endif
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/feedback/system_logs/log_sources/user_log_files_log_source.h"
 #endif
 
 namespace system_logs {
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 namespace {
 
 constexpr char kDefaultLogPath[] = "/home/chronos/user/lacros/lacros.log";
@@ -52,7 +52,7 @@
   fetcher->AddSource(std::make_unique<CrashIdsSource>());
   fetcher->AddSource(std::make_unique<MemoryDetailsLogSource>());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // These sources rely on scrubbing in SystemLogsFetcher.
   fetcher->AddSource(std::make_unique<CommandLineLogSource>());
   fetcher->AddSource(std::make_unique<DBusLogSource>());
@@ -75,17 +75,17 @@
   }
 #endif
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   fetcher->AddSource(std::make_unique<UserLogFilesLogSource>(
       base::FilePath(kDefaultLogPath), kLacrosUserLogKey));
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (crosapi::browser_util::IsLacrosEnabled()) {
     fetcher->AddSource(std::make_unique<UserLogFilesLogSource>(
         base::FilePath(kDefaultLogPath), kLacrosUserLogKey));
   }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   return fetcher;
 }
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
index 834b8a2..11459e1654a 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -21,6 +21,7 @@
 #include "base/task/thread_pool.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
@@ -38,7 +39,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/ash_interfaces.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
@@ -78,11 +79,11 @@
 constexpr char kDataReductionProxyKey[] = "data_reduction_proxy";
 constexpr char kChromeVersionTag[] = "CHROME VERSION";
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 constexpr char kLacrosChromeVersionPrefix[] = "Lacros ";
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 constexpr char kAshChromeVersionPrefix[] = "Ash ";
 constexpr char kArcPolicyComplianceReportKey[] =
     "CHROMEOS_ARC_POLICY_COMPLIANCE_REPORT";
@@ -100,7 +101,7 @@
 constexpr char kOnboardingTime[] = "ONBOARDING_TIME";
 #else
 constexpr char kOsVersionTag[] = "OS VERSION";
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
 constexpr char kUsbKeyboardDetected[] = "usb_keyboard_detected";
@@ -118,7 +119,7 @@
 constexpr char kCpuArch[] = "cpu_arch";
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::string GetPrimaryAccountTypeString() {
   DCHECK(user_manager::UserManager::Get());
@@ -230,7 +231,7 @@
   response->emplace(kChromeOsFirmwareVersion,
                     chromeos::version_loader::GetFirmware());
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::string GetChromeVersionString() {
   // Version of the current running browser.
@@ -239,11 +240,11 @@
 // This is used by simple lacros feedback for backward compatibility.
 // TODO(http://crbug.com/1132106): Remove after M87 beta when Feedback
 // crosapi is available in all ash versions.
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   browser_version = kLacrosChromeVersionPrefix + browser_version;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // If the device is receiving LTS updates, add a prefix to the version string.
   // The value of the policy is ignored here.
   std::string value;
@@ -263,7 +264,7 @@
     return kLacrosChromeVersionPrefix + lacros_version + ", " +
            kAshChromeVersionPrefix + browser_version;
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   return browser_version;
 }
 
@@ -316,10 +317,10 @@
 
 ChromeInternalLogSource::ChromeInternalLogSource()
     : SystemLogsSource("ChromeInternal") {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::BindCrosDisplayConfigController(
       cros_display_config_.BindNewPipeAndPassReceiver());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 ChromeInternalLogSource::~ChromeInternalLogSource() {
@@ -332,7 +333,7 @@
   auto response = std::make_unique<SystemLogsResponse>();
   response->emplace(kChromeVersionTag, GetChromeVersionString());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   response->emplace(kChromeEnrollmentTag, GetEnrollmentStatusString());
 #else
   // On ChromeOS, this will be pulled in from the LSB_RELEASE.
@@ -359,7 +360,7 @@
   if (ProfileManager::GetLastUsedProfile()->IsChild())
     response->emplace("account_type", "child");
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Store ARC enabled status.
   bool is_arc_enabled = arc::IsArcPlayStoreEnabledForProfile(
       ProfileManager::GetLastUsedProfile());
@@ -390,7 +391,7 @@
 #else
   // On other platforms, we're done. Invoke the callback.
   std::move(callback).Run(std::move(response));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void ChromeInternalLogSource::PopulateSyncLogs(SystemLogsResponse* response) {
@@ -468,7 +469,7 @@
                     data_saver_enabled ? "enabled" : "disabled");
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void ChromeInternalLogSource::PopulateLocalStateSettings(
     SystemLogsResponse* response) {
   // Extract the "settings" entry in the local state and serialize back to
@@ -518,7 +519,7 @@
                                        exploded.month, exploded.day_of_month));
 }
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
 void ChromeInternalLogSource::PopulateUsbKeyboardDetected(
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
index fdd95c4ce..b04ff4d 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
@@ -7,9 +7,10 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/feedback/system_logs/system_logs_source.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/mojom/cros_display_config.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #endif
@@ -31,11 +32,11 @@
   void PopulatePowerApiLogs(SystemLogsResponse* response);
   void PopulateDataReductionProxyLogs(SystemLogsResponse* response);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void PopulateLocalStateSettings(SystemLogsResponse* response);
   void PopulateArcPolicyStatus(SystemLogsResponse* response);
   void PopulateOnboardingTime(SystemLogsResponse* response);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
   void PopulateUsbKeyboardDetected(SystemLogsResponse* response);
@@ -44,7 +45,7 @@
   void PopulateLastUpdateState(SystemLogsResponse* response);
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   mojo::Remote<ash::mojom::CrosDisplayConfigController> cros_display_config_;
 #endif
 
diff --git a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source.cc b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source.cc
index e848b83..5c337f0 100644
--- a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source.cc
@@ -9,11 +9,12 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/crash_upload_list/crash_upload_list.h"
 #include "components/feedback/feedback_report.h"
 #include "content/public/browser/browser_thread.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
@@ -62,7 +63,7 @@
   base::OnceClosure list_available_cb = base::BindOnce(
       &CrashIdsSource::OnUploadListAvailable, weak_ptr_factory_.GetWeakPtr());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Upload recent crashes so that they're shown in the report.
   // Non-chromeOS systems upload crashes shortly after they happen. ChromeOS is
   // unique in that it has a separate process (crash_sender) that uploads
diff --git a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
index 438c33b..e9e38d4f 100644
--- a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
@@ -3,12 +3,13 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/feedback/system_logs/log_sources/crash_ids_source.h"
+#include "build/chromeos_buildflags.h"
 #include "components/feedback/system_logs/system_logs_source.h"
 #include "components/upload_list/upload_list.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #endif
@@ -31,7 +32,7 @@
   void RequestSingleUpload(const std::string& local_id) override {}
 };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class TestDebugDaemonClient : public chromeos::FakeDebugDaemonClient {
  public:
   TestDebugDaemonClient() = default;
@@ -70,6 +71,6 @@
 
   EXPECT_EQ(1, fake_debug_client()->upload_crashes_called());
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace system_logs
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc
index 925b4e1b..75737d3d 100644
--- a/chrome/browser/first_run/first_run_browsertest.cc
+++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -58,7 +58,7 @@
   EXPECT_FALSE(ShouldShowWelcomePage());
 }
 
-#if !defined(OS_CHROMEOS) && !BUILDFLAG(IS_LACROS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)
 namespace {
 
 // A generic test class to be subclassed by test classes testing specific
@@ -420,6 +420,6 @@
                          FirstRunMasterPrefsVariationsSeedTest,
                          testing::Bool());
 
-#endif  // !defined(OS_CHROMEOS) && !BUILDFLAG(IS_LACROS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)
 
 }  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_dialog.h b/chrome/browser/first_run/first_run_dialog.h
index 6ce444f..ba4a13b6 100644
--- a/chrome/browser/first_run/first_run_dialog.h
+++ b/chrome/browser/first_run/first_run_dialog.h
@@ -7,9 +7,12 @@
 
 #include "base/callback_forward.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 // Hide this function on platforms where the dialog does not exist.
-#if defined(OS_MAC) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_MAC) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 
 class Profile;
 
diff --git a/chrome/browser/first_run/first_run_internal.h b/chrome/browser/first_run/first_run_internal.h
index 2164b8e..b16689a 100644
--- a/chrome/browser/first_run/first_run_internal.h
+++ b/chrome/browser/first_run/first_run_internal.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_FIRST_RUN_FIRST_RUN_INTERNAL_H_
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 class Profile;
 
@@ -55,13 +56,16 @@
                                      bool force_first_run,
                                      bool no_first_run);
 
-#if defined(OS_MAC) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_MAC) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 // For testing, forces the first run dialog to either be shown or not. If not
 // called, the decision to show the dialog or not will be made by Chrome based
 // on a number of factors (such as install type, whether it's a Chrome-branded
 // build, etc).
 void ForceFirstRunDialogShownForTesting(bool shown);
-#endif  // defined(OS_MAC) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#endif  // defined(OS_MAC) || (defined(OS_LINUX) ||
+        // BUILDFLAG(IS_CHROMEOS_LACROS))
 
 }  // namespace internal
 }  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_internal_posix.cc b/chrome/browser/first_run/first_run_internal_posix.cc
index 027bc67c..c9f8852 100644
--- a/chrome/browser/first_run/first_run_internal_posix.cc
+++ b/chrome/browser/first_run/first_run_internal_posix.cc
@@ -10,6 +10,7 @@
 #include "base/path_service.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/first_run/first_run_dialog.h"
@@ -26,12 +27,12 @@
 
 namespace first_run {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 base::OnceClosure& GetBeforeShowFirstRunDialogHookForTesting() {
   static base::NoDestructor<base::OnceClosure> closure;
   return *closure;
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace internal {
 namespace {
@@ -45,7 +46,7 @@
 ForcedShowDialogState g_forced_show_dialog_state =
     ForcedShowDialogState::kNotForced;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Returns whether the first run dialog should be shown. This is only true for
 // certain builds, and only if the user has not already set preferences. In a
 // real, official-build first run, initializes the default metrics reporting if
@@ -96,7 +97,7 @@
 }
 
 void DoPostImportPlatformSpecificTasks(Profile* profile) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (!ShouldShowFirstRunDialog())
     return;
 
diff --git a/chrome/browser/first_run/upgrade_util.h b/chrome/browser/first_run/upgrade_util.h
index ac04852..1732727 100644
--- a/chrome/browser/first_run/upgrade_util.h
+++ b/chrome/browser/first_run/upgrade_util.h
@@ -9,8 +9,9 @@
 
 #include "base/callback_forward.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
 #error Not used on Android or ChromeOS
 #endif
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 184be0b..37ec161f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1425,6 +1425,16 @@
     "expiry_milestone": 90
   },
   {
+    "name": "enable-cros-multilingual-typing",
+    "owners": [ "tranbaoduy", "essential-inputs-team@google.com" ],
+    "expiry_milestone": 92
+  },
+  {
+    "name": "enable-cros-on-device-grammar-check",
+    "owners": [ "jiwan", "essential-inputs-team@google.com" ],
+    "expiry_milestone": 95
+  },
+  {
     "name": "enable-cros-system-latin-physical-typing",
     "owners": [ "shend", "essential-inputs-team@google.com" ],
     "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 4fa6c8d9..e555902 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3747,6 +3747,10 @@
 const char kCrosLanguageSettingsUpdateDescription[] =
     "Enable this flag to see the new language settings update.";
 
+const char kCrosOnDeviceGrammarCheckName[] = "On-device Grammar Check";
+const char kCrosOnDeviceGrammarCheckDescription[] =
+    "Enable new on-device grammar check component.";
+
 const char kCrosRegionsModeName[] = "Cros-regions load mode";
 const char kCrosRegionsModeDescription[] =
     "This flag controls cros-regions load mode";
@@ -4375,6 +4379,10 @@
     "The toggle allows users to set whether a network should be considered "
     "metered for purposes of bandwith usage (e.g. for automatic updates).";
 
+const char kMultilingualTypingName[] = "Multilingual typing on CrOS";
+const char kMultilingualTypingDescription[] =
+    "Enables support for multilingual assistive typing on Chrome OS.";
+
 const char kNearbySharingName[] = "Nearby Sharing";
 const char kNearbySharingDescription[] =
     "Enables Nearby Sharing for sharing content between devices.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 667be75..e163baa 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2170,6 +2170,9 @@
 extern const char kCrosLanguageSettingsUpdateName[];
 extern const char kCrosLanguageSettingsUpdateDescription[];
 
+extern const char kCrosOnDeviceGrammarCheckName[];
+extern const char kCrosOnDeviceGrammarCheckDescription[];
+
 extern const char kCrosRegionsModeName[];
 extern const char kCrosRegionsModeDescription[];
 extern const char kCrosRegionsModeDefault[];
@@ -2558,6 +2561,9 @@
 extern const char kMeteredShowToggleName[];
 extern const char kMeteredShowToggleDescription[];
 
+extern const char kMultilingualTypingName[];
+extern const char kMultilingualTypingDescription[];
+
 extern const char kNearbySharingName[];
 extern const char kNearbySharingDescription[];
 
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc
index a78aebc..72a4a14 100644
--- a/chrome/browser/lifetime/application_lifetime.cc
+++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -13,6 +13,7 @@
 #include "base/process/process_handle.h"
 #include "base/types/strong_alias.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -42,7 +43,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/boot_times_recorder.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -50,7 +51,7 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/user_manager.h"
 #endif
 
@@ -84,7 +85,7 @@
 }
 #endif  // !defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Sets kApplicationLocale in |local_state| for the login screen on the next
 // application start, if it is forced to a specific value due to enterprise
 // policy or the owner's locale.  Returns true if any pref has been modified.
@@ -132,7 +133,7 @@
   PrefService* pref_service = g_browser_process->local_state();
   pref_service->SetBoolean(prefs::kWasRestarted, true);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::BootTimesRecorder::Get()->set_restart_requested();
 
   DCHECK(!g_send_stop_request_to_session_manager);
@@ -212,7 +213,7 @@
     return;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker(
       "StartedClosingWindows", false);
 #endif
@@ -223,7 +224,7 @@
 #endif  // !defined(OS_ANDROID)
 
 void AttemptUserExit() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   VLOG(1) << "AttemptUserExit";
   chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker("LogoutStarted",
                                                           false);
@@ -250,7 +251,7 @@
   PrefService* pref_service = g_browser_process->local_state();
   pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false);
   AttemptExitInternal(false);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // The Android implementation is in application_lifetime_android.cc
@@ -261,7 +262,7 @@
 #endif  // !defined(OS_ANDROID)
 
 void AttemptRelaunch() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::PowerManagerClient::Get()->RequestRestart(
       power_manager::REQUEST_RESTART_OTHER, "Chrome relaunch");
   // If running the Chrome OS build, but we're not on the device, fall through.
@@ -271,7 +272,7 @@
 
 #if !defined(OS_ANDROID)
 void RelaunchIgnoreUnloadHandlers() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::PowerManagerClient::Get()->RequestRestart(
       power_manager::REQUEST_RESTART_OTHER, "Chrome relaunch");
   // If running the Chrome OS build, but we're not on the device, fall through.
@@ -281,7 +282,7 @@
 #endif
 
 void AttemptExit() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, user exit and system exits are the same.
   AttemptUserExit();
 #else
@@ -304,7 +305,7 @@
   // We always mark exit cleanly.
   MarkAsCleanShutdown();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS ExitIgnoreUnloadHandlers() is used to handle SIGTERM.
   // In this case, AreAllBrowsersCloseable()
   // can be false in following cases. a) power-off b) signout from
@@ -312,16 +313,16 @@
   browser_shutdown::OnShutdownStarting(
       AreAllBrowsersCloseable() ? browser_shutdown::ShutdownType::kBrowserExit
                                 : browser_shutdown::ShutdownType::kEndSession);
-#else   // defined(OS_CHROMEOS)
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
   // For desktop browsers, always perform a silent exit.
   browser_shutdown::OnShutdownStarting(
       browser_shutdown::ShutdownType::kSilentExit);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #endif  // !defined(OS_ANDROID)
   AttemptExitInternal(true);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 bool IsAttemptingShutdown() {
   return g_send_stop_request_to_session_manager;
 }
diff --git a/chrome/browser/lifetime/application_lifetime.h b/chrome/browser/lifetime/application_lifetime.h
index f466421..1686031 100644
--- a/chrome/browser/lifetime/application_lifetime.h
+++ b/chrome/browser/lifetime/application_lifetime.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 class Browser;
 
@@ -57,7 +58,7 @@
 // use AttemptExit or AttemptRestart respectively.
 void ExitIgnoreUnloadHandlers();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Returns true if any of the above Attempt calls have been called.
 bool IsAttemptingShutdown();
 #endif
diff --git a/chrome/browser/lifetime/application_lifetime_aura.cc b/chrome/browser/lifetime/application_lifetime_aura.cc
index c0a2ae1..d339d60 100644
--- a/chrome/browser/lifetime/application_lifetime_aura.cc
+++ b/chrome/browser/lifetime/application_lifetime_aura.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/lifetime/termination_notification.h"
@@ -14,7 +15,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/shell.h"
 #else
 #include "chrome/browser/notifications/notification_ui_manager.h"
@@ -26,7 +27,7 @@
   // Close all non browser windows now. Those includes notifications
   // and windows created by Ash (launcher, background, etc).
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (ash::Shell::HasInstance()) {
     // Releasing the capture will close any menus that might be open:
     // http://crbug.com/134472
@@ -42,7 +43,7 @@
 
   views::Widget::CloseAllSecondaryWidgets();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableZeroBrowsersOpenForTests)) {
     // App is exiting, release the keep alive on behalf of Aura Shell.
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
index e2a4109..8ff4be0 100644
--- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/background/background_mode_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -62,7 +63,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -282,7 +283,7 @@
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     command_line->AppendSwitch(
         chromeos::switches::kIgnoreUserProfileMappingForTests);
 #endif
@@ -527,7 +528,7 @@
 // Regression for crbug.com/365052 caused some of tabs to be closed even if
 // user chose to cancel browser close.
 // Flaky on ChromeOS ASan. https://crbug.com/805457
-#if defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && defined(ADDRESS_SANITIZER)
 #define MAYBE_TestUnloadMultipleSlowTabs DISABLED_TestUnloadMultipleSlowTabs
 #else
 #define MAYBE_TestUnloadMultipleSlowTabs TestUnloadMultipleSlowTabs
diff --git a/chrome/browser/lifetime/browser_shutdown.cc b/chrome/browser/lifetime/browser_shutdown.cc
index 3d98a97..3e25f91 100644
--- a/chrome/browser/lifetime/browser_shutdown.cc
+++ b/chrome/browser/lifetime/browser_shutdown.cc
@@ -24,6 +24,7 @@
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "build/config/compiler/compiler_buildflags.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
@@ -50,11 +51,11 @@
 #include "chrome/browser/win/browser_util.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/first_run/upgrade_util.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/boot_times_recorder.h"
 #include "chrome/browser/lifetime/termination_notification.h"
 #endif
@@ -63,7 +64,7 @@
 #include "chrome/browser/background/background_mode_manager.h"
 #endif
 
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/service_process/service_process_control.h"
 #endif
 
@@ -224,11 +225,11 @@
 
 #if !defined(OS_ANDROID)
 bool ShutdownPreThreadsStop() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker(
       "BrowserShutdownStarted", false);
 #endif
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !BUILDFLAG(IS_CHROMEOS_ASH)
   // Shutdown the IPC channel to the service processes.
   ServiceProcessControl::GetInstance()->Disconnect();
 #endif
@@ -285,7 +286,7 @@
   // goes away.
   ProfileManager::NukeDeletedProfilesFromDisk();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker("BrowserDeleted",
                                                           true);
 #endif
@@ -298,7 +299,7 @@
 #endif
 
   if (restart_mode != RestartMode::kNoRestart) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     NOTIMPLEMENTED();
 #else
     const base::CommandLine& old_cl(*base::CommandLine::ForCurrentProcess());
@@ -335,7 +336,7 @@
       new_cl.AppendSwitchNative(it.first, it.second);
 
     upgrade_util::RelaunchChromeBrowser(new_cl);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   if (g_shutdown_type != ShutdownType::kNotValid &&
@@ -355,7 +356,7 @@
     base::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   NotifyAndTerminate(false /* fast_path */);
 #endif
 }
diff --git a/chrome/browser/lifetime/browser_shutdown_browsertest.cc b/chrome/browser/lifetime/browser_shutdown_browsertest.cc
index 10d65b8..edbb096 100644
--- a/chrome/browser/lifetime/browser_shutdown_browsertest.cc
+++ b/chrome/browser/lifetime/browser_shutdown_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/lifetime/browser_shutdown.h"
@@ -21,7 +22,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/event_generator.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/aura/window.h"
 #endif
 
@@ -51,7 +52,7 @@
 
 // ChromeOS has the different shutdown flow on user initiated exit process.
 // See the comment for chrome::AttemptUserExit() function declaration.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest,
                        PRE_TwoBrowsersClosingShutdownHistograms) {
   ui_test_utils::NavigateToURL(browser(), GURL("browser://version"));
@@ -102,4 +103,4 @@
 
   EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/lifetime/termination_notification.cc b/chrome/browser/lifetime/termination_notification.cc
index 3ecdce0..79ba3dae 100644
--- a/chrome/browser/lifetime/termination_notification.cc
+++ b/chrome/browser/lifetime/termination_notification.cc
@@ -5,13 +5,14 @@
 #include "chrome/browser/lifetime/termination_notification.h"
 
 #include "base/bind.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
@@ -37,7 +38,7 @@
 }
 
 void NotifyAndTerminate(bool fast_path, RebootPolicy reboot_policy) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   static bool notified = false;
   // Return if a shutdown request has already been sent.
   if (notified)
@@ -48,7 +49,7 @@
   if (fast_path)
     NotifyAppTerminating();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chromeos::PowerPolicyController::IsInitialized())
     chromeos::PowerPolicyController::Get()->NotifyChromeIsExiting();
 
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
index 9c13bc3..3e5a33b5 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
@@ -20,6 +20,7 @@
 #include "base/task/lazy_thread_pool_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_validator_factory.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
@@ -45,7 +46,7 @@
 #include "storage/common/file_system/file_system_types.h"
 #include "storage/common/file_system/file_system_util.h"
 
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
 #endif
 
@@ -138,7 +139,7 @@
           std::make_unique<MediaFileValidatorFactory>()),
       native_media_file_util_(
           std::make_unique<NativeMediaFileUtil>(g_media_task_runner.Get()))
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
       ,
       device_media_async_file_util_(
           DeviceMediaAsyncFileUtil::Create(profile_path_,
@@ -242,7 +243,7 @@
   switch (type) {
     case storage::kFileSystemTypeNativeMedia:
       return native_media_file_util_.get();
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
     case storage::kFileSystemTypeDeviceMedia:
       return device_media_async_file_util_.get();
 #endif
@@ -290,7 +291,7 @@
 
 bool MediaFileSystemBackend::SupportsStreaming(
     const storage::FileSystemURL& url) const {
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
   if (url.type() == storage::kFileSystemTypeDeviceMedia)
     return device_media_async_file_util_->SupportsStreaming(url);
 #endif
@@ -312,7 +313,7 @@
     int64_t max_bytes_to_read,
     const base::Time& expected_modification_time,
     FileSystemContext* context) const {
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
   if (url.type() == storage::kFileSystemTypeDeviceMedia) {
     std::unique_ptr<storage::FileStreamReader> reader =
         device_media_async_file_util_->GetFileStreamReader(
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
index c6919dc9..c26d83b7 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "storage/browser/file_system/file_system_backend.h"
 #include "storage/browser/file_system/task_runner_bound_observer_list.h"
@@ -104,7 +105,7 @@
 
   std::unique_ptr<storage::AsyncFileUtil> native_media_file_util_;
 
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<DeviceMediaAsyncFileUtil> device_media_async_file_util_;
 #endif
 
diff --git a/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc b/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
index bcad334..13f0c9a 100644
--- a/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
+++ b/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_path_override.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager_observer.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
@@ -29,7 +30,7 @@
 #include "extensions/common/extension.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #endif
@@ -57,7 +58,7 @@
  public:
   GalleryWatchManagerTest()
       : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         test_user_manager_(std::make_unique<chromeos::ScopedTestUserManager>()),
 #endif
         profile_(new TestingProfile()),
@@ -104,7 +105,7 @@
     // because TestingProfile uses TestingBrowserProcess in its destructor.
     ShutdownProfile();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // The TestUserManager must be destroyed before the TestingBrowserProcess
     // because TestUserManager uses TestingBrowserProcess in its destructor.
     test_user_manager_.reset();
@@ -200,7 +201,7 @@
 
   EnsureMediaDirectoriesExists mock_gallery_locations_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
   std::unique_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
 #endif
@@ -217,7 +218,7 @@
 };
 
 // TODO(crbug.com/936065): Flaky on ChromeOS.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_Basic DISABLED_Basic
 #else
 #define MAYBE_Basic Basic
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 278e50c..a1f79d3 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/stl_util.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
 #include "chrome/browser/media_galleries/media_file_system_context.h"
@@ -45,7 +46,7 @@
 #include "storage/common/file_system/file_system_mount_option.h"
 #include "storage/common/file_system/file_system_types.h"
 
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
 #endif
 
@@ -666,7 +667,7 @@
   void RevokeFileSystem(const std::string& fs_name) override {
     ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
 
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
     content::GetIOThreadTaskRunner({})->PostTask(
         FROM_HERE,
         base::BindOnce(&MTPDeviceMapService::RevokeMTPFileSystem,
@@ -705,7 +706,7 @@
   bool RegisterFileSystemForMTPDevice(const std::string& device_id,
                                       const std::string fs_name,
                                       const base::FilePath& path) {
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(!StorageInfo::IsMassStorageDevice(device_id));
 
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
index c1187335..bfe9f52 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -27,6 +27,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/media_galleries/media_file_system_context.h"
@@ -51,7 +52,7 @@
 #include "extensions/common/extension.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #endif
 
@@ -284,7 +285,7 @@
 };
 
 base::string16 GetExpectedFolderName(const base::FilePath& path) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return path.BaseName().LossyDisplayName();
 #else
   return path.LossyDisplayName();
@@ -391,7 +392,7 @@
 
   // Needed for extension service & friends to work.
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
 #endif
 
@@ -692,7 +693,7 @@
     // Make sure that we have at least one gallery and that they are all
     // auto added galleries.
     const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
     ASSERT_GT(galleries.size(), 0U);
 #endif
     for (auto it = galleries.begin(); it != galleries.end(); ++it) {
@@ -710,7 +711,7 @@
   ProfileState* profile_state = GetProfileState(0U);
   *galleries_info = profile_state->GetGalleriesInfo(
       profile_state->all_permission_extension());
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
   ASSERT_EQ(3U, galleries_info->size());
 #else
   ASSERT_EQ(0U, galleries_info->size());
diff --git a/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc b/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
index 25e08f49..3747b15 100644
--- a/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller_test_util.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
@@ -24,7 +25,7 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #endif
@@ -149,7 +150,7 @@
 
   scoped_refptr<extensions::Extension> extension_;
 
-#if defined OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
   chromeos::ScopedTestUserManager test_user_manager_;
 #endif
@@ -253,7 +254,7 @@
       StorageInfo::FIXED_MASS_STORAGE, "/path/to/gallery");
   gallery.type = MediaGalleryPrefInfo::kAutoDetected;
   std::string galleryName("/path/to/gallery");
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   galleryName = "gallery";
 #endif
   EXPECT_EQ(galleryName, GalleryName(gallery));
@@ -267,7 +268,7 @@
 
   gallery.path = base::FilePath(FILE_PATH_LITERAL("sub/gallery2"));
   galleryName = "/path/to/gallery/sub/gallery2";
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   galleryName = "gallery2";
 #endif
 #if defined(OS_WIN)
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc
index e0cc9f9..40c0304 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences.cc
@@ -23,6 +23,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
@@ -398,7 +399,7 @@
     if (!display_name.empty())
       return display_name;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // See chrome/browser/chromeos/fileapi/file_system_backend.cc
     base::FilePath download_path;
     if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE,
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 258670f..02081d7 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
@@ -40,7 +41,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #endif
@@ -358,7 +359,7 @@
 
   EnsureMediaDirectoriesExists mock_gallery_locations_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
   chromeos::ScopedTestUserManager test_user_manager_;
 #endif
@@ -1223,7 +1224,7 @@
   // default_gallery field set.
 
   // No default galleries exist on CrOS so this test isn't relevant there.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   base::FilePath music_path;
   base::FilePath pictures_path;
   base::FilePath videos_path;
@@ -1274,7 +1275,7 @@
   // rewrite the device ID in prefs to include the new path.
 
   // No default galleries exist on CrOS so this test isn't relevant there.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   base::FilePath old_music_path;
   base::FilePath old_pictures_path;
   base::FilePath old_videos_path;
@@ -1381,7 +1382,7 @@
   // MediaGalleriesPreferences is initialized, it assigns the proper one.
 
   // No default galleries exist on CrOS so this test isn't relevant there.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Add a new user added gallery.
   AddFixedGalleryWithExpectation("user_added", "UserAdded",
                                  MediaGalleryPrefInfo::kUserAdded);
diff --git a/chrome/browser/media_galleries/media_galleries_test_util.cc b/chrome/browser/media_galleries/media_galleries_test_util.cc
index f8707eb..963b70a 100644
--- a/chrome/browser/media_galleries/media_galleries_test_util.cc
+++ b/chrome/browser/media_galleries/media_galleries_test_util.cc
@@ -16,6 +16,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
@@ -143,7 +144,7 @@
 #endif  // OS_WIN
 
 void EnsureMediaDirectoriesExists::Init() {
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
   return;
 #else
 
@@ -154,7 +155,7 @@
 #endif  // OS_MAC
 
   ChangeMediaPathOverrides();
-#endif  // OS_CHROMEOS || OS_ANDROID
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || OS_ANDROID
 }
 
 base::FilePath MakeMediaGalleriesTestingPath(const std::string& dir) {
diff --git a/chrome/browser/nearby_sharing/nearby_notification_handler.cc b/chrome/browser/nearby_sharing/nearby_notification_handler.cc
index d6ccff1..39f80e82 100644
--- a/chrome/browser/nearby_sharing/nearby_notification_handler.cc
+++ b/chrome/browser/nearby_sharing/nearby_notification_handler.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/nearby_sharing/logging/logging.h"
 #include "chrome/browser/nearby_sharing/nearby_notification_delegate.h"
 #include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
@@ -17,7 +18,7 @@
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
 #endif
@@ -89,7 +90,7 @@
 
 void NearbyNotificationHandler::OpenSettings(Profile* profile,
                                              const GURL& origin) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
       profile, chromeos::settings::mojom::kNearbyShareSubpagePath);
 #else
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.cc b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
index aa065b6..6120e8f 100644
--- a/chrome/browser/nearby_sharing/nearby_notification_manager.cc
+++ b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
@@ -14,6 +14,7 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/image_decoder/image_decoder.h"
@@ -59,7 +60,7 @@
 
   // TODO(crbug.com/1102348): Also show settings for other platforms once there
   // is a nearby settings page in Chrome browser.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   notification.set_settings_button_handler(
       message_center::SettingsButtonHandler::DELEGATE);
 #endif
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc
index 4d6dd86..d22a81fa 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc
@@ -9,6 +9,7 @@
 
 #include "base/memory/singleton.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/nearby/nearby_process_manager_factory.h"
 #include "chrome/browser/nearby_sharing/common/nearby_share_features.h"
 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
@@ -26,12 +27,12 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/nearby_sharing/power_client_chromeos.h"
-#else  // !defined(OS_CHROMEOS)
+#else  // !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/nearby_sharing/power_client.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -73,7 +74,7 @@
   Profile* profile = Profile::FromBrowserContext(context);
   NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS we will only support the active profile.
   if (!chromeos::ProfileHelper::IsPrimaryProfile(profile)) {
     NS_LOG(VERBOSE)
@@ -102,11 +103,11 @@
   return new NearbySharingServiceImpl(
       pref_service, notification_display_service, profile,
       std::move(nearby_connections_manager), &process_manager,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       std::make_unique<PowerClientChromeos>());
-#else   // !defined(OS_CHROMEOS)
+#else   // !BUILDFLAG(IS_CHROMEOS_ASH)
       std::make_unique<PowerClient>());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 content::BrowserContext* NearbySharingServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index bc30eb47..4247b8f3 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -18,6 +18,7 @@
 #include "base/task/post_task.h"
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/nearby_sharing/certificates/common.h"
 #include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.h"
@@ -261,13 +262,13 @@
 
   RecordNearbyShareEnabledMetric(prefs);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   auto* session_controller = ash::SessionController::Get();
   if (session_controller) {
     is_screen_locked_ = session_controller->IsScreenLocked();
     session_controller->AddObserver(this);
   }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   nearby_process_observer_.Add(process_manager_);
   power_client_->AddObserver(this);
@@ -327,11 +328,11 @@
   if (bluetooth_adapter_)
     bluetooth_adapter_->RemoveObserver(this);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   auto* session_controller = ash::SessionController::Get();
   if (session_controller)
     session_controller->RemoveObserver(this);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   foreground_receive_callbacks_.Clear();
   background_receive_callbacks_.Clear();
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
index e95435b2..280d6d8 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_core_service_impl.h"
@@ -61,9 +62,9 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/ash/test_session_controller.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 using ::testing::_;
 using testing::AtLeast;
@@ -387,9 +388,9 @@
     device::BluetoothAdapterFactory::SetAdapterForTesting(
         mock_bluetooth_adapter_);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     session_controller_ = std::make_unique<TestSessionController>();
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     service_ = CreateService();
     SetFakeFastInitiationManagerFactory(/*should_succeed_on_start=*/true);
@@ -919,9 +920,9 @@
   FakeNearbyShareCertificateManager::Factory certificate_manager_factory_;
   std::unique_ptr<NotificationDisplayServiceTester> notification_tester_;
   NiceMock<MockNearbyProcessManager> mock_nearby_process_manager_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<TestSessionController> session_controller_;
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<NearbySharingServiceImpl> service_;
   std::unique_ptr<base::ScopedDisallowBlocking> disallow_blocking_;
   std::unique_ptr<FakeFastInitiationManagerFactory>
@@ -960,10 +961,10 @@
   bool bluetooth_enabled;
   net::NetworkChangeNotifier::ConnectionType connection_type;
 } kInvalidSendSurfaceTestData[] = {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // Screen locked
     {/*screen_locked=*/true, true, net::NetworkChangeNotifier::CONNECTION_WIFI},
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     // No network connection and no bluetooth
     {/*screen_locked=*/false, false,
      net::NetworkChangeNotifier::CONNECTION_NONE},
@@ -1445,9 +1446,9 @@
 
 TEST_P(NearbySharingServiceImplInvalidSendTest,
        RegisterSendSurfaceNotDiscovering) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   session_controller_->SetScreenLocked(GetParam().screen_locked);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   is_bluetooth_present_ = GetParam().bluetooth_enabled;
   SetConnectionType(GetParam().connection_type);
   MockTransferUpdateCallback transfer_callback;
@@ -1653,7 +1654,7 @@
   EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(NearbySharingServiceImplTest,
        ScreenLockedRegisterReceiveSurfaceNotAdvertising) {
   session_controller_->SetScreenLocked(true);
@@ -1681,7 +1682,7 @@
   session_controller_->SetScreenLocked(false);
   EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering());
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(NearbySharingServiceImplTest,
        SuspendedRegisterReceiveSurfaceNotAdvertising) {
diff --git a/chrome/browser/notifications/notification_common.cc b/chrome/browser/notifications/notification_common.cc
index 348184e..0ab150f8 100644
--- a/chrome/browser/notifications/notification_common.cc
+++ b/chrome/browser/notifications/notification_common.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/notifications/notification_common.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
@@ -34,10 +35,10 @@
 // TODO(peter): Use the |origin| to direct the user to a more appropriate
 // settings page to toggle permission.
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-  // Android settings are handled through Java. Chrome OS settings are handled
-  // through the tray's setting panel.
-  NOTREACHED();
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+// Android settings are handled through Java. Chrome OS settings are handled
+// through the tray's setting panel.
+NOTREACHED();
 #else
   chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile);
   chrome::ShowContentSettingsExceptions(browser_displayer.browser(),
diff --git a/chrome/browser/notifications/notification_display_service_impl.cc b/chrome/browser/notifications/notification_display_service_impl.cc
index ea9aeb5..f82d310 100644
--- a/chrome/browser/notifications/notification_display_service_impl.cc
+++ b/chrome/browser/notifications/notification_display_service_impl.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/notifications/non_persistent_notification_handler.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
@@ -35,7 +36,7 @@
 #include "chrome/browser/sharing/sharing_notification_handler.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/nearby_sharing/common/nearby_share_features.h"
 #include "chrome/browser/nearby_sharing/nearby_notification_handler.h"
 #endif
@@ -63,7 +64,9 @@
 // static
 void NotificationDisplayServiceImpl::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   registry->RegisterBooleanPref(prefs::kAllowNativeNotifications, true);
 #endif
 }
@@ -111,7 +114,7 @@
 
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (base::FeatureList::IsEnabled(features::kNearbySharing)) {
       AddNotificationHandler(NotificationHandler::Type::NEARBY_SHARE,
                              std::make_unique<NearbyNotificationHandler>());
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc
index 76f8c5b5..babb0e4 100644
--- a/chrome/browser/notifications/notification_interactive_uitest.cc
+++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -782,7 +782,7 @@
 // TODO(knollr): Test fails on Windows and macOS on the bots as there is no real
 // display to test with. Need to find a way to run these without a display and
 // figure out why Lacros is timing out. Tests pass locally with a real display.
-#if defined(OS_MAC) || defined(OS_WIN) || BUILDFLAG(IS_LACROS)
+#if defined(OS_MAC) || defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #define MAYBE_ShouldQueueDuringScreenPresent \
   DISABLED_ShouldQueueDuringScreenPresent
 #else
diff --git a/chrome/browser/notifications/notification_platform_bridge_chromeos.cc b/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
index 4215da8..0961a90 100644
--- a/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/ui/app_icon_loader.h"
 #include "ui/gfx/image/image.h"
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/notifications/notification_platform_bridge_lacros.h"
 #include "chromeos/lacros/lacros_chrome_service_impl.h"
 #else
@@ -37,7 +37,7 @@
 }
 
 NotificationPlatformBridgeChromeOs::NotificationPlatformBridgeChromeOs() {
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   mojo::Remote<crosapi::mojom::MessageCenter>* remote = nullptr;
   auto* service = chromeos::LacrosChromeServiceImpl::Get();
   if (service->IsMessageCenterAvailable())
diff --git a/chrome/browser/notifications/notification_platform_bridge_delegator.cc b/chrome/browser/notifications/notification_platform_bridge_delegator.cc
index 7ae9ce9c..672df19 100644
--- a/chrome/browser/notifications/notification_platform_bridge_delegator.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_delegator.cc
@@ -14,6 +14,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/notification_display_service_impl.h"
 #include "chrome/browser/profiles/profile.h"
@@ -51,11 +52,11 @@
 // the platforms supported by the browser.
 bool NativeNotificationsEnabled(Profile* profile) {
 #if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
   return true;
 #elif defined(OS_WIN)
   return NotificationPlatformBridgeWin::NativeNotificationEnabled();
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   if (profile) {
     // Prefs take precedence over flags.
     PrefService* prefs = profile->GetPrefs();
diff --git a/chrome/browser/notifications/notifier_state_tracker.cc b/chrome/browser/notifications/notifier_state_tracker.cc
index 1f937e87..0573ade 100644
--- a/chrome/browser/notifications/notifier_state_tracker.cc
+++ b/chrome/browser/notifications/notifier_state_tracker.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
@@ -79,7 +80,7 @@
       // We do not disable system component notifications.
       return true;
     case message_center::NotifierType::ARC_APPLICATION:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       // TODO(hriono): Ask Android if the application's notifications are
       // enabled.
       return true;
@@ -87,7 +88,7 @@
       break;
 #endif
     case message_center::NotifierType::CROSTINI_APPLICATION:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       // Disabling Crostini notifications is not supported yet.
       return true;
 #else
@@ -95,7 +96,7 @@
       break;
 #endif
     case message_center::NotifierType::PHONE_HUB:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       // PhoneHub notifications are controlled in their own settings.
       return true;
 #else
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
index 3bff883..0346a13 100644
--- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
+++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -19,6 +19,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/engagement/site_engagement_score.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/notifications/notification_common.h"
@@ -436,7 +437,7 @@
 }
 
 // Chrome OS shows the notification settings inline.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest,
                        WebNotificationSiteSettingsButton) {
   GrantNotificationPermissionForTest();
@@ -920,7 +921,8 @@
 #if !defined(OS_MAC)
 
 // TODO(https://crbug.com/1086169) Test is flaky on Linux TSan.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(THREAD_SANITIZER)
+#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+    defined(THREAD_SANITIZER)
 #define MAYBE_TestShouldDisplayFullscreen DISABLED_TestShouldDisplayFullscreen
 #else
 #define MAYBE_TestShouldDisplayFullscreen TestShouldDisplayFullscreen
diff --git a/chrome/browser/notifications/profile_notification.cc b/chrome/browser/notifications/profile_notification.cc
index fe13fabe..6e86d59f 100644
--- a/chrome/browser/notifications/profile_notification.cc
+++ b/chrome/browser/notifications/profile_notification.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "components/account_id/account_id.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
@@ -36,7 +37,7 @@
           notification),
       original_id_(notification.id()),
       type_(type) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (profile_) {
     notification_.set_profile_id(
         multi_user_util::GetAccountIdFromProfile(profile).GetUserEmail());
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 0cb21f7c..eca32675 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -22,6 +22,7 @@
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
@@ -141,7 +142,7 @@
 #include "extensions/common/constants.h"
 #endif
 
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 #include "chrome/browser/signin/dice_web_signin_interceptor_factory.h"
 #endif
 
@@ -1170,7 +1171,7 @@
       content_credential_manager_(this),
       password_generation_driver_receivers_(web_contents, this),
       observer_(nullptr),
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
       credentials_filter_(this, base::BindRepeating(&GetSyncService, profile_)),
 #else
       credentials_filter_(
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index c14f5f4..6514128 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom-forward.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/autofill/core/common/renderer_id.h"
@@ -51,7 +52,7 @@
 #include "chrome/browser/ui/passwords/account_storage_auth_helper.h"
 #endif
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/password_manager/core/browser/sync_credentials_filter.h"
 #else
 #include "chrome/browser/password_manager/multi_profile_credentials_filter.h"
@@ -387,7 +388,7 @@
   // point.
   BooleanPrefMember saving_passwords_enabled_;
 
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
   // ChromeOS and Android don't support multiple profiles
   const password_manager::SyncCredentialsFilter credentials_filter_;
 #else
diff --git a/chrome/browser/password_manager/generated_password_leak_detection_pref_unittest.cc b/chrome/browser/password_manager/generated_password_leak_detection_pref_unittest.cc
index f2d0b216..1dd05989 100644
--- a/chrome/browser/password_manager/generated_password_leak_detection_pref_unittest.cc
+++ b/chrome/browser/password_manager/generated_password_leak_detection_pref_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/password_manager/generated_password_leak_detection_pref.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/api/settings_private/generated_pref_test_base.h"
 #include "chrome/browser/extensions/api/settings_private/generated_prefs_factory.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
@@ -76,7 +77,7 @@
   EXPECT_EQ(test_observer.GetUpdatedPrefName(),
             kGeneratedPasswordLeakDetectionPref);
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Clearing the primary account does not make sense on ChromeOS.
   test_observer.Reset();
   identity_test_env()->ClearPrimaryAccount();
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 1b70b37..1f798e4 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -22,6 +22,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/password_manager/password_manager_test_base.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
@@ -809,7 +810,7 @@
 }
 
 // Flaky on chromeos: http://crbug.com/870372
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_PromptForFetchSubmitWithoutNavigation \
   DISABLED_PromptForFetchSubmitWithoutNavigation
 #else
@@ -846,7 +847,7 @@
 }
 
 // Flaky on chromeos: http://crbug.com/870372
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_PromptForFetchSubmitWithoutNavigation_SignupForm \
   DISABLED_PromptForFetchSubmitWithoutNavigation_SignupForm
 #else
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc
index 49f6513..9d4d56d9 100644
--- a/chrome/browser/password_manager/password_store_factory.cc
+++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/password_manager/credentials_cleaner_runner_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
@@ -129,7 +130,7 @@
 #endif
 
   scoped_refptr<PasswordStore> ps;
-#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
+#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID) || \
     defined(OS_MAC) || defined(USE_X11) || defined(USE_OZONE)
   ps = new password_manager::PasswordStoreDefault(std::move(login_db));
 #else
@@ -159,8 +160,10 @@
       profile->GetPrefs(), base::TimeDelta::FromSeconds(60),
       network_context_getter);
 
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   std::unique_ptr<password_manager::PasswordStoreSigninNotifier> notifier =
       std::make_unique<password_manager::PasswordStoreSigninNotifierImpl>(
           IdentityManagerFactory::GetForProfile(profile));
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
index 42d71231..db72792d 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/performance_manager/browser_child_process_watcher.h"
 #include "chrome/browser/performance_manager/decorators/frozen_frame_aggregator.h"
@@ -35,7 +36,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_features.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/allocator/buildflags.h"
 #include "chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h"
 
@@ -44,7 +45,7 @@
 #include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h"
 #endif  // BUILDFLAG(USE_TCMALLOC)
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
@@ -95,7 +96,7 @@
                            CreatePolicyForPlatform());
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (performance_manager::policies::UserspaceSwapPolicy::
           UserspaceSwapSupportedAndEnabled()) {
     graph->PassToGraph(
@@ -109,7 +110,7 @@
                        performance_manager::policies::DynamicTcmallocPolicy>());
   }
 #endif  // BUILDFLAG(USE_TCMALLOC)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !defined(OS_ANDROID)
   graph->PassToGraph(FormInteractionTabHelper::CreateGraphObserver());
diff --git a/chrome/browser/performance_manager/mechanisms/working_set_trimmer.cc b/chrome/browser/performance_manager/mechanisms/working_set_trimmer.cc
index c8d2e5e8..d36eb3a 100644
--- a/chrome/browser/performance_manager/mechanisms/working_set_trimmer.cc
+++ b/chrome/browser/performance_manager/mechanisms/working_set_trimmer.cc
@@ -6,10 +6,11 @@
 
 #include "base/no_destructor.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/performance_manager/mechanisms/working_set_trimmer_win.h"
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos.h"
 #endif
 
@@ -34,7 +35,7 @@
 WorkingSetTrimmer* WorkingSetTrimmer::GetInstance() {
 #if defined(OS_WIN)
   static base::NoDestructor<WorkingSetTrimmerWin> trimmer;
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   static base::NoDestructor<WorkingSetTrimmerChromeOS> trimmer;
 #else
   static base::NoDestructor<NoOpWorkingSetTrimmer> trimmer;
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper.cc b/chrome/browser/performance_manager/policies/page_discarding_helper.cc
index 6c37d1d..b60a21e 100644
--- a/chrome/browser/performance_manager/policies/page_discarding_helper.cc
+++ b/chrome/browser/performance_manager/policies/page_discarding_helper.cc
@@ -13,6 +13,7 @@
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/performance_manager/mechanisms/page_discarder.h"
 #include "chrome/browser/performance_manager/policies/policy_features.h"
 #include "components/performance_manager/graph/node_attached_data_impl.h"
@@ -28,7 +29,7 @@
 namespace policies {
 namespace {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Time during which non visible pages are protected from urgent discarding
 // (not on ChromeOS).
 constexpr base::TimeDelta kNonVisiblePagesUrgentProtectionTime =
@@ -219,7 +220,7 @@
       return false;
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (page_node->GetTimeSinceLastVisibilityChange() <
       kNonVisiblePagesUrgentProtectionTime) {
     return false;
@@ -269,7 +270,7 @@
       return false;
     if (live_state_data->IsConnectedToUSBDevice())
       return false;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // TODO(sebmarchand): Skip this check if the Entreprise memory limit is set.
     if (live_state_data->WasDiscarded())
       return false;
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
index bae8ab4..3853399 100644
--- a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
+++ b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/performance_manager/policies/policy_features.h"
 #include "chrome/browser/performance_manager/test_support/page_discarding_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -76,7 +77,7 @@
           page_node()));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PageDiscardingHelperTest, TestCannotDiscardRecentlyVisiblePage) {
   page_node()->SetIsVisible(true);
   page_node()->SetIsVisible(false);
@@ -181,7 +182,7 @@
           page_node()));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageMultipleTimes) {
   testing::FakePageLiveStateData::GetOrCreate(page_node())->was_discarded_ =
       true;
diff --git a/chrome/browser/performance_manager/policies/policy_features.cc b/chrome/browser/performance_manager/policies/policy_features.cc
index 59a811b..fb9ba1d 100644
--- a/chrome/browser/performance_manager/policies/policy_features.cc
+++ b/chrome/browser/performance_manager/policies/policy_features.cc
@@ -8,8 +8,9 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/allocator/buildflags.h"
 #endif
 
@@ -22,7 +23,7 @@
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_WIN)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 const base::Feature kTrimOnMemoryPressure{"TrimOnMemoryPressure",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
@@ -116,7 +117,7 @@
     &kDynamicTcmallocTuning, "DynamicTcmallocScaleInvisibleTimeSec", -1};
 #endif  // BUILDFLAG(USE_TCMALLOC)
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !defined(OS_ANDROID)
 const base::Feature kPageFreezingFromPerformanceManager{
@@ -124,7 +125,7 @@
 
 const base::Feature kUrgentDiscardingFromPerformanceManager{
   "UrgentDiscardingFromPerformanceManager",
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       base::FEATURE_DISABLED_BY_DEFAULT
 #else
       base::FEATURE_ENABLED_BY_DEFAULT
diff --git a/chrome/browser/performance_manager/policies/policy_features.h b/chrome/browser/performance_manager/policies/policy_features.h
index 8cc7cd8..32a46f4 100644
--- a/chrome/browser/performance_manager/policies/policy_features.h
+++ b/chrome/browser/performance_manager/policies/policy_features.h
@@ -6,8 +6,9 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/allocator/buildflags.h"
 #endif
 
@@ -22,7 +23,7 @@
 extern const base::Feature kEmptyWorkingSet;
 #endif  // defined(OS_WIN)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 // The trim on Memory Pressure feature will trim a process nodes working set
 // according to the parameters below.
@@ -112,7 +113,7 @@
 extern const base::FeatureParam<int> kDynamicTuningScaleInvisibleTimeSec;
 #endif  // BUILDFLAG(USE_TCMALLOC)
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !defined(OS_ANDROID)
 // Enables freezing pages directly from PerformanceManager rather than via
diff --git a/chrome/browser/performance_manager/policies/working_set_trimmer_policy.cc b/chrome/browser/performance_manager/policies/working_set_trimmer_policy.cc
index 9f90c04..2298661 100644
--- a/chrome/browser/performance_manager/policies/working_set_trimmer_policy.cc
+++ b/chrome/browser/performance_manager/policies/working_set_trimmer_policy.cc
@@ -10,6 +10,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
 #include "components/performance_manager/graph/graph_impl.h"
 #include "components/performance_manager/graph/process_node_impl.h"
@@ -19,7 +20,7 @@
 #include "components/performance_manager/public/graph/process_node.h"
 #if defined(OS_WIN)
 #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy_win.h"
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy_chromeos.h"
 #endif
 
@@ -121,7 +122,7 @@
 bool WorkingSetTrimmerPolicy::PlatformSupportsWorkingSetTrim() {
 #if defined(OS_WIN)
   return WorkingSetTrimmerPolicyWin::PlatformSupportsWorkingSetTrim();
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return WorkingSetTrimmerPolicyChromeOS::PlatformSupportsWorkingSetTrim();
 #else
   return false;
@@ -133,7 +134,7 @@
 WorkingSetTrimmerPolicy::CreatePolicyForPlatform() {
 #if defined(OS_WIN)
   return std::make_unique<WorkingSetTrimmerPolicyWin>();
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return std::make_unique<WorkingSetTrimmerPolicyChromeOS>();
 #else
   NOTIMPLEMENTED() << "Platform does not support WorkingSetTrim.";
diff --git a/chrome/browser/persisted_state_db/persisted_state_db.cc b/chrome/browser/persisted_state_db/persisted_state_db.cc
index 14b0386..9b24216 100644
--- a/chrome/browser/persisted_state_db/persisted_state_db.cc
+++ b/chrome/browser/persisted_state_db/persisted_state_db.cc
@@ -119,9 +119,11 @@
 }
 
 PersistedStateDB::PersistedStateDB(
+    content::BrowserContext* browser_context,
     leveldb_proto::ProtoDatabaseProvider* proto_database_provider,
     const base::FilePath& profile_directory)
-    : database_status_(base::nullopt),
+    : browser_context_(browser_context),
+      database_status_(base::nullopt),
       storage_database_(
           proto_database_provider
               ->GetDB<persisted_state_db::PersistedStateContentProto>(
@@ -246,7 +248,7 @@
 }
 
 void PersistedStateDB::Destroy(JNIEnv* env) {
-  delete this;
+  PersistedStateDBFactory::GetInstance()->Disassociate(browser_context_);
 }
 
 static void JNI_LevelDBPersistedTabDataStorage_Init(
diff --git a/chrome/browser/persisted_state_db/persisted_state_db.h b/chrome/browser/persisted_state_db/persisted_state_db.h
index e2ed4bcb..dc85c0d6 100644
--- a/chrome/browser/persisted_state_db/persisted_state_db.h
+++ b/chrome/browser/persisted_state_db/persisted_state_db.h
@@ -27,6 +27,10 @@
 class ProtoDatabaseProvider;
 }  // namespace leveldb_proto
 
+namespace content {
+class BrowserContext;
+}  // namespace content
+
 class PersistedStateDBFactory;
 class PersistedStateDBFactoryTest;
 class PersistedStateDBTest;
@@ -103,6 +107,7 @@
 
   // Initializes the database
   PersistedStateDB(
+      content::BrowserContext* browser_context,
       leveldb_proto::ProtoDatabaseProvider* proto_database_provider,
       const base::FilePath& profile_directory);
 
@@ -131,6 +136,9 @@
   // Returns true if the database failed to initialize
   bool FailedToInit() const;
 
+  // Browser context associated with the PersistedStateDB
+  content::BrowserContext* browser_context_;
+
   // Status of the database initialization.
   base::Optional<leveldb_proto::Enums::InitStatus> database_status_;
 
diff --git a/chrome/browser/persisted_state_db/persisted_state_db_factory.cc b/chrome/browser/persisted_state_db/persisted_state_db_factory.cc
index 838e06a..85974c9 100644
--- a/chrome/browser/persisted_state_db/persisted_state_db_factory.cc
+++ b/chrome/browser/persisted_state_db/persisted_state_db_factory.cc
@@ -45,5 +45,6 @@
           ->GetProtoDatabaseProvider();
   base::FilePath tab_state_db_dir(
       context->GetPath().AppendASCII(kPersistedStateDBFolder));
-  return new PersistedStateDB(proto_database_provider, tab_state_db_dir);
+  return new PersistedStateDB(context, proto_database_provider,
+                              tab_state_db_dir);
 }
diff --git a/chrome/browser/persisted_state_db/persisted_state_db_factory.h b/chrome/browser/persisted_state_db/persisted_state_db_factory.h
index 72fcc32..6381b7b54 100644
--- a/chrome/browser/persisted_state_db/persisted_state_db_factory.h
+++ b/chrome/browser/persisted_state_db/persisted_state_db_factory.h
@@ -21,6 +21,11 @@
   // Acquire PersistedStateDB - there is one per profile.
   static PersistedStateDB* GetForProfile(content::BrowserContext* context);
 
+  // Call the parent Disassocaite which is a protected method
+  void Disassociate(content::BrowserContext* context) {
+    BrowserContextKeyedServiceFactory::Disassociate(context);
+  }
+
  private:
   friend struct base::DefaultSingletonTraits<PersistedStateDBFactory>;
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 8c4da83d..fd694ae 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -9,6 +9,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/accessibility/accessibility_labels_service.h"
 #include "chrome/browser/accessibility/accessibility_ui.h"
@@ -171,7 +172,7 @@
 #include "extensions/browser/api/audio/audio_api.h"
 #include "extensions/browser/api/runtime/runtime_api.h"
 #include "extensions/browser/extension_prefs.h"
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/device_name_store.h"
 #include "chrome/browser/chromeos/extensions/extensions_permissions_tracker.h"
 #include "chrome/browser/chromeos/guest_os/guest_os_share_path.h"
@@ -182,7 +183,7 @@
 #include "chrome/browser/chromeos/policy/system_proxy_manager.h"
 #include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
 #include "chrome/browser/component_updater/metadata_table_chromeos.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
@@ -242,7 +243,7 @@
 #include "components/ntp_tiles/custom_links_manager_impl.h"
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/ash_prefs.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
@@ -379,12 +380,14 @@
 #include "components/os_crypt/os_crypt.h"
 #endif
 
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 #include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/device_identity//device_oauth2_token_store_desktop.h"
 #include "chrome/browser/downgrade/downgrade_prefs.h"
 #include "chrome/browser/ui/startup/default_browser_prompt.h"
@@ -409,11 +412,11 @@
 const char kDataReductionNetworkProperties[] =
     "data_reduction.network_properties";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Deprecated 10/2019
 const char kDisplayRotationAcceleratorDialogHasBeenAccepted[] =
     "settings.a11y.display_rotation_accelerator_dialog_has_been_accepted";
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Deprecated 11/2019
 const char kBlacklistedCredentialsNormalized[] =
@@ -433,13 +436,13 @@
 const char kInvalidatorInvalidationState[] = "invalidator.invalidation_state";
 const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Deprecated 4/2020
 const char kAmbientModeTopicSource[] = "settings.ambient_mode.topic_source";
 
 // Deprecated 4/2020
 const char kPrintingAllowedPageSizes[] = "printing.allowed_page_sizes";
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Deprecated 4/2020
 const char kExcludedSchemes[] = "protocol_handler.excluded_schemes";
@@ -450,10 +453,10 @@
 const char kPreviewsLPROriginProbeCache[] =
     "Availability.Prober.cache.LitepagesOriginCheck";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Deprecated 4/2020
 const char kSupervisedUsersNextId[] = "LocallyManagedUsersNextId";
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Deprecated 6/2020
 const char kStricterMixedContentTreatmentEnabled[] =
@@ -503,9 +506,9 @@
   registry->RegisterStringPref(kInvalidatorInvalidationState, std::string());
   registry->RegisterStringPref(kInvalidatorClientId, std::string());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterIntegerPref(kSupervisedUsersNextId, 0);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // Register prefs used only for migration (clearing or moving to a new key).
@@ -517,10 +520,10 @@
       kDataReductionProxySavingsClearedNegativeSystemClock, 0);
   registry->RegisterDictionaryPref(kDataReductionNetworkProperties);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterBooleanPref(
       kDisplayRotationAcceleratorDialogHasBeenAccepted, false);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   registry->RegisterBooleanPref(kBlacklistedCredentialsNormalized, false);
 
@@ -534,10 +537,10 @@
 
   chrome_browser_net::secure_dns::RegisterProbesSettingBackupPref(registry);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterIntegerPref(kAmbientModeTopicSource, 0);
   registry->RegisterListPref(kPrintingAllowedPageSizes);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   registry->RegisterDictionaryPref(kExcludedSchemes);
   registry->RegisterDictionaryPref(kPreviewsLPRHostBlacklist);
@@ -662,7 +665,7 @@
   UpgradeDetector::RegisterPrefs(registry);
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   arc::prefs::RegisterLocalStatePrefs(registry);
   ChromeOSMetricsProvider::RegisterPrefs(registry);
   chromeos::ArcKioskAppManager::RegisterPrefs(registry);
@@ -735,7 +738,7 @@
   quirks::QuirksManager::RegisterPrefs(registry);
   UpgradeDetectorChromeos::RegisterPrefs(registry);
   RegisterNearbySharingLocalPrefs(registry);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
   confirm_quit::RegisterLocalState(registry);
@@ -759,7 +762,7 @@
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #endif  // defined(OS_WIN)
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   RegisterDefaultBrowserPromptPrefs(registry);
   downgrade::RegisterPrefs(registry);
   DeviceOAuth2TokenStoreDesktop::RegisterPrefs(registry);
@@ -936,7 +939,7 @@
   UnifiedAutoplayConfig::RegisterProfilePrefs(registry);
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   app_list::AppListSyncableService::RegisterProfilePrefs(registry);
   app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry);
   arc::prefs::RegisterProfilePrefs(registry);
@@ -1004,7 +1007,7 @@
   ::onc::RegisterProfilePrefs(registry);
   chromeos::cert_provisioning::RegisterProfilePrefs(registry);
   borealis::prefs::RegisterProfilePrefs(registry);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
   component_updater::RegisterProfilePrefsForSwReporter(registry);
@@ -1014,12 +1017,14 @@
   safe_browsing::PostCleanupSettingsResetter::RegisterProfilePrefs(registry);
 #endif
 
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   browser_switcher::BrowserSwitcherPrefs::RegisterProfilePrefs(registry);
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   default_apps::RegisterProfilePrefs(registry);
 #endif
 
@@ -1047,7 +1052,7 @@
 #if defined(OS_ANDROID)
   ::android::RegisterUserProfilePrefs(registry);
 #endif
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::RegisterUserProfilePrefs(registry);
 #endif
 }
@@ -1056,7 +1061,7 @@
   registry->RegisterBooleanPref(prefs::kDisableScreenshots, false);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void RegisterSigninProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
   RegisterProfilePrefs(registry, g_browser_process->GetApplicationLocale());
   ash::RegisterSigninProfilePrefs(registry);
@@ -1079,10 +1084,10 @@
   local_state->ClearPref(kInvalidatorInvalidationState);
   local_state->ClearPref(kInvalidatorClientId);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Added 4/2020.
   local_state->ClearPref(kSupervisedUsersNextId);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // This method should be periodically pruned of year+ old migrations.
@@ -1102,10 +1107,10 @@
   profile_prefs->ClearPref(
       kDataReductionProxySavingsClearedNegativeSystemClock);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Added 10/2019.
   profile_prefs->ClearPref(kDisplayRotationAcceleratorDialogHasBeenAccepted);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Added 11/2019.
   profile_prefs->ClearPref(kBlacklistedCredentialsNormalized);
@@ -1125,7 +1130,7 @@
   chrome_browser_net::secure_dns::MigrateProbesSettingToOrFromBackup(
       profile_prefs);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Added 4/2020.
   profile_prefs->ClearPref(kAmbientModeTopicSource);
 
diff --git a/chrome/browser/prefs/browser_prefs.h b/chrome/browser/prefs/browser_prefs.h
index bff02b1..815c2997 100644
--- a/chrome/browser/prefs/browser_prefs.h
+++ b/chrome/browser/prefs/browser_prefs.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -31,7 +32,7 @@
 void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
                               const std::string& locale);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Register all prefs that will be used via a PrefService attached to the
 // sign-in profile using the locale of |g_browser_process|.
 void RegisterSigninProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
index a3ad13a..57086c3 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_split.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/browser_sync/browser_sync_switches.h"
@@ -35,7 +36,7 @@
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/display_switches.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -51,7 +52,7 @@
         {switches::kAuthAndroidNegotiateAccountType,
          prefs::kAuthAndroidNegotiateAccountType},
 #endif
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         {switches::kSchedulerConfiguration, prefs::kSchedulerConfiguration},
 #endif
 };
@@ -75,7 +76,7 @@
         {switches::kDisablePrintPreview, prefs::kPrintPreviewDisabled, true},
         {safe_browsing::switches::kSbEnableEnhancedProtection,
          prefs::kSafeBrowsingEnhanced, true},
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         {chromeos::switches::kEnableTouchpadThreeFingerClick,
          prefs::kEnableTouchpadThreeFingerClick, true},
         {switches::kEnableUnifiedDesktop,
@@ -85,7 +86,7 @@
 #endif
         {switches::kEnableLocalSyncBackend,
          syncer::prefs::kEnableLocalSyncBackend, true},
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
         {switches::kUseSystemDefaultPrinter,
          prefs::kPrintPreviewUseSystemDefaultPrinter, true},
 #endif
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index dc0f221..a2f062d 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -21,6 +21,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/prefs/chrome_command_line_pref_store.h"
@@ -452,7 +453,7 @@
                             PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
 
   if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
     // an example problem that this can cause.
     // Do some diagnosis and try to avoid losing data.
diff --git a/chrome/browser/prefs/chrome_pref_service_unittest.cc b/chrome/browser/prefs/chrome_pref_service_unittest.cc
index 7bd596f..aca8d26 100644
--- a/chrome/browser/prefs/chrome_pref_service_unittest.cc
+++ b/chrome/browser/prefs/chrome_pref_service_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/chrome_command_line_pref_store.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -91,7 +92,7 @@
   // These should still be the default values.
 #if defined(OS_MAC)
   const char kDefaultFont[] = "Times";
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   const char kDefaultFont[] = "Tinos";
 #else
   const char kDefaultFont[] = "Times New Roman";
diff --git a/chrome/browser/prefs/pref_service_browsertest.cc b/chrome/browser/prefs/pref_service_browsertest.cc
index fde487ef..8336af0 100644
--- a/chrome/browser/prefs/pref_service_browsertest.cc
+++ b/chrome/browser/prefs/pref_service_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/browser_window_state.h"
@@ -33,7 +34,7 @@
 
 // Fails on Chrome OS as the browser thinks it is restarting after a crash, see
 // http://crbug.com/168044
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_Test DISABLED_Test
 #else
 #define MAYBE_Test Test
diff --git a/chrome/browser/prefs/pref_service_incognito_allowlist.cc b/chrome/browser/prefs/pref_service_incognito_allowlist.cc
index 653e6f0..9369459 100644
--- a/chrome/browser/prefs/pref_service_incognito_allowlist.cc
+++ b/chrome/browser/prefs/pref_service_incognito_allowlist.cc
@@ -8,6 +8,7 @@
 
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/pref_names.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -20,16 +21,16 @@
 #include "chrome/browser/accessibility/animation_policy_prefs.h"
 #endif  // !defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/ash_pref_names.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
 // List of keys that can be changed in the user prefs file by the incognito
 // profile.
 const char* const kPersistentPrefNames[] = {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // Accessibility preferences should be persisted if they are changed in
     // incognito mode.
     ash::prefs::kAccessibilityLargeCursorEnabled,
@@ -69,7 +70,7 @@
     ash::prefs::kHighContrastAcceleratorDialogHasBeenAccepted,
     ash::prefs::kScreenMagnifierAcceleratorDialogHasBeenAccepted,
     ash::prefs::kShouldAlwaysShowAccessibilityMenu,
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #if !defined(OS_ANDROID)
     kAnimationPolicyAllowed,
     kAnimationPolicyOnce,
@@ -133,7 +134,9 @@
     prefs::kShowFullscreenToolbar,
 #endif
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
     // Toggleing custom frames affects all open windows in the profile, hence
     // should be written to the regular profile when changed in incognito mode.
     prefs::kUseCustomChromeFrame,
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc
index ce8e80a..059a33db 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/common/chrome_constants.h"
 #include "components/prefs/json_pref_store.h"
@@ -39,7 +40,7 @@
 // Preference tracking and protection is not required on platforms where other
 // apps do not have access to chrome's persistent storage.
 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking =
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
     false;
 #else
     true;
diff --git a/chrome/browser/prefs/proxy_policy_unittest.cc b/chrome/browser/prefs/proxy_policy_unittest.cc
index c13af2d..b327038f 100644
--- a/chrome/browser/prefs/proxy_policy_unittest.cc
+++ b/chrome/browser/prefs/proxy_policy_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/prefs/browser_prefs.h"
@@ -29,7 +30,7 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/tpm/stub_install_attributes.h"
 #endif
 
@@ -129,7 +130,7 @@
   MockConfigurationPolicyProvider provider_;
   std::unique_ptr<PolicyServiceImpl> policy_service_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedStubInstallAttributes test_install_attributes_;
 #endif
 };
diff --git a/chrome/browser/prefs/session_startup_pref.cc b/chrome/browser/prefs/session_startup_pref.cc
index 941442b..4e6a83b 100644
--- a/chrome/browser/prefs/session_startup_pref.cc
+++ b/chrome/browser/prefs/session_startup_pref.cc
@@ -58,7 +58,7 @@
 
 // static
 SessionStartupPref::Type SessionStartupPref::GetDefaultStartupType() {
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   return SessionStartupPref::LAST;
 #else
   return SessionStartupPref::DEFAULT;
diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
index 97b0e9e..bec2e23f 100644
--- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
+++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -21,6 +21,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/profile_pref_store_manager.h"
@@ -41,7 +42,7 @@
 #include "extensions/common/extension.h"
 #include "services/preferences/public/cpp/tracked/tracked_preference_histogram_names.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -144,7 +145,7 @@
   return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
     const base::FilePath& pref_file) {
   JSONFileValueDeserializer deserializer(pref_file);
@@ -205,7 +206,7 @@
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     extensions::ExtensionBrowserTest::SetUpCommandLine(command_line);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     command_line->AppendSwitch(
         chromeos::switches::kIgnoreUserProfileMappingForTests);
 #endif
@@ -217,7 +218,7 @@
     if (content::IsPreTest())
       return extensions::ExtensionBrowserTest::SetUpUserDataDirectory();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // For some reason, the Preferences file does not exist in the location
     // below on Chrome OS. Since protection is disabled on Chrome OS, it's okay
     // to simply not attack preferences at all (and still assert that no
@@ -788,7 +789,7 @@
 
 // TODO(gab): This doesn't work on OS_CHROMEOS because we fail to attack
 // Preferences.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // Explicitly verify the result of reported resets.
     EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 0U : 2U,
               profile()
@@ -1232,7 +1233,7 @@
 
     if (protection_level_ < PROTECTION_ENABLED_DSE) {
 // This doesn't work on OS_CHROMEOS because we fail to attack Preferences.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
       // Attack is successful.
       EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
       EXPECT_EQ(current_dse->keyword(), base::UTF8ToUTF16("badkeyword"));
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index e302d7b..b07bc3b 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -293,6 +293,12 @@
   return true;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+bool OffTheRecordProfileImpl::IsMainProfile() const {
+  return false;
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 const Profile::OTRProfileID& OffTheRecordProfileImpl::GetOTRProfileID() const {
   return otr_profile_id_;
 }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 4e2b731..c297116 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -103,6 +103,9 @@
   scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
   bool IsOffTheRecord() override;
   bool IsOffTheRecord() const override;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  bool IsMainProfile() const override;
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   const OTRProfileID& GetOTRProfileID() const override;
   content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
   content::ResourceContext* GetResourceContext() override;
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index f1b5fee..648d716 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -439,11 +439,13 @@
   virtual bool IsSystemProfile() const;
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // TODO(https://crbug.com/1129543): Implement this method.
-  // In Lacros, there is exactly one profile associated with the currently
-  // logged in user on ChromeOS.
-  bool IsMainProfile() const { return false; }
-#endif
+  // Returns `true` if this is the first/initial Profile in Lacros, and - for
+  // regular sessions, if this Profile has the Device Account logged in.
+  // For non-regular sessions (Guest Sessions, Managed Guest Sessions) which do
+  // not have the concept of a Device Account, the latter condition is not
+  // checked.
+  virtual bool IsMainProfile() const = 0;
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
   bool CanUseDiskWhenOffTheRecord() override;
 
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 80e2346..1fea7cf 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -84,6 +84,15 @@
 #include "extensions/common/value_builder.h"
 #endif
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile_attributes_entry.h"
+#include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/lacros/lacros_chrome_service_impl.h"
+#include "components/account_id/account_id.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 namespace {
 
 // A helper class which creates a SimpleURLLoader with an expected final status
@@ -969,3 +978,158 @@
 }
 
 #endif  // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
+                       IsMainProfileReturnsFalseForNonDefaultPaths) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  {
+    base::FilePath profile_path = temp_dir.GetPath().Append("1Default");
+    std::unique_ptr<Profile> profile(
+        CreateProfile(profile_path, /* delegate= */ nullptr,
+                      Profile::CREATE_MODE_SYNCHRONOUS));
+
+    EXPECT_FALSE(profile->IsMainProfile());
+
+    // Creating a profile causes an implicit connection attempt to a Mojo
+    // service, which occurs as part of a new task. Before deleting |profile|,
+    // ensure this task runs to prevent a crash.
+    FlushIoTaskRunnerAndSpinThreads();
+  }
+  FlushIoTaskRunnerAndSpinThreads();
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
+                       IsMainProfileReturnsTrueForPublicSessions) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  {
+    base::FilePath profile_path =
+        temp_dir.GetPath().Append(chrome::kInitialProfile);
+    std::unique_ptr<Profile> profile(
+        CreateProfile(profile_path, /* delegate= */ nullptr,
+                      Profile::CREATE_MODE_SYNCHRONOUS));
+
+    crosapi::mojom::LacrosInitParamsPtr init_params =
+        crosapi::mojom::LacrosInitParams::New();
+    init_params->session_type = crosapi::mojom::SessionType::kPublicSession;
+    chromeos::LacrosChromeServiceImpl::Get()->SetInitParamsForTests(
+        std::move(init_params));
+
+    EXPECT_TRUE(profile->IsMainProfile());
+
+    // Creating a profile causes an implicit connection attempt to a Mojo
+    // service, which occurs as part of a new task. Before deleting |profile|,
+    // ensure this task runs to prevent a crash.
+    FlushIoTaskRunnerAndSpinThreads();
+  }
+  FlushIoTaskRunnerAndSpinThreads();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    ProfileBrowserTest,
+    IsMainProfileReturnsTrueForActiveDirectoryEnrolledDevices) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  {
+    base::FilePath profile_path =
+        temp_dir.GetPath().Append(chrome::kInitialProfile);
+    std::unique_ptr<Profile> profile(
+        CreateProfile(profile_path, /* delegate= */ nullptr,
+                      Profile::CREATE_MODE_SYNCHRONOUS));
+
+    crosapi::mojom::LacrosInitParamsPtr init_params =
+        crosapi::mojom::LacrosInitParams::New();
+    init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
+    init_params->device_mode =
+        crosapi::mojom::DeviceMode::kEnterpriseActiveDirectory;
+    chromeos::LacrosChromeServiceImpl::Get()->SetInitParamsForTests(
+        std::move(init_params));
+
+    EXPECT_TRUE(profile->IsMainProfile());
+
+    // Creating a profile causes an implicit connection attempt to a Mojo
+    // service, which occurs as part of a new task. Before deleting |profile|,
+    // ensure this task runs to prevent a crash.
+    FlushIoTaskRunnerAndSpinThreads();
+  }
+  FlushIoTaskRunnerAndSpinThreads();
+}
+
+// TODO(sinhak): Remove this test after launching go/cros-dent-1-lacros.
+IN_PROC_BROWSER_TEST_F(
+    ProfileBrowserTest,
+    IsMainProfileReturnsTrueForMainProfileInRegularSessions) {
+  // Setup.
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  const std::string kFakePrimaryUsername = "user@example.com";
+  const std::string kFakeGaiaId = "fake-gaia-id";
+  ProfileAttributesStorage& profile_attributes_storage =
+      g_browser_process->profile_manager()->GetProfileAttributesStorage();
+  const base::FilePath profile_path =
+      browser()->profile()->GetPath().DirName().Append(chrome::kInitialProfile);
+  // Creates a new Profile and (fake) signs in `kFakeGaiaId`.
+  profile_attributes_storage.AddProfile(
+      profile_path, base::UTF8ToUTF16(chrome::kInitialProfile), kFakeGaiaId,
+      base::UTF8ToUTF16(kFakePrimaryUsername),
+      /*is_consented_primary_account=*/false, /*icon_index=*/0,
+      /*supervised_user_id*/ std::string(), EmptyAccountId());
+
+  crosapi::mojom::LacrosInitParamsPtr init_params =
+      crosapi::mojom::LacrosInitParams::New();
+  init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
+  init_params->device_mode = crosapi::mojom::DeviceMode::kConsumer;
+  init_params->device_account_gaia_id = kFakeGaiaId;
+  chromeos::LacrosChromeServiceImpl::Get()->SetInitParamsForTests(
+      std::move(init_params));
+
+  // Test.
+  Profile* profile =
+      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
+  EXPECT_TRUE(profile->IsMainProfile());
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
+                       IsMainProfileReturnsTrueForOTRProfileInRegularSessions) {
+  // Setup.
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  const std::string kFakePrimaryUsername = "user@example.com";
+  const std::string kFakeGaiaId = "fake-gaia-id";
+  ProfileAttributesStorage& profile_attributes_storage =
+      g_browser_process->profile_manager()->GetProfileAttributesStorage();
+  const base::FilePath profile_path =
+      browser()->profile()->GetPath().DirName().Append(chrome::kInitialProfile);
+  // Creates a new Profile and (fake) signs in `kFakeGaiaId`.
+  profile_attributes_storage.AddProfile(
+      profile_path, base::UTF8ToUTF16(chrome::kInitialProfile), kFakeGaiaId,
+      base::UTF8ToUTF16(kFakePrimaryUsername),
+      /*is_consented_primary_account=*/false, /*icon_index=*/0,
+      /*supervised_user_id*/ std::string(), EmptyAccountId());
+
+  crosapi::mojom::LacrosInitParamsPtr init_params =
+      crosapi::mojom::LacrosInitParams::New();
+  init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
+  init_params->device_mode = crosapi::mojom::DeviceMode::kConsumer;
+  init_params->device_account_gaia_id = kFakeGaiaId;
+  chromeos::LacrosChromeServiceImpl::Get()->SetInitParamsForTests(
+      std::move(init_params));
+
+  // Test.
+  Profile* profile =
+      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
+  EXPECT_FALSE(profile->GetPrimaryOTRProfile()->IsMainProfile());
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index e3685799..b121e9e 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -229,6 +229,14 @@
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
 #endif
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile_attributes_entry.h"
+#include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chromeos/lacros/lacros_chrome_service_impl.h"
+#endif
+
 using base::TimeDelta;
 using bookmarks::BookmarkModel;
 using content::BrowserThread;
@@ -322,6 +330,42 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+bool IsDeviceAccountSignedIn(const Profile* const profile) {
+  const crosapi::mojom::LacrosInitParams* const init_params =
+      chromeos::LacrosChromeServiceImpl::Get()->init_params();
+  // We will need to check for the presence of the Device Account in a few lines
+  // below but for Guest and Managed Guest Sessions, "Device Account" is
+  // meaningless. Hence, we don't need any further checks. Early exit here.
+  if (init_params->session_type == crosapi::mojom::SessionType::kGuestSession ||
+      init_params->session_type ==
+          crosapi::mojom::SessionType::kPublicSession) {
+    return true;
+  }
+
+  if (init_params->device_mode != crosapi::mojom::DeviceMode::kConsumer &&
+      init_params->device_mode != crosapi::mojom::DeviceMode::kEnterprise) {
+    return true;
+  }
+
+  // Ash did not send any value, not even an empty string. This can only happen
+  // if we have an old version of Ash. Early exit.
+  if (!init_params->device_account_gaia_id.has_value())
+    return true;
+
+  // Profile must have the Device Account signed in. This is a temporary check
+  // until this is guaranteed via go/cros-dent-1-lacros.
+  ProfileAttributesStorage& profile_attributes_storage =
+      g_browser_process->profile_manager()->GetProfileAttributesStorage();
+  ProfileAttributesEntry* entry = nullptr;
+  if (!profile_attributes_storage.GetProfileAttributesWithPath(
+          profile->GetPath(), &entry)) {
+    return false;
+  }
+  return entry->GetGAIAId() == init_params->device_account_gaia_id;
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 }  // namespace
 
 // static
@@ -877,6 +921,25 @@
   return false;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+bool ProfileImpl::IsMainProfile() const {
+  // Profile must be at "Default" path.
+  if (GetPath().BaseName().value() != chrome::kInitialProfile)
+    return false;
+
+  // Until go/cros-dent-1-lacros is launched, the user could have signed into
+  // `this` Lacros Profile with a different account than the "Device Account"
+  // used to sign into Ash. We need to return `false` in this case in spite of
+  // the fact that this may mean that Lacros does not have _any_ Main Profile.
+  // This is acceptable because the check for `IsMainProfile` is done by
+  // sensitive services like Policy and Certs and we do not want to expose the
+  // Device Account's certs to non-Device Accounts (Think of the case when the
+  // Device Account has sensitive Enterprise SSL client certs).
+  // TODO(sinhak): Remove this after launching go/cros-dent-1-lacros.
+  return IsDeviceAccountSignedIn(this);
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 const Profile::OTRProfileID& ProfileImpl::GetOTRProfileID() const {
   NOTREACHED();
   static base::NoDestructor<OTRProfileID> otr_profile_id(
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 4049c08f..6afd9ec 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -118,6 +118,9 @@
   base::Time GetCreationTime() const override;
   bool IsOffTheRecord() override;
   bool IsOffTheRecord() const override;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  bool IsMainProfile() const override;
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   const OTRProfileID& GetOTRProfileID() const override;
   base::FilePath GetPath() const override;
   Profile* GetOffTheRecordProfile(const OTRProfileID& otr_profile_id) override;
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 2041dffa..2f5ed4b1 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -139,14 +139,6 @@
       base::BindOnce(&GetTPMInfoForUserOnUIThread, account_id, username_hash));
 }
 
-bool IsTPMTokenEnabledForNSS() {
-#if !defined(TPM_FALLBACK)
-  return crypto::IsTPMTokenEnabledForNSS();
-#else
-  return false;
-#endif
-}
-
 void StartNSSInitOnIOThread(const AccountId& account_id,
                             const std::string& username_hash,
                             const base::FilePath& path) {
@@ -165,7 +157,7 @@
 
   crypto::WillInitializeTPMForChromeOSUser(username_hash);
 
-  if (IsTPMTokenEnabledForNSS()) {
+  if (crypto::IsTPMTokenEnabledForNSS()) {
     if (crypto::IsTPMTokenReady(
             base::BindOnce(&StartTPMSlotInitializationOnIOThread, account_id,
                            username_hash))) {
diff --git a/chrome/browser/renderer_context_menu/accessibility_labels_menu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/accessibility_labels_menu_observer_browsertest.cc
index 9d128f4..76f6de97 100644
--- a/chrome/browser/renderer_context_menu/accessibility_labels_menu_observer_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/accessibility_labels_menu_observer_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h"
 #include "chrome/common/pref_names.h"
@@ -16,11 +17,11 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #else
 #include "content/public/browser/browser_accessibility_state.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -87,14 +88,14 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityLabelsMenuObserverTest,
                        AccessibilityLabelsShowWithScreenReaderEnabled) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Enable Chromevox.
   chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(true);
 #else
   // Spoof a screen reader.
   content::BrowserAccessibilityState::GetInstance()->AddAccessibilityModeFlags(
       ui::AXMode::kScreenReader);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   menu()->GetPrefs()->SetBoolean(prefs::kAccessibilityImageLabelsEnabled,
                                  false);
   InitMenu();
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc
index 3f3370c..8a97968 100644
--- a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc
+++ b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/url_constants.h"
 #include "components/renderer_context_menu/context_menu_content_type.h"
 #include "content/public/browser/web_contents.h"
@@ -25,14 +26,14 @@
 #include "extensions/common/extension.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/session_manager/core/session_manager.h"
 #endif
 
 namespace {
 
 bool IsUserSessionBlocked() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (session_manager::SessionManager::Get() &&
       session_manager::SessionManager::Get()->IsUserSessionBlocked()) {
     return true;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index d0578f71..0ceb21c5 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -25,6 +25,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -210,7 +211,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/clipboard_history_controller.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/intent_helper/open_with_menu.h"
@@ -511,7 +512,7 @@
 
 bool g_custom_id_ranges_initialized = false;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void AddAvatarToLastMenuItem(const gfx::Image& icon,
                              ui::SimpleMenuModel* menu) {
   // Don't try to scale too small icons.
@@ -526,7 +527,7 @@
   menu->SetIcon(menu->GetItemCount() - 1,
                 ui::ImageModel::FromImage(sized_icon));
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 void OnProfileCreated(const GURL& link_url,
                       const content::Referrer& referrer,
@@ -885,12 +886,12 @@
   }
 
   bool supports_smart_text_selection = false;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   supports_smart_text_selection =
       content_type_->SupportsGroup(
           ContextMenuContentType::ITEM_GROUP_SMART_SELECTION) &&
       arc::IsArcPlayStoreEnabledForProfile(GetProfile());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   if (supports_smart_text_selection)
     AppendSmartSelectionActionItems();
 
@@ -1175,7 +1176,7 @@
     // time.
     // TODO(jochen): Consider adding support for ChromeOS with similar
     // semantics as the profile switcher in the system tray.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // g_browser_process->profile_manager() is null during unit tests.
     if (g_browser_process->profile_manager() &&
         GetProfile()->IsRegularProfile()) {
@@ -1230,7 +1231,7 @@
         }
       }
     }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
 
@@ -1296,7 +1297,7 @@
 }
 
 void RenderViewContextMenu::AppendOpenWithLinkItems() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   open_with_menu_observer_ =
       std::make_unique<arc::OpenWithMenu>(browser_context_, this);
   observers_.AddObserver(open_with_menu_observer_.get());
@@ -1305,7 +1306,7 @@
 }
 
 void RenderViewContextMenu::AppendQuickAnswersItems() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!quick_answers_menu_observer_) {
     quick_answers_menu_observer_ =
         std::make_unique<QuickAnswersMenuObserver>(this);
@@ -1317,7 +1318,7 @@
 }
 
 void RenderViewContextMenu::AppendSmartSelectionActionItems() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   start_smart_selection_action_menu_observer_ =
       std::make_unique<arc::StartSmartSelectionActionMenu>(this);
   observers_.AddObserver(start_smart_selection_action_menu_observer_.get());
@@ -1720,7 +1721,7 @@
                                     IDS_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE);
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chromeos::features::IsClipboardHistoryEnabled()) {
     menu_model_.AddItemWithStringId(
         IDC_CONTENT_CLIPBOARD_HISTORY_MENU,
@@ -2116,7 +2117,7 @@
       return true;
 
     case IDC_CONTENT_CLIPBOARD_HISTORY_MENU:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       if (chromeos::features::IsClipboardHistoryEnabled())
         return ash::ClipboardHistoryController::Get()->CanShowMenu();
 #else
@@ -2458,7 +2459,7 @@
     }
 
     case IDC_CONTENT_CLIPBOARD_HISTORY_MENU: {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       // Calculate the anchor point in screen coordinates.
       gfx::Point anchor_point_in_screen =
           GetRenderFrameHost()->GetNativeView()->GetBoundsInScreen().origin();
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index ebe6e6b0..9e8a0b5 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -13,6 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
@@ -279,7 +280,7 @@
       spelling_options_submenu_observer_;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // An observer that handles "Open with <app>" items.
   std::unique_ptr<RenderViewContextMenuObserver> open_with_menu_observer_;
   // An observer that handles smart text selection action items.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index d0bfa08..44244787 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -22,6 +22,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/browser_process.h"
@@ -101,7 +102,7 @@
 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/ui/base/window_pin_type.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "ui/aura/window.h"
@@ -433,7 +434,7 @@
 
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest,
                        ContextMenuEntriesAreDisabledInLockedFullscreen) {
   int entries_to_test[] = {
@@ -456,7 +457,7 @@
   for (auto entry : entries_to_test)
     EXPECT_FALSE(menu->IsCommandIdEnabled(entry));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenEntryPresentForNormalURLs) {
   std::unique_ptr<TestRenderViewContextMenu> menu =
@@ -695,7 +696,7 @@
 }
 
 // Only Chrome OS supports emoji panel callbacks.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest,
                        ContextMenuForEmojiPanel_NoCallback) {
   // Reset the emoji callback.
@@ -712,7 +713,7 @@
   // If there's no callback, the emoji context menu should not be present.
   EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, CopyLinkTextMouse) {
   std::unique_ptr<TestRenderViewContextMenu> menu = CreateContextMenu(
@@ -1137,7 +1138,7 @@
 }
 
 // Functionality is not present on ChromeOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenLinkInProfileEntryPresent) {
   {
     std::unique_ptr<TestRenderViewContextMenu> menu(
@@ -1282,7 +1283,7 @@
     EXPECT_EQ(profile, Profile::FromBrowserContext(tab->GetBrowserContext()));
   }
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Maintains image search test state. In particular, note that |menu_observer_|
 // must live until the right-click completes asynchronously.
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
index bfb74cb..2a9498a 100644
--- a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/no_destructor.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 #include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
@@ -814,7 +815,7 @@
 
 // Tests TabManager.Backgrounded.ForegroundedOrClosed UKM logging.
 // Flaky on ChromeOS. http://crbug.com/924864
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_SingleTab DISABLED_SingleTab
 #else
 #define MAYBE_SingleTab SingleTab
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index d2ef810..40029d5 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/process/process_metrics.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
@@ -347,7 +348,7 @@
 // Fix for urgent discarding woes in crbug.com/883071. These protections only
 // apply on non-ChromeOS desktop platforms (Linux, Mac, Win).
 // NOTE: These do not currently provide DecisionDetails!
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (reason == LifecycleUnitDiscardReason::URGENT) {
     // Limit urgent discarding to once only, unless discarding for the
     // enterprise memory limit feature.
@@ -369,14 +370,14 @@
   // whether the tab can be discarded. Additional reasons can be added for
   // reporting purposes, but do not affect whether the tab can be discarded.
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
     decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
 #else
   // Do not discard the tab if it is currently active in its window.
   if (tab_strip_model_->GetActiveWebContents() == web_contents())
     decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Do not discard tabs in which the user has entered text in a form.
 
@@ -496,7 +497,7 @@
   bool fast_shutdown_success =
       GetRenderProcessHost()->FastShutdownIfPossible(1u, false);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!fast_shutdown_success &&
       discard_reason == LifecycleUnitDiscardReason::URGENT) {
     content::RenderFrameHost* main_frame = old_contents->GetMainFrame();
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index c432974..27b7e58 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
@@ -263,7 +264,7 @@
   ExpectCanDiscardFalseTrivialAllReasons(&tab_lifecycle_unit);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(TabLifecycleUnitTest, CannotDiscardActive) {
   TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
                                       usage_clock_.get(), web_contents_,
@@ -314,7 +315,7 @@
   GetTabLifecycleUnitSource()->SetMemoryLimitEnterprisePolicyFlag(true);
   ExpectCanDiscardTrue(&tab_lifecycle_unit, LifecycleUnitDiscardReason::URGENT);
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(TabLifecycleUnitTest, CannotDiscardInvalidURL) {
   content::WebContents* web_contents = AddNewHiddenWebContentsToTabStrip();
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc
index b679c64..e756db7 100644
--- a/chrome/browser/resource_coordinator/tab_manager.cc
+++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -28,6 +28,7 @@
 #include "base/threading/thread.h"
 #include "base/trace_event/traced_value.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
@@ -68,7 +69,7 @@
 #include "content/public/common/content_features.h"
 #include "net/base/network_change_notifier.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h"
 #endif
 
@@ -143,7 +144,7 @@
       background_tab_loading_mode_(BackgroundTabLoadingMode::kStaggered),
       loading_slots_(kNumOfLoadingSlots),
       tab_load_tracker_(tab_load_tracker) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   delegate_.reset(new TabManagerDelegate(weak_ptr_factory_.GetWeakPtr()));
 #endif
   browser_tab_strip_tracker_.Init();
@@ -160,13 +161,13 @@
 void TabManager::Start() {
   background_tab_loading_mode_ = BackgroundTabLoadingMode::kStaggered;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   delegate_->StartPeriodicOOMScoreUpdate();
 #endif
 
 // MemoryPressureMonitor is not implemented on Linux so far and tabs are never
 // discarded.
-#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
   // Don't handle memory pressure events here if this is done by
   // PerformanceManager.
   if (!base::FeatureList::IsEnabled(
@@ -222,12 +223,12 @@
 
 void TabManager::DiscardTab(LifecycleUnitDiscardReason reason,
                             TabDiscardDoneCB tab_discard_done) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Call Chrome OS specific low memory handling process.
   delegate_->LowMemoryKill(reason, std::move(tab_discard_done));
 #else
   DiscardTabImpl(reason, std::move(tab_discard_done));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 WebContents* TabManager::DiscardTabByExtension(content::WebContents* contents) {
@@ -249,7 +250,7 @@
   DCHECK(!base::FeatureList::IsEnabled(
       performance_manager::features::kUrgentDiscardingFromPerformanceManager));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Output a log with per-process memory usage and number of file descriptors,
   // as well as GPU memory details. Discard happens without waiting for the log
   // (https://crbug.com/850545) Per comment at
@@ -258,7 +259,7 @@
   // platforms since it is not used and data shows it can create IO thread hangs
   // (https://crbug.com/1040522).
   memory::OomMemoryDetails::Log("Tab Discards Memory details");
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Start handling memory pressure. Suppress further notifications before
   // completion in case a slow handler queues up multiple dispatches of this
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h
index 51da563..44ef457 100644
--- a/chrome/browser/resource_coordinator/tab_manager.h
+++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -19,6 +19,7 @@
 #include "base/strings/string16.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h"
@@ -45,7 +46,7 @@
 
 class BackgroundTabNavigationThrottle;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class TabManagerDelegate;
 #endif
 class TabManagerStatsCollector;
@@ -342,7 +343,7 @@
   // A listener to global memory pressure events.
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<TabManagerDelegate> delegate_;
 #endif
 
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
index c0b9387..2371ce8 100644
--- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "base/util/memory_pressure/fake_memory_pressure_monitor.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_window_testing.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
@@ -470,7 +471,7 @@
       tab_manager()->DiscardTabImpl(LifecycleUnitDiscardReason::EXTERNAL));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Makes sure that recently opened or used tabs are protected.
 IN_PROC_BROWSER_TEST_F(TabManagerTest,
                        ProtectRecentlyUsedTabsFromUrgentDiscarding) {
@@ -517,7 +518,7 @@
   // WebContentsData::WebContentsDestroyed.
   tsm->CloseAllTabs();
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Makes sure that tabs using media devices are protected.
 IN_PROC_BROWSER_TEST_F(TabManagerTest, ProtectVideoTabs) {
@@ -674,11 +675,11 @@
   base::HistogramTester tester;
   EXPECT_TRUE(
       tab_manager()->DiscardTabImpl(LifecycleUnitDiscardReason::URGENT));
-#ifdef OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // The unsafe killing attempt will fail for the same reason.
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldUnsafeFastShutdown", false, 1);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldFastShutdown", false, 1);
 }
@@ -696,16 +697,16 @@
   // one of them is current, and the other has an unload handler. An unsafe
   // attempt will be made on some platforms.
   base::HistogramTester tester;
-#ifdef OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // The unsafe attempt for ChromeOS should succeed as ChromeOS ignores unload
   // handlers when in critical condition.
   content::WindowedNotificationObserver observer(
       content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
       content::NotificationService::AllSources());
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_TRUE(
       tab_manager()->DiscardTabImpl(LifecycleUnitDiscardReason::URGENT));
-#ifdef OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldUnsafeFastShutdown", true, 1);
   tester.ExpectUniqueSample(
@@ -714,7 +715,7 @@
 #else
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldFastShutdown", false, 1);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 IN_PROC_BROWSER_TEST_F(TabManagerTest,
@@ -733,12 +734,12 @@
   base::HistogramTester tester;
   EXPECT_TRUE(
       tab_manager()->DiscardTabImpl(LifecycleUnitDiscardReason::URGENT));
-#ifdef OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // The unsafe killing attempt will fail as ChromeOS does not ignore
   // beforeunload handlers.
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldUnsafeFastShutdown", false, 1);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   tester.ExpectUniqueSample(
       "TabManager.Discarding.DiscardedTabCouldFastShutdown", false, 1);
 }
@@ -981,7 +982,7 @@
 
 // On ChromeOS, active tabs are discarded if their window is non-visible. On
 // other platforms, they are never discarded.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_TRUE(
       IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
 #else
@@ -1027,7 +1028,7 @@
 
 // On ChromeOS, active tabs are discarded if their window is non-visible. On
 // other platforms, they are never discarded.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_TRUE(
       IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
 #else
@@ -1191,4 +1192,4 @@
 
 }  // namespace resource_coordinator
 
-#endif  // OS_WIN || OS_MAXOSX || OS_LINUX || defined(OS_CHROMEOS)
+#endif  // OS_WIN || OS_MAXOSX || OS_LINUX || BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
index e02bad5b..aca2529c5 100644
--- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "chrome/browser/profiles/profile.h"
@@ -290,7 +291,7 @@
   EXPECT_TRUE(TabManager::IsInternalPage(GURL(chrome::kChromeUISettingsURL)));
 
 // Debugging URLs are not included.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(TabManager::IsInternalPage(GURL(chrome::kChromeUIDiscardsURL)));
 #endif
   EXPECT_FALSE(
@@ -355,7 +356,7 @@
   EXPECT_TRUE(IsTabDiscarded(tab_strip1->GetWebContentsAt(1)));
   EXPECT_TRUE(IsTabDiscarded(tab_strip2->GetWebContentsAt(1)));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, a non-visible tab should be discarded even if it's active in
   // its tab strip.
   EXPECT_TRUE(IsTabDiscarded(tab_strip2->GetWebContentsAt(0)));
@@ -363,7 +364,7 @@
   // On other platforms, an active tab is never discarded, even if it's not
   // visible.
   EXPECT_FALSE(IsTabDiscarded(tab_strip2->GetWebContentsAt(0)));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Tabs with a committed URL must be closed explicitly to avoid DCHECK errors.
   tab_strip1->CloseAllTabs();
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
index cd27b1d7..0bda6fa 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/signin/public/identity_manager/accounts_mutator.h"
@@ -282,7 +283,7 @@
   aps_manager.UnsubscribeFromSigninEvents();
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Not applicable to Chrome OS.
 TEST_F(AdvancedProtectionStatusManagerTest, SignInAndSignOutEvent) {
   AdvancedProtectionStatusManager aps_manager(
@@ -394,7 +395,7 @@
 
 // On ChromeOS, there is no unconsented primary account. We can only track the
 // primary account.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(AdvancedProtectionStatusManagerTest, TracksUnconsentedPrimaryAccount) {
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index 2dfae53..4dcf33a 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/bind.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
@@ -34,7 +35,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/tpm/stub_install_attributes.h"
 #endif
 
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
index fd7e1179..b372e58 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
@@ -15,6 +15,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
 #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
@@ -323,7 +324,7 @@
   if (reason != REASON_DOWNLOAD_UNCOMMON)
     return false;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return false;
 #else
   Profile* profile = Profile::FromBrowserContext(GetBrowserContext());
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
index d5b0b4b..160b9ce60 100644
--- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/install_signer.h"
 #include "chrome/browser/extensions/test_extension_system.h"
@@ -34,7 +35,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #endif
@@ -135,13 +136,13 @@
     profile_manager_.reset(
         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     ASSERT_TRUE(profile_manager_->SetUp());
-#if defined OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     test_user_manager_.reset(new chromeos::ScopedTestUserManager());
 #endif
   }
 
   void TearDown() override {
-#if defined OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // UserManager should be destroyed before TestingBrowserProcess as it
     // uses it in destructor.
     test_user_manager_.reset();
@@ -189,7 +190,7 @@
  private:
   int profile_number_;
 
-#if defined OS_CHROMEOS
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
   std::unique_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
 #endif
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 4ed8193..285cb1f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -40,6 +40,7 @@
 #include "base/time/time.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -102,7 +103,7 @@
 #include "url/gurl.h"
 #include "url/url_canon.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chromeos/constants/chromeos_switches.h"
 #endif
@@ -529,7 +530,7 @@
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     command_line->AppendSwitch(
         chromeos::switches::kIgnoreUserProfileMappingForTests);
 #endif
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc
index 2c72e86..e4c08741 100644
--- a/chrome/browser/sessions/better_session_restore_browsertest.cc
+++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/test/bind.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/background/background_mode_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -564,7 +565,7 @@
 #endif  // BUILDFLAG(ENABLE_BACKGROUND_MODE)
 // ChromeOS does not override the SessionStartupPreference upon controlled
 // system restart.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 class RestartTest : public BetterSessionRestoreTest {
  public:
   RestartTest() { }
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index f1eb2592..68e4c36 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -29,6 +29,7 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
@@ -70,7 +71,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension_set.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/boot_times_recorder.h"
 #endif
 
@@ -313,7 +314,7 @@
       BrowserList::RemoveObserver(this);
     }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker("SessionRestore-End",
                                                            false);
 #endif
@@ -323,7 +324,7 @@
   void OnGotSession(
       std::vector<std::unique_ptr<sessions::SessionWindow>> windows,
       SessionID active_window_id) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
         "SessionRestore-GotSession", false);
 #endif
@@ -364,7 +365,7 @@
       return FinishedTabCreation(false, false, created_contents);
     }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
         "SessionRestore-CreatingTabs-Start", false);
 #endif
@@ -400,7 +401,7 @@
         // The first set of tabs is added to the existing browser.
         browser = browser_;
       } else {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
             "SessionRestore-CreateRestoredBrowser-Start", false);
 #endif
@@ -414,7 +415,7 @@
         browser = CreateRestoredBrowser(
             BrowserTypeForWindowType((*i)->type), (*i)->bounds, (*i)->workspace,
             show_state, (*i)->app_name, (*i)->user_title);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
             "SessionRestore-CreateRestoredBrowser-End", false);
 #endif
@@ -478,7 +479,7 @@
 
     if (last_normal_browser && !urls_to_open_.empty())
       AppendURLsToBrowser(last_normal_browser, urls_to_open_);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
         "SessionRestore-CreatingTabs-End", false);
 #endif
@@ -641,7 +642,7 @@
     params.initial_bounds = bounds;
     params.user_title = user_title;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // We only store trusted app windows, so we also create them as trusted.
     if (type == Browser::Type::TYPE_APP) {
       params = Browser::CreateParams::CreateForApp(
@@ -759,7 +760,7 @@
     Profile* profile, Browser* browser,
     SessionRestore::BehaviorBitmask behavior,
     const std::vector<GURL>& urls_to_open) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
       "SessionRestore-Start", false);
 #endif
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 0c3fc53..dfc4747 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -104,7 +104,7 @@
   ~SessionRestoreTest() override = default;
 
  protected:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void SetUpCommandLine(base::CommandLine* command_line) override {
     // TODO(nkostylev): Investigate if we can remove this switch.
     command_line->AppendSwitch(switches::kCreateBrowserOnStartupForTests);
@@ -116,7 +116,7 @@
 
     SessionStartupPref pref(SessionStartupPref::LAST);
     SessionStartupPref::SetStartupPref(browser()->profile(), pref);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     const testing::TestInfo* const test_info =
         testing::UnitTest::GetInstance()->current_test_info();
     if (strcmp(test_info->name(), "NoSessionRestoreNewWindowChromeOS") != 0) {
@@ -237,7 +237,7 @@
     }
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   Profile* CreateSecondaryProfile(int profile_num) {
     base::ScopedAllowBlockingForTesting allow_blocking;
     ProfileManager* profile_manager = g_browser_process->profile_manager();
@@ -249,7 +249,7 @@
     SessionStartupPref::SetStartupPref(profile, pref);
     return profile;
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   GURL url1_;
   GURL url2_;
@@ -496,7 +496,7 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Verify that session restore does not occur when a user opens a browser window
 // when no other browser windows are open on ChromeOS.
 // TODO(pkotwicz): Add test which doesn't open incognito browser once
@@ -552,7 +552,7 @@
   EXPECT_TRUE(app_browser->window()->IsMaximized());
   EXPECT_TRUE(app_browser->is_type_app());
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Creates a tabbed browser and popup and makes sure we restore both.
 IN_PROC_BROWSER_TEST_F(SessionRestoreTest, NormalAndPopup) {
@@ -700,7 +700,7 @@
   EXPECT_EQ(0U, service->entries().size());
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // This test does not apply to ChromeOS as ChromeOS does not do session
 // restore when a new window is open.
 
@@ -1888,7 +1888,7 @@
   }
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 namespace {
 
 class MultiBrowserObserver : public BrowserListObserver {
@@ -2011,11 +2011,11 @@
                .possibly_invalid_spec();
   }
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // PRE_CorrectLoadingOrder is flaky on ChromeOS MSAN and Mac.
 // See http://crbug.com/493167.
-#if (defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER)) || defined(OS_MAC)
+#if (BUILDFLAG(IS_CHROMEOS_ASH) && defined(MEMORY_SANITIZER)) || defined(OS_MAC)
 #define MAYBE_PRE_CorrectLoadingOrder DISABLED_PRE_CorrectLoadingOrder
 #define MAYBE_CorrectLoadingOrder DISABLED_CorrectLoadingOrder
 #else
diff --git a/chrome/browser/sessions/session_restore_interactive_uitest.cc b/chrome/browser/sessions/session_restore_interactive_uitest.cc
index da8763f..004b6085 100644
--- a/chrome/browser/sessions/session_restore_interactive_uitest.cc
+++ b/chrome/browser/sessions/session_restore_interactive_uitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/sessions/session_restore_test_helper.h"
 #include "chrome/browser/sessions/session_service_factory.h"
diff --git a/chrome/browser/sessions/session_restore_observer_browsertest.cc b/chrome/browser/sessions/session_restore_observer_browsertest.cc
index b1bc216..408cdcd3 100644
--- a/chrome/browser/sessions/session_restore_observer_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_observer_browsertest.cc
@@ -7,6 +7,7 @@
 
 #include "base/run_loop.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
@@ -111,7 +112,7 @@
   void SetUpOnMainThread() override {
     SessionStartupPref pref(SessionStartupPref::LAST);
     SessionStartupPref::SetStartupPref(browser()->profile(), pref);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     SessionServiceTestHelper helper(
         SessionServiceFactory::GetForProfile(browser()->profile()));
     helper.SetForceBrowserNotAliveWithNoWindows(true);
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc
index 3ccad0a..8b52c37 100644
--- a/chrome/browser/sessions/session_service.cc
+++ b/chrome/browser/sessions/session_service.cc
@@ -19,6 +19,7 @@
 #include "base/stl_util.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/background/background_mode_manager.h"
 #include "chrome/browser/browser_process.h"
@@ -55,7 +56,7 @@
 #include "content/public/browser/session_storage_namespace.h"
 #include "content/public/browser/web_contents.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
 #endif
 
@@ -117,7 +118,7 @@
   // ChromeOS and OSX have different ideas of application lifetime than
   // the other platforms.
   // On ChromeOS opening a new window should never start a new session.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!force_browser_not_alive_with_no_windows_)
     return false;
 #endif
@@ -588,7 +589,7 @@
 
 bool SessionService::ShouldRestoreWindowOfType(
     sessions::SessionWindow::WindowType window_type) const {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Restore apps and app popups for ChromeOS alone.
   if (window_type == sessions::SessionWindow::TYPE_APP ||
       window_type == sessions::SessionWindow::TYPE_APP_POPUP)
@@ -917,7 +918,7 @@
 bool SessionService::ShouldTrackBrowser(Browser* browser) const {
   if (browser->profile() != profile())
     return false;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Do not track Crostini apps or terminal.  Apps will fail since VMs are not
   // restarted on restore, and we don't want terminal to force the VM to start.
   if (crostini::CrostiniAppIdFromAppName(browser->app_name()) ||
diff --git a/chrome/browser/sessions/session_service_utils.cc b/chrome/browser/sessions/session_service_utils.cc
index 84cfa512..1fc759c 100644
--- a/chrome/browser/sessions/session_service_utils.cc
+++ b/chrome/browser/sessions/session_service_utils.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/sessions/session_service_utils.h"
 
+#include "build/chromeos_buildflags.h"
+
 sessions::SessionWindow::WindowType WindowTypeForBrowserType(
     Browser::Type type) {
   switch (type) {
@@ -17,7 +19,7 @@
       return sessions::SessionWindow::TYPE_DEVTOOLS;
     case Browser::TYPE_APP_POPUP:
       return sessions::SessionWindow::TYPE_APP_POPUP;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     case Browser::TYPE_CUSTOM_TAB:
       // Session restore isn't supported for CUSTOM_TAB browser.
       // This method must never be called for this type.
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index 56fc007..e76526e 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -11,6 +11,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -31,7 +32,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #else
 #include "chrome/browser/signin/signin_util.h"
@@ -80,7 +81,7 @@
 bool ChildAccountService::IsChildAccountDetectionEnabled() {
 // Child account detection is always enabled on Android and ChromeOS, and
 // disabled in other platforms.
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
   return true;
 #else
   return false;
@@ -178,7 +179,7 @@
     settings_service->SetLocalSetting(supervised_users::kGeolocationDisabled,
                                       std::make_unique<base::Value>(false));
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // This is also used by user policies (UserPolicySigninService), but since
     // child accounts can not also be Dasher accounts, there shouldn't be any
     // problems.
@@ -204,7 +205,7 @@
     settings_service->SetLocalSetting(supervised_users::kGeolocationDisabled,
                                       nullptr);
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     signin_util::SetUserSignoutAllowedForProfile(profile_, true);
 #endif
 
@@ -336,7 +337,7 @@
 }
 
 void ChildAccountService::PropagateChildStatusToUser(bool is_child) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   user_manager::User* user =
       chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
   if (user) {
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
index 4d2d0ba..a7cd79fe 100644
--- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/identity_manager/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
@@ -143,7 +144,7 @@
   }
 
   CoreAccountInfo SetPrimaryAccount() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     return identity_test_env_.SetUnconsentedPrimaryAccount(kAccountId);
 #elif defined(OS_ANDROID)
     // TODO(https://crbug.com/1046746): Change to SetUnconsentedPrimaryAccount()
@@ -156,7 +157,7 @@
   }
 
   void IssueRefreshToken() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     identity_test_env_.MakeUnconsentedPrimaryAccountAvailable(kAccountId);
 #elif defined(OS_ANDROID)
     identity_test_env_.MakePrimaryAccountAvailable(kAccountId);
diff --git a/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc b/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
index b174a99..4fc475e2 100644
--- a/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
+++ b/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.h"
 #include "chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client_factory.h"
 #include "chrome/browser/supervised_user/kids_chrome_management/kidschromemanagement_messages.pb.h"
@@ -24,7 +25,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #endif
@@ -99,7 +100,7 @@
     ASSERT_TRUE(test_profile_manager_->SetUp());
 
 // ChromeOS requires a chromeos::FakeChromeUserManager for the tests to work.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     const char kEmail[] = "account@gmail.com";
     const AccountId test_account_id(AccountId::FromUserEmail(kEmail));
     user_manager_ = new chromeos::FakeChromeUserManager;
@@ -147,7 +148,7 @@
   TestingProfile* test_profile_;
   std::unique_ptr<TestingProfileManager> test_profile_manager_;
   std::unique_ptr<KidsManagementURLCheckerClient> url_classifier_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::FakeChromeUserManager* user_manager_;
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
 #endif
diff --git a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
index 3e15e5d..8825a540 100644
--- a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
+++ b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
@@ -123,7 +124,7 @@
   if (authStatus == ChildAccountService::AuthState::PENDING)
     return content::NavigationThrottle::DEFER;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // A credentials re-mint is already underway when we reach here (Mirror
   // account reconciliation). Nothing to do here except block the navigation
   // while re-minting is underway.
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index f03a87c..6c42234 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -23,6 +23,7 @@
 #include "base/values.h"
 #include "base/version.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
 #include "chrome/browser/profiles/profile.h"
@@ -58,7 +59,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -215,7 +216,7 @@
 std::string SupervisedUserService::GetCustodianEmailAddress() const {
   std::string email = profile_->GetPrefs()->GetString(
       prefs::kSupervisedUserCustodianEmail);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // |GetActiveUser()| can return null in unit tests.
   if (email.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
     email = chromeos::ChromeUserManager::Get()
@@ -237,7 +238,7 @@
 std::string SupervisedUserService::GetCustodianName() const {
   std::string name = profile_->GetPrefs()->GetString(
       prefs::kSupervisedUserCustodianName);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // |GetActiveUser()| can return null in unit tests.
   if (name.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
     name = base::UTF16ToUTF8(
@@ -786,7 +787,7 @@
 SupervisedUserService::ExtensionState SupervisedUserService::GetExtensionState(
     const Extension& extension) const {
   bool was_installed_by_default = extension.was_installed_by_default();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS all external sources are controlled by us so it means that
   // they are "default". Method was_installed_by_default returns false because
   // extensions creation flags are ignored in case of default extensions with
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
index 9a8563e..51a6380 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
@@ -10,6 +10,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
+import org.chromium.base.annotations.RemovableInRelease;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.embedder_support.browser_context.BrowserContextHandle;
 
@@ -26,7 +27,6 @@
     private long mNativePersistedStateDB;
     // Callback is only used for synchronization of save and delete in testing.
     // Otherwise it is a no-op.
-    private Runnable mOnCompleteForTesting;
     // TODO(crbug.com/1146799) Apply tricks like @CheckDiscard or @RemovableInRelease to improve
     // performance
     private boolean mIsDestroyed;
@@ -49,7 +49,15 @@
     public void save(int tabId, String dataId, byte[] data) {
         makeNativeAssertion();
         LevelDBPersistedTabDataStorageJni.get().save(
-                mNativePersistedStateDB, getKey(tabId, dataId), data, mOnCompleteForTesting);
+                mNativePersistedStateDB, getKey(tabId, dataId), data, null);
+    }
+
+    @RemovableInRelease
+    @MainThread
+    public void saveForTesting(int tabId, String dataId, byte[] data, Runnable onComplete) {
+        makeNativeAssertion();
+        LevelDBPersistedTabDataStorageJni.get().save(
+                mNativePersistedStateDB, getKey(tabId, dataId), data, onComplete);
     }
 
     @MainThread
@@ -77,7 +85,15 @@
     public void delete(int tabId, String dataId) {
         makeNativeAssertion();
         LevelDBPersistedTabDataStorageJni.get().delete(
-                mNativePersistedStateDB, getKey(tabId, dataId), mOnCompleteForTesting);
+                mNativePersistedStateDB, getKey(tabId, dataId), null);
+    }
+
+    @RemovableInRelease
+    @MainThread
+    public void deleteForTesting(int tabId, String dataId, Runnable onComplete) {
+        makeNativeAssertion();
+        LevelDBPersistedTabDataStorageJni.get().delete(
+                mNativePersistedStateDB, getKey(tabId, dataId), onComplete);
     }
 
     @Override
@@ -118,11 +134,6 @@
         mNativePersistedStateDB = nativePtr;
     }
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected void setOnCompleteForTesting(Runnable onComplete) {
-        mOnCompleteForTesting = onComplete;
-    }
-
     @VisibleForTesting
     public static void setSkipNativeAssertionsForTesting(boolean skipNativeAssertionsForTesting) {
         sSkipNativeAssertionsForTesting = skipNativeAssertionsForTesting;
diff --git a/chrome/browser/task_manager/providers/worker_task_provider_browsertest.cc b/chrome/browser/task_manager/providers/worker_task_provider_browsertest.cc
index 4e86b6a..3264088 100644
--- a/chrome/browser/task_manager/providers/worker_task_provider_browsertest.cc
+++ b/chrome/browser/task_manager/providers/worker_task_provider_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_window.h"
@@ -33,7 +34,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_switches.h"
 #endif
 
@@ -142,7 +143,7 @@
 
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     command_line->AppendSwitch(
         chromeos::switches::kIgnoreUserProfileMappingForTests);
 #endif
diff --git a/chrome/browser/task_manager/sampling/task_group.cc b/chrome/browser/task_manager/sampling/task_group.cc
index 48fe9c2a7..cf04820 100644
--- a/chrome/browser/task_manager/sampling/task_group.cc
+++ b/chrome/browser/task_manager/sampling/task_group.cc
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/task_manager/sampling/shared_sampler.h"
 #include "chrome/browser/task_manager/task_manager_observer.h"
 #include "components/nacl/browser/nacl_browser.h"
@@ -92,9 +93,9 @@
       on_background_calculations_done_(on_background_calculations_done),
       worker_thread_sampler_(nullptr),
       shared_sampler_(shared_sampler),
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       arc_shared_sampler_(nullptr),
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
       expected_on_bg_done_flags_(kBackgroundRefreshTypesMask),
       current_on_bg_done_flags_(0),
       platform_independent_cpu_usage_(std::numeric_limits<double>::quiet_NaN()),
@@ -143,10 +144,10 @@
 
 TaskGroup::~TaskGroup() {
   shared_sampler_->UnregisterCallback(process_id_);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (arc_shared_sampler_)
     arc_shared_sampler_->UnregisterCallback(process_id_);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void TaskGroup::AddTask(Task* task) {
@@ -249,7 +250,7 @@
   return expected_on_bg_done_flags_ == current_on_bg_done_flags_;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void TaskGroup::SetArcSampler(ArcSharedSampler* sampler) {
   DCHECK(sampler);
   arc_shared_sampler_ = sampler;
@@ -257,7 +258,7 @@
       process_id_, base::BindRepeating(&TaskGroup::OnArcSamplerRefreshDone,
                                        weak_ptr_factory_.GetWeakPtr()));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void TaskGroup::RefreshGpuMemory(
     const gpu::VideoMemoryUsageStats& gpu_memory_stats) {
@@ -364,13 +365,13 @@
                                   shared_sampler_->GetSupportedFlags());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void TaskGroup::OnArcSamplerRefreshDone(
     base::Optional<ArcSharedSampler::MemoryFootprintBytes> memory_footprint) {
   if (memory_footprint)
     set_footprint_bytes(*memory_footprint);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void TaskGroup::OnBackgroundRefreshTypeFinished(int64_t finished_refresh_type) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/task_manager/sampling/task_group.h b/chrome/browser/task_manager/sampling/task_group.h
index 78e72968..ff98fa2 100644
--- a/chrome/browser/task_manager/sampling/task_group.h
+++ b/chrome/browser/task_manager/sampling/task_group.h
@@ -16,15 +16,16 @@
 #include "base/process/process_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/task_manager/providers/task.h"
 #include "chrome/browser/task_manager/sampling/shared_sampler.h"
 #include "chrome/browser/task_manager/sampling/task_group_sampler.h"
 #include "chrome/browser/task_manager/task_manager_observer.h"
 #include "components/nacl/common/buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/task_manager/sampling/arc_shared_sampler.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace gpu {
 struct VideoMemoryUsageStats;
@@ -79,9 +80,9 @@
   // process represented by this TaskGroup have completed.
   bool AreBackgroundCalculationsDone() const;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void SetArcSampler(ArcSharedSampler* sampler);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   const base::ProcessHandle& process_handle() const { return process_handle_; }
   const base::ProcessId& process_id() const { return process_id_; }
@@ -97,7 +98,7 @@
   base::TimeDelta cpu_time() const { return cpu_time_; }
   void set_footprint_bytes(int64_t footprint) { memory_footprint_ = footprint; }
   int64_t footprint_bytes() const { return memory_footprint_; }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   int64_t swapped_bytes() const { return swapped_mem_bytes_; }
 #endif
   int64_t gpu_memory() const { return gpu_memory_; }
@@ -150,10 +151,10 @@
   void OnSamplerRefreshDone(
       base::Optional<SharedSampler::SamplingResult> results);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnArcSamplerRefreshDone(
       base::Optional<ArcSharedSampler::MemoryFootprintBytes> results);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   void OnBackgroundRefreshTypeFinished(int64_t finished_refresh_type);
 
@@ -169,10 +170,10 @@
   scoped_refptr<TaskGroupSampler> worker_thread_sampler_;
 
   scoped_refptr<SharedSampler> shared_sampler_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Shared sampler that retrieves memory footprint for all ARC processes.
   ArcSharedSampler* arc_shared_sampler_;  // Not owned
-#endif                                    // defined(OS_CHROMEOS)
+#endif                                    // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Lists the Tasks in this TaskGroup.
   // Tasks are not owned by the TaskGroup. They're owned by the TaskProviders.
diff --git a/chrome/browser/task_manager/sampling/task_group_sampler.cc b/chrome/browser/task_manager/sampling/task_group_sampler.cc
index 0c0a8ee..de1c0b3c 100644
--- a/chrome/browser/task_manager/sampling/task_group_sampler.cc
+++ b/chrome/browser/task_manager/sampling/task_group_sampler.cc
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/process/process_metrics.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/task_manager/task_manager_observer.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/browser_thread.h"
@@ -132,9 +133,9 @@
 int64_t TaskGroupSampler::RefreshSwappedMem() {
   DCHECK(worker_pool_sequenced_checker_.CalledOnValidSequence());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return process_metrics_->GetVmSwapBytes();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   return 0;
 }
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc
index 6d7cad2..a24816b 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.cc
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -18,6 +18,7 @@
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/task_manager/providers/browser_process_task_provider.h"
 #include "chrome/browser/task_manager/providers/child_process_task_provider.h"
 #include "chrome/browser/task_manager/providers/fallback_task_provider.h"
@@ -38,12 +39,12 @@
 #include "services/network/public/cpp/features.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/arc/process/arc_process_service.h"
 #include "chrome/browser/task_manager/providers/arc/arc_process_task_provider.h"
 #include "chrome/browser/task_manager/providers/vm/vm_process_task_provider.h"
 #include "components/arc/arc_util.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace task_manager {
 
@@ -101,12 +102,12 @@
       std::move(primary_subproviders),
       std::make_unique<RenderProcessHostTaskProvider>()));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (arc::IsArcAvailable())
     task_providers_.push_back(std::make_unique<ArcProcessTaskProvider>());
   task_providers_.push_back(std::make_unique<VmProcessTaskProvider>());
   arc_shared_sampler_ = std::make_unique<ArcSharedSampler>();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 TaskManagerImpl::~TaskManagerImpl() {
@@ -158,7 +159,7 @@
 }
 
 int64_t TaskManagerImpl::GetSwappedMemoryUsage(TaskId task_id) const {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return GetTaskGroupByTaskId(task_id)->swapped_bytes();
 #else
   return -1;
@@ -481,7 +482,7 @@
                                    is_running_in_vm,
                                    on_background_data_ready_callback_,
                                    shared_sampler_, blocking_pool_runner_));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (task->GetType() == Task::ARC)
       task_group->SetArcSampler(arc_shared_sampler_.get());
 #endif
@@ -627,12 +628,12 @@
                                enabled_resources_flags());
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (TaskManagerObserver::IsResourceRefreshEnabled(
           REFRESH_TYPE_MEMORY_FOOTPRINT, enabled_resources_flags())) {
     arc_shared_sampler_->Refresh();
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   NotifyObserversOnRefresh(GetTaskIdsList());
 }
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.h b/chrome/browser/task_manager/sampling/task_manager_impl.h
index 4a329559..12c1fb28 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.h
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.h
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/task_manager/providers/task_provider.h"
 #include "chrome/browser/task_manager/providers/task_provider_observer.h"
 #include "chrome/browser/task_manager/sampling/task_group.h"
@@ -26,9 +27,9 @@
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/task_manager/sampling/arc_shared_sampler.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace task_manager {
 
@@ -212,11 +213,11 @@
   // subset of resources for all processes at once.
   scoped_refptr<SharedSampler> shared_sampler_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // A sampler shared with all instances of TaskGroup that hold ARC tasks and
   // calculates memory footprint for all processes at once.
   std::unique_ptr<ArcSharedSampler> arc_shared_sampler_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // This will be set to true while there are observers and the task manager is
   // running.
diff --git a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
index bf9aa56..1fba4ad 100644
--- a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
+++ b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
@@ -88,11 +88,15 @@
 
 void MultiProfileBrowserStatusMonitor::ConnectV1AppToLauncher(
     Browser* browser) {
+  content::WebContents* web_contents =
+      browser->tab_strip_model()->GetActiveWebContents();
+  if (!web_contents)
+    return;
+
   // Adding a V1 app to the launcher consists of two actions: Add the browser
   // (launcher item) and add the content (launcher item status).
   BrowserStatusMonitor::AddV1AppToShelf(browser);
-  launcher_controller_->UpdateAppState(
-      browser->tab_strip_model()->GetActiveWebContents(), false /*remove*/);
+  launcher_controller_->UpdateAppState(web_contents, false /*remove*/);
 }
 
 void MultiProfileBrowserStatusMonitor::DisconnectV1AppFromLauncher(
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc b/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc
index 15c9747..5f5d9fe 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc
@@ -517,7 +517,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(SystemWebAppManagerMultiDesktopLaunchBrowserTest,
-                       DISABLED_LaunchToActiveDesktop) {
+                       LaunchToActiveDesktop) {
   // Login two users.
   LoginUser(account_id1_);
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chrome/browser/ui/webui/discards/graph_dump_impl.h
index 4257f12..f4948cb 100644
--- a/chrome/browser/ui/webui/discards/graph_dump_impl.h
+++ b/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -117,14 +117,18 @@
       const performance_manager::PageNode* page_node,
       const performance_manager::FrameNode* previous_opener,
       OpenedType previous_opened_type) override;
+  // Ignored.
   void OnIsVisibleChanged(
-      const performance_manager::PageNode* page_node) override {}  // Ignored.
+      const performance_manager::PageNode* page_node) override {}
+  // Ignored.
   void OnIsAudibleChanged(
-      const performance_manager::PageNode* page_node) override {}  // Ignored.
+      const performance_manager::PageNode* page_node) override {}
+  // Ignored.
   void OnIsLoadingChanged(
-      const performance_manager::PageNode* page_node) override {}  // Ignored.
+      const performance_manager::PageNode* page_node) override {}
+  // Ignored.
   void OnUkmSourceIdChanged(
-      const performance_manager::PageNode* page_node) override {}  // Ignored.
+      const performance_manager::PageNode* page_node) override {}
   // Ignored.
   void OnPageLifecycleStateChanged(
       const performance_manager::PageNode* page_node) override {}
@@ -139,12 +143,17 @@
   // Ignored.
   void OnMainFrameDocumentChanged(
       const performance_manager::PageNode* page_node) override {}
+  // Ignored.
   void OnHadFormInteractionChanged(
       const performance_manager::PageNode* page_node) override {}
+  // Ignored.
   void OnTitleUpdated(const performance_manager::PageNode* page_node) override {
-  }  // Ignored.
+  }
   void OnFaviconUpdated(
       const performance_manager::PageNode* page_node) override;
+  // Ignored.
+  void OnFreezingVoteChanged(
+      const performance_manager::PageNode* page_node) override {}
 
   // ProcessNodeObserver implementation:
   void OnProcessNodeAdded(
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 55f09a6f..e229b00 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -75,12 +75,13 @@
 
   deps = [
     ":web_app_group",
-    "//chrome/browser:browser_process",
     "//build:chromeos_buildflags",
+    "//chrome/browser:browser_process",
     "//chrome/browser/web_applications/components",
     "//chrome/browser/web_applications/preinstalled_web_apps",
     "//chrome/common",
     "//components/content_settings/core/browser",
+    "//components/device_event_log",
     "//components/keyed_service/content",
     "//components/performance_manager",
     "//components/pref_registry",
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index 38ba6ff..09f68ce 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -33,6 +33,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/device_event_log/device_event_log.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
@@ -131,6 +132,10 @@
         OriginTrialsMap({{GetOrigin("chrome://camera-app"),
                           {"FileHandling", "NativeFileSystem2"}}});
     infos.at(SystemAppType::CAMERA).capture_navigations = true;
+
+    // TODO(b/172343409): Remove this log when the camera app is fully migrated
+    // to SWA.
+    CAMERA_LOG(EVENT) << "Install the camera app as SWA";
   }
 
   if (SystemWebAppManager::IsAppEnabled(SystemAppType::DIAGNOSTICS)) {
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 3e9e892..a7756c46 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1606391943-c49ce66f4f03ab73428a9c9ccbc70b089767b5c2.profdata
+chrome-linux-master-1606434328-b11de2c42e4be1904f18040e42ebddef022e94a9.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index d5b80cf3..6deb4a5 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1606391943-6f31c76b4f9e93d1de26d5f38d730905e1d3f7a7.profdata
+chrome-mac-master-1606434328-d20b89cbb7113eb50f7c91d68d6760cac88c7639.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 1b89595..4a409ad 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1606359294-a78100f1c02315e3a2df0ee09ef21dd127ea538b.profdata
+chrome-win32-master-1606423711-20b7d89425d1187d62c0bed2d0c51ba670083d7c.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index f88a255..b008469a 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1606380888-a2312ebb2792a371a28e16249fe53f8f1a9dbcea.profdata
+chrome-win64-master-1606445966-4a9759f3f64c32ba89411261d898a8870ebcc34b.profdata
diff --git a/chrome/installer/mac/third_party/xz/BUILD.gn b/chrome/installer/mac/third_party/xz/BUILD.gn
index f1d0ac1..5024b8265 100644
--- a/chrome/installer/mac/third_party/xz/BUILD.gn
+++ b/chrome/installer/mac/third_party/xz/BUILD.gn
@@ -29,7 +29,7 @@
   defines = [ "HAVE_CONFIG_H" ]
 
   include_dirs = [
-    "config/$host_os",
+    "config/$current_os",
     "xz/src/common",
     "xz/src/liblzma/api",
     "xz/src/liblzma/check",
@@ -387,7 +387,7 @@
   deps = [ ":lzma" ]
 
   include_dirs = [
-    "config/$host_os",
+    "config/$current_os",
     "xz/src/common",
   ]
 }
@@ -413,7 +413,7 @@
   deps = [ ":lzma_decompress" ]
 
   include_dirs = [
-    "config/$host_os",
+    "config/$current_os",
     "xz/src/common",
   ]
 
diff --git a/chrome/renderer/autofill/autofill_renderer_browsertest.cc b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
index 49d6c8fc..1f85383 100644
--- a/chrome/renderer/autofill/autofill_renderer_browsertest.cc
+++ b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
@@ -70,8 +70,7 @@
   void SetFormToBeProbablySubmitted(
       const base::Optional<FormData>& form) override {}
 
-  void FormsSeen(const std::vector<FormData>& forms,
-                 base::TimeTicks timestamp) override {
+  void FormsSeen(const std::vector<FormData>& forms) override {
     // FormsSeen() could be called multiple times and sometimes even with empty
     // forms array for main frame, but we're interested in only the first time
     // call.
diff --git a/chrome/renderer/autofill/form_autocomplete_browsertest.cc b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
index e3ab82f..b3896231 100644
--- a/chrome/renderer/autofill/form_autocomplete_browsertest.cc
+++ b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
@@ -69,8 +69,7 @@
   void SetFormToBeProbablySubmitted(
       const base::Optional<FormData>& form) override {}
 
-  void FormsSeen(const std::vector<FormData>& forms,
-                 base::TimeTicks timestamp) override {}
+  void FormsSeen(const std::vector<FormData>& forms) override {}
 
   void FormSubmitted(const FormData& form,
                      bool known_success,
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 455f6d31..7b0bbf5f 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -632,6 +632,12 @@
   return original_profile_;
 }
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+bool TestingProfile::IsMainProfile() const {
+  return false;
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 const Profile::OTRProfileID& TestingProfile::GetOTRProfileID() const {
   DCHECK(IsOffTheRecord());
   return *otr_profile_id_;
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 1b4ca2d..c9dab3fe 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -295,6 +295,9 @@
   // profile dynamically.
   bool IsOffTheRecord() final;
   bool IsOffTheRecord() const final;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  bool IsMainProfile() const override;
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   const OTRProfileID& GetOTRProfileID() const override;
   content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
   content::ResourceContext* GetResourceContext() override;
diff --git a/chromeos/components/camera_app_ui/resources.h b/chromeos/components/camera_app_ui/resources.h
index ffd80afb..22df1c0 100644
--- a/chromeos/components/camera_app_ui/resources.h
+++ b/chromeos/components/camera_app_ui/resources.h
@@ -58,6 +58,7 @@
     {"expert_preview_metadata", IDS_EXPERT_PREVIEW_METADATA},
     {"expert_save_metadata", IDS_EXPERT_SAVE_METADATA},
     {"expert_print_performance_logs", IDS_EXPERT_PRINT_PERFORMANCE_LOGS},
+    {"expert_scan_barcode", IDS_EXPERT_SCAN_BARCODE},
     {"error_msg_expert_mode_not_supported",
      IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED},
     {"feedback_button", IDS_FEEDBACK_BUTTON},
diff --git a/chromeos/components/camera_app_ui/resources/.eslintrc.js b/chromeos/components/camera_app_ui/resources/.eslintrc.js
index 44b3a77..dc6938d 100644
--- a/chromeos/components/camera_app_ui/resources/.eslintrc.js
+++ b/chromeos/components/camera_app_ui/resources/.eslintrc.js
@@ -376,6 +376,7 @@
     'blink': 'readable',
     'cros': 'readable',
     'trustedTypes': 'readable',
+    'BarcodeDetector': 'readable',
     'webkitRequestFileSystem': 'readable',
   },
   // Generally, the rules should be compatible to both bundled and the newest
diff --git a/chromeos/components/camera_app_ui/resources/BUILD.gn b/chromeos/components/camera_app_ui/resources/BUILD.gn
index 8860cbd..fc5e630b 100644
--- a/chromeos/components/camera_app_ui/resources/BUILD.gn
+++ b/chromeos/components/camera_app_ui/resources/BUILD.gn
@@ -134,6 +134,7 @@
 copy("chrome_camera_app_js_models") {
   sources = [
     "js/models/async_writer.js",
+    "js/models/barcode.js",
     "js/models/chrome_file_system_entry.js",
     "js/models/file_namer.js",
     "js/models/file_system.js",
diff --git a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
index 46a3a80c..03dc3841 100644
--- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
+++ b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
@@ -18,6 +18,7 @@
       <structure name="IDR_CAMERA_ASYNC_WRITER_JS" file="js/models/async_writer.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BACKGROUND_JS" file="js/background.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BACKGROUND_OPS_JS" file="js/background_ops.js" type="chrome_html" />
+      <structure name="IDR_CAMERA_BARCODE_JS" file="js/models/barcode.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BROWSER_PROXY_INTERFACE_JS" file="js/browser_proxy/browser_proxy_interface.js" type="chrome_html" />
       <structure name="IDR_CAMERA_CAMERA3_DEVICE_INFO_JS" file="js/device/camera3_device_info.js" type="chrome_html" />
       <structure name="IDR_CAMERA_CAMERA_INTENT_JS" file="js/views/camera_intent.js" type="chrome_html" />
diff --git a/chromeos/components/camera_app_ui/resources/js/BUILD.gn b/chromeos/components/camera_app_ui/resources/js/BUILD.gn
index 197313f..a1d2bf18 100644
--- a/chromeos/components/camera_app_ui/resources/js/BUILD.gn
+++ b/chromeos/components/camera_app_ui/resources/js/BUILD.gn
@@ -72,6 +72,7 @@
     "main.js",
     "metrics.js",
     "models/async_writer.js",
+    "models/barcode.js",
     "models/chrome_file_system_entry.js",
     "models/file_namer.js",
     "models/file_system.js",
diff --git a/chromeos/components/camera_app_ui/resources/js/externs/w3c_api.js b/chromeos/components/camera_app_ui/resources/js/externs/w3c_api.js
index f5144a5..4f9f39c 100644
--- a/chromeos/components/camera_app_ui/resources/js/externs/w3c_api.js
+++ b/chromeos/components/camera_app_ui/resources/js/externs/w3c_api.js
@@ -2,15 +2,64 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(inker): Put it to the externs/browser/w3c_api.js of the upstream
-// Closure Compiler, uprev the one bundled in Chromium repo, and remove the
-// definition here.
+/* eslint-disable no-unused-vars, no-var, valid-jsdoc */
 
-/* eslint-disable valid-jsdoc */
+// TODO(b/172879638): Upstream the externs of BarcodeDetector to Closure
+// Compiler.
 
 /**
- * @see http://www.w3.org/TR/FileAPI/#arraybuffer-method-algo
- * @return {!Promise<!ArrayBuffer>}
- * @nosideeffects
+ * @typedef {HTMLImageElement|HTMLVideoElement|HTMLCanvasElement|ImageBitmap|
+ *     OffscreenCanvas}
  */
-Blob.prototype.arrayBuffer = function() {};
+var CanvasImageSource;
+
+/**
+ * @typedef {!CanvasImageSource|!Blob|!ImageData}
+ * @see https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#imagebitmapsource
+ */
+var ImageBitmapSource;
+
+/**
+ * @record
+ * @struct
+ */
+function BarcodeDetectorOptions() {}
+
+/** @type {!Array<string>} */
+BarcodeDetectorOptions.prototype.formats;
+
+/**
+ * @record
+ * @struct
+ */
+function DetectedBarcode() {}
+
+/** @type {!DOMRectReadOnly} */
+DetectedBarcode.prototype.boundingBox;
+
+/** @type {!Array<{x: number, y: number}>} */
+DetectedBarcode.prototype.cornerPoints;
+
+/** @type {string} */
+DetectedBarcode.prototype.format;
+
+/** @type {string} */
+DetectedBarcode.prototype.rawValue;
+
+/**
+ * @constructor
+ * @param {!BarcodeDetectorOptions=} barcodeDetectorOptions
+ * @see https://wicg.github.io/shape-detection-api/#barcode-detection-api
+ */
+function BarcodeDetector(barcodeDetectorOptions) {}
+
+/**
+ * @return {!Promise<!Array<string>>}
+ */
+BarcodeDetector.getSupportedFormats = function() {};
+
+/**
+ * @param {!ImageBitmapSource} image
+ * @return {!Promise<!Array<!DetectedBarcode>>}
+ */
+BarcodeDetector.prototype.detect = function(image) {};
diff --git a/chromeos/components/camera_app_ui/resources/js/models/barcode.js b/chromeos/components/camera_app_ui/resources/js/models/barcode.js
new file mode 100644
index 0000000..0b49c046f
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/js/models/barcode.js
@@ -0,0 +1,90 @@
+// 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.
+
+// TODO(b/172879638): Get some performance data and tune the scan interval.
+const SCAN_INTERVAL = 1000;
+
+/**
+ * A barcode scanner to detect barcodes from a camera stream.
+ */
+export class BarcodeScanner {
+  /**
+   * @param {!HTMLVideoElement} video The video to be scanned for barcode.
+   * @param {function(string)} callback The callback for the detected barcodes.
+   */
+  constructor(video, callback) {
+    /**
+     * @type {!HTMLVideoElement}
+     * @private
+     */
+    this.video_ = video;
+
+    /**
+     * @type {function(string)}
+     * @private
+     */
+    this.callback_ = callback;
+
+    /**
+     * @type {!BarcodeDetector}
+     * @private
+     */
+    this.detector_ = new BarcodeDetector({formats: ['qr_code']});
+
+    /**
+     * The current running interval id.
+     * @type {?number}
+     */
+    this.intervalId_ = null;
+  }
+
+  /**
+   * Starts scanning barcodes continuously. Calling this method when it's
+   * already started would be no-op.
+   */
+  start() {
+    if (this.intervalId_ !== null) {
+      return;
+    }
+    let prevCode = null;
+    // TODO(b/172879638): Add a setIntervalAsync() helper to avoid two
+    // detections running at the same time.
+    this.intervalId_ = setInterval(async () => {
+      const code = await this.scan_();
+      if (code !== null && code !== prevCode) {
+        prevCode = code;
+        this.callback_(code);
+      }
+    }, SCAN_INTERVAL);
+  }
+
+  /**
+   * Stops scanning barcodes.
+   */
+  stop() {
+    if (this.intervalId_ === null) {
+      return;
+    }
+    clearInterval(this.intervalId_);
+    this.intervalId_ = null;
+  }
+
+  /**
+   * Scans barcodes from the current frame.
+   * @return {!Promise<?string>} The detected barcode value, or null if no
+   *     barcode is detected.
+   * @private
+   */
+  async scan_() {
+    // TODO(b/172879638): Down scale the frame if the resolution is too high.
+    // TODO(b/172879638): Run this on a Web Worker.
+    const codes = await this.detector_.detect(this.video_);
+
+    if (codes.length === 0) {
+      return null;
+    }
+    // TODO(b/172879638): Handle multiple barcodes.
+    return codes[0].rawValue;
+  }
+}
diff --git a/chromeos/components/camera_app_ui/resources/js/state.js b/chromeos/components/camera_app_ui/resources/js/state.js
index d3cd86e..df95e46 100644
--- a/chromeos/components/camera_app_ui/resources/js/state.js
+++ b/chromeos/components/camera_app_ui/resources/js/state.js
@@ -46,6 +46,7 @@
   REVIEW_RESULT: 'review-result',
   REVIEW_VIDEO_RESULT: 'review-video-result',
   SAVE_METADATA: 'save-metadata',
+  SCAN_BARCODE: 'scan-barcode',
   SHOULD_HANDLE_INTENT_RESULT: 'should-handle-intent-result',
   SHOW_METADATA: 'show-metadata',
   SQUARE_PREVIEW: 'square-preview',
diff --git a/chromeos/components/camera_app_ui/resources/js/views/camera/preview.js b/chromeos/components/camera_app_ui/resources/js/views/camera/preview.js
index 49d3d49..00c988d4 100644
--- a/chromeos/components/camera_app_ui/resources/js/views/camera/preview.js
+++ b/chromeos/components/camera_app_ui/resources/js/views/camera/preview.js
@@ -4,9 +4,11 @@
 
 import {browserProxy} from '../../browser_proxy/browser_proxy.js';
 import * as dom from '../../dom.js';
+import {BarcodeScanner} from '../../models/barcode.js';
 import {DeviceOperator, parseMetadata} from '../../mojo/device_operator.js';
 import * as nav from '../../nav.js';
 import * as state from '../../state.js';
+import * as toast from '../../toast.js';
 import * as util from '../../util.js';
 import {windowController} from '../../window_controller/window_controller.js';
 
@@ -73,11 +75,21 @@
      */
     this.resizeWindowTimeout_ = null;
 
+    /**
+     * @type {?BarcodeScanner}
+     * @private
+     */
+    this.scanner_ = null;
+
+
     window.addEventListener('resize', () => this.onWindowResize_());
 
     [state.State.EXPERT, state.State.SHOW_METADATA].forEach((s) => {
       state.addObserver(s, this.updateShowMetadata_.bind(this));
     });
+    [state.State.EXPERT, state.State.SCAN_BARCODE].forEach((s) => {
+      state.addObserver(s, this.updateScanBarcode_.bind(this));
+    });
   }
 
   /**
@@ -150,7 +162,13 @@
           this.onNewStreamNeeded_();
         }
       }, 100);
+      this.scanner_ = new BarcodeScanner(this.video_, (code) => {
+        // TODO(b/172879638): Show this with a actionable toast.
+        toast.showDebugMessage(code);
+      });
+      this.updateScanBarcode_();
       this.updateShowMetadata_();
+
       state.set(state.State.STREAMING, true);
     } catch (e) {
       await this.close();
@@ -164,13 +182,13 @@
    * @return {!Promise}
    */
   async close() {
-    if (this.watchdog_) {
+    if (this.watchdog_ !== null) {
       clearInterval(this.watchdog_);
       this.watchdog_ = null;
     }
     // Pause video element to avoid black frames during transition.
     this.video_.pause();
-    if (this.stream_) {
+    if (this.stream_ !== null) {
       const track = this.stream_.getVideoTracks()[0];
       const {deviceId} = track.getSettings();
       track.stop();
@@ -180,10 +198,29 @@
       }
       this.stream_ = null;
     }
+    if (this.scanner_ !== null) {
+      this.scanner_.stop();
+      this.scanner_ = null;
+    }
     state.set(state.State.STREAMING, false);
   }
 
   /**
+   * Checks whether to scan barcode on preview or not.
+   * @private
+   */
+  updateScanBarcode_() {
+    if (this.scanner_ === null) {
+      return;
+    }
+    if (state.get(state.State.EXPERT) && state.get(state.State.SCAN_BARCODE)) {
+      this.scanner_.start();
+    } else {
+      this.scanner_.stop();
+    }
+  }
+
+  /**
    * Checks preview whether to show preview metadata or not.
    * @private
    */
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings.grd b/chromeos/components/camera_app_ui/resources/strings/camera_strings.grd
index 2758835b..63573b16f 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings.grd
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings.grd
@@ -336,6 +336,9 @@
       <message desc="Label for expert mode option: print performance logs." name="IDS_EXPERT_PRINT_PERFORMANCE_LOGS">
         Print performance logs
       </message>
+      <message desc="Label for expert mode option: scan barcode." name="IDS_EXPERT_SCAN_BARCODE">
+        Scan barcode
+      </message>
       <message desc="Error message when the device does not support expert mode but tries to enable it." name="IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED">
         Expert mode is not supported on this device
       </message>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_grd/IDS_EXPERT_SCAN_BARCODE.png.sha1 b/chromeos/components/camera_app_ui/resources/strings/camera_strings_grd/IDS_EXPERT_SCAN_BARCODE.png.sha1
new file mode 100644
index 0000000..052d3a0
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_grd/IDS_EXPERT_SCAN_BARCODE.png.sha1
@@ -0,0 +1 @@
+fd4166d2a4aa6d5118d7127d3ee638863cf0e938
\ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/views/main.html b/chromeos/components/camera_app_ui/resources/views/main.html
index aa7a0f9..0c677f6 100644
--- a/chromeos/components/camera_app_ui/resources/views/main.html
+++ b/chromeos/components/camera_app_ui/resources/views/main.html
@@ -375,6 +375,12 @@
                  data-key="printPerformanceLogs">
           <span i18n-content="expert_print_performance_logs"></span>
         </label>
+        <label class="menu-item">
+          <input class="icon" id="expert-scan-barcode" type="checkbox"
+                 tabindex="0" data-state="scan-barcode"
+                 data-key="scanBarcode">
+          <span i18n-content="expert_scan_barcode"></span>
+        </label>
       </div>
     </div>
     <div class="centered-overlay" id="spinner"></div>
diff --git a/chromeos/components/file_manager/file_manager_ui.cc b/chromeos/components/file_manager/file_manager_ui.cc
index 8091ee1..55e84db 100644
--- a/chromeos/components/file_manager/file_manager_ui.cc
+++ b/chromeos/components/file_manager/file_manager_ui.cc
@@ -58,9 +58,8 @@
 
 void FileManagerUI::BindInterface(
     mojo::PendingReceiver<mojom::PageHandlerFactory> pending_receiver) {
-  if (page_factory_receiver_.is_bound()) {
-    page_factory_receiver_.reset();
-  }
+  DCHECK(!page_factory_receiver_.is_bound());
+
   page_factory_receiver_.Bind(std::move(pending_receiver));
 }
 
diff --git a/chromeos/components/file_manager/resources/file_manager_resources.grd b/chromeos/components/file_manager/resources/file_manager_resources.grd
index 540cc73..e33d4ed8 100644
--- a/chromeos/components/file_manager/resources/file_manager_resources.grd
+++ b/chromeos/components/file_manager/resources/file_manager_resources.grd
@@ -14,19 +14,13 @@
     <includes>
       <if expr="is_official_build == false">
         <!-- Privileged app host contents. -->
+        <include name="IDR_FILE_MANAGER_SWA_MOJO_LITE_JS" file="$root_gen_dir/chromeos/components/file_manager/mojom/file_manager.mojom-lite.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_SWA_BROWSER_PROXY_JS" file="browser_proxy.js" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_SWA_SCRIPT_LOADER_JS" file="script_loader.js" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_SWA_MAIN_HTML" file="${root_gen_dir}/chromeos/components/file_manager/resources/main.html" flattenhtml="true" use_base_dir="false" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_SWA_MAIN_JS" file="main.js" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_SWA_ICON_192" file="images/icon192.png" type="BINDATA" />
-
-        <!-- Mojo resources -->
-        <include name="IDR_FILE_MANAGER_SWA_MOJO_LITE_JS"
-          file="$root_gen_dir\chromeos\components\file_manager\mojom\file_manager.mojom-lite.js"
-          use_base_dir="false"
-          type="BINDATA" />
       </if>
     </includes>
   </release>
 </grit>
-
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 59fc41a..e92e3ff1 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -453,6 +453,14 @@
 const base::Feature kMediaAppPdfInInk{"MediaAppPdfInInk",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables support for multilingual assistive typing on Chrome OS.
+const base::Feature kMultilingualTyping{"MultilingualTyping",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether to enable on-device grammar check service.
+const base::Feature kOnDeviceGrammarCheck{"OnDeviceGrammarCheck",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables a unique URL for each path in CrOS settings.
 // This allows deep linking to individual settings, i.e. in settings search.
 const base::Feature kOsSettingsDeepLinking{"OsSettingsDeepLinking",
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index b9cd168..44f8256 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -202,6 +202,10 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kMinimumChromeVersion;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kMultilingualTyping;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kOnDeviceGrammarCheck;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kOsSettingsDeepLinking;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kOsSettingsPolymer3;
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index 8b5c0667..299610ca 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -162,6 +162,8 @@
 //
 // If ash-chrome is newer than lacros-chrome, then some fields may not be
 // processed by lacros-chrome.
+//
+// Next version: 8
 [Stable]
 struct LacrosInitParams {
   // This is ash-chrome's version of the AshChromeService interface. This is
@@ -203,6 +205,13 @@
   // Added in M89.
   [MinVersion=6]
   DefaultPaths? default_paths@6;
+
+  // Device Account's obfuscated Gaia id, if present.
+  // This is null for older versions of ash, for Active Directory sessions,
+  // Guest sessions, Managed Guest sessions, Demo mode, and Kiosks.
+  // Added in M89.
+  [MinVersion=7]
+  string? device_account_gaia_id@7;
 };
 
 // LacrosChromeService defines the APIs that live in lacros-chrome and
diff --git a/chromeos/lacros/lacros_chrome_service_impl.cc b/chromeos/lacros/lacros_chrome_service_impl.cc
index 89c5c408..e32e3103 100644
--- a/chromeos/lacros/lacros_chrome_service_impl.cc
+++ b/chromeos/lacros/lacros_chrome_service_impl.cc
@@ -521,6 +521,11 @@
   return it->second;
 }
 
+void LacrosChromeServiceImpl::SetInitParamsForTests(
+    crosapi::mojom::LacrosInitParamsPtr init_params) {
+  init_params_ = std::move(init_params);
+}
+
 void LacrosChromeServiceImpl::BindScreenManagerReceiver(
     mojo::PendingReceiver<crosapi::mojom::ScreenManager> pending_receiver) {
   DCHECK(IsScreenManagerAvailable());
diff --git a/chromeos/lacros/lacros_chrome_service_impl.h b/chromeos/lacros/lacros_chrome_service_impl.h
index c7c1494..de5f71b 100644
--- a/chromeos/lacros/lacros_chrome_service_impl.h
+++ b/chromeos/lacros/lacros_chrome_service_impl.h
@@ -207,6 +207,11 @@
   // work on M87 or older should not use this.
   int GetInterfaceVersion(base::Token interface_uuid) const;
 
+  // Sets `init_params_` to the provided value.
+  // Useful for tests that cannot setup a full Lacros test environment with a
+  // working Mojo connection to Ash.
+  void SetInitParamsForTests(crosapi::mojom::LacrosInitParamsPtr init_params);
+
  private:
   // LacrosChromeServiceNeverBlockingState is an implementation detail of this
   // class.
diff --git a/components/BUILD.gn b/components/BUILD.gn
index a2b91e9..854b493 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -803,6 +803,7 @@
       "//components/media_router/browser/android:junit",
       "//components/messages/android:junit",
       "//components/messages/android/internal:junit",
+      "//components/payments/content/android:junit",
       "//components/permissions/android:components_permissions_junit_tests",
       "//components/policy/android:components_policy_junit_tests",
       "//components/prefs/android:junit",
diff --git a/components/autofill/android/provider/autofill_provider_android.cc b/components/autofill/android/provider/autofill_provider_android.cc
index 157142cd..2d7344240 100644
--- a/components/autofill/android/provider/autofill_provider_android.cc
+++ b/components/autofill/android/provider/autofill_provider_android.cc
@@ -341,8 +341,7 @@
 }
 
 void AutofillProviderAndroid::OnFormsSeen(AutofillHandlerProxy* handler,
-                                          const std::vector<FormData>& forms,
-                                          const base::TimeTicks timestamp) {}
+                                          const std::vector<FormData>& forms) {}
 
 void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/components/autofill/android/provider/autofill_provider_android.h b/components/autofill/android/provider/autofill_provider_android.h
index 618517c..cddf4f9f 100644
--- a/components/autofill/android/provider/autofill_provider_android.h
+++ b/components/autofill/android/provider/autofill_provider_android.h
@@ -66,8 +66,7 @@
                                  const FormData& form,
                                  base::TimeTicks timestamp) override;
   void OnFormsSeen(AutofillHandlerProxy* handler,
-                   const std::vector<FormData>& forms,
-                   const base::TimeTicks timestamp) override;
+                   const std::vector<FormData>& forms) override;
   void OnHidePopup(AutofillHandlerProxy* handler) override;
 
   void Reset(AutofillHandlerProxy* handler) override;
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc
index 3c37af3..f03b1475 100644
--- a/components/autofill/content/browser/content_autofill_driver.cc
+++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -219,9 +219,8 @@
   return render_frame_host_->GetIsolationInfoForSubresources();
 }
 
-void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& forms,
-                                      base::TimeTicks timestamp) {
-  autofill_handler_->OnFormsSeen(forms, timestamp);
+void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& forms) {
+  autofill_handler_->OnFormsSeen(forms);
 }
 
 void ContentAutofillDriver::SetFormToBeProbablySubmitted(
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index efa2872..61f4467d 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -107,8 +107,7 @@
   // mojom::AutofillDriver:
   void SetFormToBeProbablySubmitted(
       const base::Optional<FormData>& form) override;
-  void FormsSeen(const std::vector<FormData>& forms,
-                 base::TimeTicks timestamp) override;
+  void FormsSeen(const std::vector<FormData>& forms) override;
   void FormSubmitted(const FormData& form,
                      bool known_success,
                      mojom::SubmissionSource source) override;
diff --git a/components/autofill/content/common/mojom/autofill_driver.mojom b/components/autofill/content/common/mojom/autofill_driver.mojom
index 106f0d69..a87410e 100644
--- a/components/autofill/content/common/mojom/autofill_driver.mojom
+++ b/components/autofill/content/common/mojom/autofill_driver.mojom
@@ -22,7 +22,7 @@
 
   // Notification that forms have been seen that are candidates for
   // filling/submitting by the AutofillManager.
-  FormsSeen(array<FormData> forms, mojo_base.mojom.TimeTicks timestamp);
+  FormsSeen(array<FormData> forms);
 
   // Notification that a form has been submitted. The |known_success| indicates
   // whether the submission succeeded or not. Currently, we assume submission
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 95ff56c..1aed939 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -437,13 +437,12 @@
   if (FindFormAndFieldForFormControlElement(element_, field_data_manager_.get(),
                                             &updated_form, &field) &&
       (!element_.IsAutofilled() || !form.DynamicallySameFormAs(updated_form))) {
-    base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
     WebLocalFrame* frame = render_frame()->GetWebFrame();
     std::vector<FormData> forms;
     forms.push_back(updated_form);
     // Always communicate to browser process for topmost frame.
     if (!forms.empty() || !frame->Parent()) {
-      GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
+      GetAutofillDriver()->FormsSeen(forms);
     }
   }
 }
@@ -826,17 +825,13 @@
 }
 
 void AutofillAgent::ProcessForms() {
-  // Record timestamp of when the forms are first seen. This is used to
-  // measure the overhead of the Autofill feature.
-  base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
-
   WebLocalFrame* frame = render_frame()->GetWebFrame();
   std::vector<FormData> forms =
       form_cache_.ExtractNewForms(field_data_manager_.get());
 
   // Always communicate to browser process for topmost frame.
   if (!forms.empty() || !frame->Parent()) {
-    GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
+    GetAutofillDriver()->FormsSeen(forms);
   }
 }
 
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index ae5afd2..105d3ff 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -507,7 +507,6 @@
     "test_autofill_profile_validator.h",
     "test_autofill_profile_validator_delayed.cc",
     "test_autofill_profile_validator_delayed.h",
-    "test_autofill_provider.cc",
     "test_autofill_provider.h",
     "test_autofill_tick_clock.cc",
     "test_autofill_tick_clock.h",
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc
index 419e5cd..abfd223 100644
--- a/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -1946,7 +1946,7 @@
 
   AutofillDownloadManager download_manager(driver_.get(), this);
   FormStructure form_structure(form);
-  form_structure.set_original_page_language(LanguageCode("fr"));
+  form_structure.set_current_page_language(LanguageCode("fr"));
 
   pref_service_->SetBoolean(
       RandomizedEncoder::kUrlKeyedAnonymizedDataCollectionEnabled, true);
@@ -1984,7 +1984,7 @@
     ASSERT_TRUE(request.has_upload());
     const AutofillUploadContents& upload = request.upload();
     EXPECT_EQ(upload.language(),
-              form_structure.original_page_language().value());
+              form_structure.current_page_language().value());
     ASSERT_TRUE(upload.has_randomized_form_metadata());
     EXPECT_TRUE(upload.randomized_form_metadata().has_id());
     EXPECT_TRUE(upload.randomized_form_metadata().has_name());
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc
index 914fb25..58dbf5bd 100644
--- a/components/autofill/core/browser/autofill_handler.cc
+++ b/components/autofill/core/browser/autofill_handler.cc
@@ -45,7 +45,7 @@
 bool CachedFormNeedsUpdate(const FormData& live_form,
                            const LanguageCode& live_form_language,
                            const FormStructure& cached_form) {
-  if (cached_form.original_page_language() != live_form_language)
+  if (cached_form.current_page_language() != live_form_language)
     return true;
 
   if (live_form.fields.size() != cached_form.field_count())
@@ -76,14 +76,13 @@
     OnFormSubmittedImpl(form, known_success, source);
 }
 
-void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms,
-                                  const base::TimeTicks timestamp) {
+void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms) {
   if (!IsValidFormDataVector(forms) || !driver_->RendererIsAvailable())
     return;
 
   // This should be called even forms is empty, AutofillProviderAndroid uses
   // this event to detect form submission.
-  if (!ShouldParseForms(forms, timestamp))
+  if (!ShouldParseForms(forms))
     return;
 
   if (forms.empty())
@@ -131,7 +130,7 @@
 
   if (new_forms.empty())
     return;
-  OnFormsParsed(new_forms, timestamp);
+  OnFormsParsed(new_forms);
 }
 
 void AutofillHandler::OnTextFieldDidChange(const FormData& form,
@@ -294,7 +293,7 @@
       value_from_dynamic_change_form_ = true;
   }
 
-  form_structure->set_original_page_language(GetPageLanguage());
+  form_structure->set_current_page_language(GetPageLanguage());
 
   form_structure->DetermineHeuristicTypes(log_manager_);
 
diff --git a/components/autofill/core/browser/autofill_handler.h b/components/autofill/core/browser/autofill_handler.h
index c9ac660..874daab 100644
--- a/components/autofill/core/browser/autofill_handler.h
+++ b/components/autofill/core/browser/autofill_handler.h
@@ -88,8 +88,7 @@
                        mojom::SubmissionSource source);
 
   // Invoked when |forms| has been detected.
-  void OnFormsSeen(const std::vector<FormData>& forms,
-                   const base::TimeTicks timestamp);
+  void OnFormsSeen(const std::vector<FormData>& forms);
 
   // Invoked when focus is no longer on form. |had_interacted_form| indicates
   // whether focus was previously on a form with which the user had interacted.
@@ -191,12 +190,10 @@
 
   // Return whether the |forms| from OnFormSeen() should be parsed to
   // form_structures.
-  virtual bool ShouldParseForms(const std::vector<FormData>& forms,
-                                const base::TimeTicks timestamp) = 0;
+  virtual bool ShouldParseForms(const std::vector<FormData>& forms) = 0;
 
   // Invoked when forms from OnFormsSeen() has been parsed to |form_structures|.
-  virtual void OnFormsParsed(const std::vector<const FormData*>& forms,
-                             const base::TimeTicks timestamp) = 0;
+  virtual void OnFormsParsed(const std::vector<const FormData*>& forms) = 0;
 
   // Returns the number of FormStructures with the given |form_signature| and
   // appends them to |form_structures|. Runs in linear time.
diff --git a/components/autofill/core/browser/autofill_handler_proxy.cc b/components/autofill/core/browser/autofill_handler_proxy.cc
index 41fd6d4..e7ea4a96a 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -62,18 +62,14 @@
   provider_->OnSelectControlDidChange(this, form, field, bounding_box);
 }
 
-bool AutofillHandlerProxy::ShouldParseForms(const std::vector<FormData>& forms,
-                                            const base::TimeTicks timestamp) {
-  provider_->OnFormsSeen(this, forms, timestamp);
+bool AutofillHandlerProxy::ShouldParseForms(
+    const std::vector<FormData>& forms) {
+  provider_->OnFormsSeen(this, forms);
   // Need to parse the |forms| to FormStructure, so heuristic_type can be
   // retrieved later.
   return true;
 }
 
-void AutofillHandlerProxy::OnFormsParsed(
-    const std::vector<const FormData*>& form_structures,
-    const base::TimeTicks timestamp) {}
-
 void AutofillHandlerProxy::OnFocusNoLongerOnForm(bool had_interacted_form) {
   provider_->OnFocusNoLongerOnForm(this, had_interacted_form);
 }
@@ -84,10 +80,6 @@
   provider_->OnDidFillAutofillFormData(this, form, timestamp);
 }
 
-void AutofillHandlerProxy::OnDidPreviewAutofillFormData() {}
-
-void AutofillHandlerProxy::OnDidEndTextFieldEditing() {}
-
 void AutofillHandlerProxy::OnHidePopup() {
   provider_->OnHidePopup(this);
 }
diff --git a/components/autofill/core/browser/autofill_handler_proxy.h b/components/autofill/core/browser/autofill_handler_proxy.h
index 8d2f0287..2a31eda 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.h
+++ b/components/autofill/core/browser/autofill_handler_proxy.h
@@ -25,8 +25,8 @@
   void OnDidFillAutofillFormData(const FormData& form,
                                  const base::TimeTicks timestamp) override;
 
-  void OnDidPreviewAutofillFormData() override;
-  void OnDidEndTextFieldEditing() override;
+  void OnDidPreviewAutofillFormData() override {}
+  void OnDidEndTextFieldEditing() override {}
   void OnHidePopup() override;
   void SelectFieldOptionsDidChange(const FormData& form) override;
 
@@ -64,11 +64,10 @@
                                     const FormFieldData& field,
                                     const gfx::RectF& bounding_box) override;
 
-  bool ShouldParseForms(const std::vector<FormData>& forms,
-                        const base::TimeTicks timestamp) override;
+  bool ShouldParseForms(const std::vector<FormData>& forms) override;
 
-  void OnFormsParsed(const std::vector<const FormData*>& form_structures,
-                     const base::TimeTicks timestamp) override;
+  void OnFormsParsed(
+      const std::vector<const FormData*>& form_structures) override {}
 
  private:
   AutofillProvider* provider_;
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index bb716b1..593c8b7 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -660,8 +660,7 @@
 }
 #endif
 
-bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms,
-                                       const base::TimeTicks timestamp) {
+bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms) {
   bool autofill_enabled = IsAutofillEnabled();
   sync_state_ = personal_data_ ? personal_data_->GetSyncSigninState()
                                : AutofillSyncSigninState::kNumSyncStates;
@@ -797,7 +796,7 @@
     copied_credit_cards.push_back(*card);
 
   // Annotate the form with the source language of the page.
-  form_structure->set_original_page_language(GetPageLanguage());
+  form_structure->set_current_page_language(GetPageLanguage());
 
   // Attach the Randomized Encoder.
   form_structure->set_randomized_encoder(
@@ -2033,8 +2032,7 @@
   return suggestions;
 }
 
-void AutofillManager::OnFormsParsed(const std::vector<const FormData*>& forms,
-                                    const base::TimeTicks timestamp) {
+void AutofillManager::OnFormsParsed(const std::vector<const FormData*>& forms) {
   DCHECK(!forms.empty());
   has_parsed_forms_ = true;
 
@@ -2798,7 +2796,7 @@
   const translate::LanguageState* language_state = client_->GetLanguageState();
   if (!language_state)
     return LanguageCode();
-  return LanguageCode(language_state->original_language());
+  return LanguageCode(language_state->current_language());
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 82af7ed6..4e07e12 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -369,10 +369,8 @@
   void OnSelectControlDidChangeImpl(const FormData& form,
                                     const FormFieldData& field,
                                     const gfx::RectF& bounding_box) override;
-  bool ShouldParseForms(const std::vector<FormData>& forms,
-                        const base::TimeTicks timestamp) override;
-  void OnFormsParsed(const std::vector<const FormData*>& forms,
-                     const base::TimeTicks timestamp) override;
+  bool ShouldParseForms(const std::vector<FormData>& forms) override;
+  void OnFormsParsed(const std::vector<const FormData*>& forms) override;
 
   AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger() {
     return form_interactions_ukm_logger_.get();
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 5f29a9f..a2bc8c1 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -462,7 +462,7 @@
   }
 
   void FormsSeen(const std::vector<FormData>& forms) {
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
   }
 
   void FormSubmitted(const FormData& form) {
@@ -8458,22 +8458,22 @@
   FormData form;
   test::CreateTestAddressFormData(&form);
 
-  autofill_client_.GetLanguageState()->SetOriginalLanguage("und");
+  autofill_client_.GetLanguageState()->SetCurrentLanguage("und");
 
-  autofill_manager_->OnFormsSeen({form}, base::TimeTicks());
+  autofill_manager_->OnFormsSeen({form});
   FormStructure* parsed_form =
       autofill_manager_->FindCachedFormByRendererId(form.unique_renderer_id);
 
   ASSERT_TRUE(parsed_form);
-  ASSERT_EQ(LanguageCode("und"), parsed_form->original_page_language());
+  ASSERT_EQ(LanguageCode("und"), parsed_form->current_page_language());
 
-  autofill_client_.GetLanguageState()->SetOriginalLanguage("zh");
+  autofill_client_.GetLanguageState()->SetCurrentLanguage("zh");
 
-  autofill_manager_->OnFormsSeen({form}, base::TimeTicks());
+  autofill_manager_->OnFormsSeen({form});
   parsed_form =
       autofill_manager_->FindCachedFormByRendererId(form.unique_renderer_id);
 
-  ASSERT_EQ(LanguageCode("zh"), parsed_form->original_page_language());
+  ASSERT_EQ(LanguageCode("zh"), parsed_form->current_page_language());
 }
 
 // AutofillManagerTest with kAutofillDisabledMixedForms feature enabled.
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 849095f..5bccf85 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -2682,7 +2682,7 @@
   // Simulate a OnFormsSeen() call that should trigger the recording.
   std::vector<FormData> forms;
   forms.push_back(form);
-  autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(forms);
 
   // Because these metrics are related to timing, it is not possible to know in
   // advance which bucket the sample will fall into, so we just need to make
@@ -3179,7 +3179,7 @@
 
   // Simulate form submission.
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_manager_->OnFormSubmitted(form, false,
                                      SubmissionSource::FORM_SUBMISSION);
 
@@ -3212,7 +3212,7 @@
 
   // Simulate form submission.
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_manager_->OnFormSubmitted(form, false,
                                      SubmissionSource::FORM_SUBMISSION);
 
@@ -3488,7 +3488,7 @@
   // number of fields enforced).
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
     histogram_tester.ExpectTotalCount("Autofill.DeveloperEngagement", 0);
   }
@@ -3500,7 +3500,7 @@
   // Expect the "form parsed without hints" metric to be logged.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
     histogram_tester.ExpectUniqueSample(
         "Autofill.DeveloperEngagement",
@@ -3525,7 +3525,7 @@
   // Expect the "form parsed with field type hints" metric to be logged.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
     histogram_tester.ExpectBucketCount(
         "Autofill.DeveloperEngagement",
@@ -3545,7 +3545,7 @@
   // "author-specified upi-vpa type" metric to be logged.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
     histogram_tester.ExpectBucketCount(
         "Autofill.DeveloperEngagement",
@@ -3578,7 +3578,7 @@
 
   // Ensure no entries are logged when loading a non-fillable form.
   {
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
 
     EXPECT_EQ(0ul, test_ukm_recorder_->entries_count());
@@ -3591,7 +3591,7 @@
   // Expect the "form parsed without field type hints" metric and the
   // "form loaded" form interaction event to be logged.
   {
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
 
     VerifyDeveloperEngagementUkm(
@@ -3642,7 +3642,7 @@
   // Expect the "form parsed without field type hints" metric and the
   // "form loaded" form interaction event to be logged.
   {
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     autofill_manager_->Reset();
 
     VerifyDeveloperEngagementUkm(
@@ -3678,7 +3678,7 @@
 
   {
     SCOPED_TRACE("VPA and other autocomplete hint present");
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
 
     VerifyDeveloperEngagementUkm(
         test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -4273,7 +4273,7 @@
   std::vector<FormData> forms(1, form);
 
   {
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
 
     VerifySubmitFormUkm(test_ukm_recorder_, forms.back(),
                         AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
@@ -4640,7 +4640,7 @@
   forms.push_back(form);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   histogram_tester.ExpectUniqueSample(
       "Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_DID_PARSE_FORM,
       1);
@@ -6679,7 +6679,7 @@
   forms.push_back(form);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData",
                                       FORM_EVENT_DID_PARSE_FORM, 1);
   histogram_tester.ExpectUniqueSample(
@@ -6714,7 +6714,7 @@
   forms.push_back(form);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData",
                                       FORM_EVENT_DID_PARSE_FORM, 1);
 
@@ -7724,7 +7724,7 @@
 TEST_F(AutofillMetricsTest, AutofillProfileIsEnabledAtPageLoad) {
   base::HistogramTester histogram_tester;
   autofill_manager_->SetAutofillProfileEnabled(true);
-  autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
+  autofill_manager_->OnFormsSeen(std::vector<FormData>());
   histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.PageLoad",
                                       true, 1);
 }
@@ -7733,7 +7733,7 @@
 TEST_F(AutofillMetricsTest, AutofillProfileIsDisabledAtPageLoad) {
   base::HistogramTester histogram_tester;
   autofill_manager_->SetAutofillProfileEnabled(false);
-  autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
+  autofill_manager_->OnFormsSeen(std::vector<FormData>());
   histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.PageLoad",
                                       false, 1);
 }
@@ -7742,7 +7742,7 @@
 TEST_F(AutofillMetricsTest, AutofillCreditCardIsEnabledAtPageLoad) {
   base::HistogramTester histogram_tester;
   autofill_manager_->SetAutofillCreditCardEnabled(true);
-  autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
+  autofill_manager_->OnFormsSeen(std::vector<FormData>());
   histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.PageLoad",
                                       true, 1);
 }
@@ -7751,7 +7751,7 @@
 TEST_F(AutofillMetricsTest, AutofillCreditCardIsDisabledAtPageLoad) {
   base::HistogramTester histogram_tester;
   autofill_manager_->SetAutofillCreditCardEnabled(false);
-  autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
+  autofill_manager_->OnFormsSeen(std::vector<FormData>());
   histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.PageLoad",
                                       false, 1);
 }
@@ -7801,7 +7801,7 @@
   // Expect no notifications when the form is first seen.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     histogram_tester.ExpectTotalCount("Autofill.FormSubmittedState", 0);
 
     VerifyDeveloperEngagementUkm(
@@ -8070,7 +8070,7 @@
   {
     base::HistogramTester histogram_tester;
     base::UserActionTester user_action_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     VerifyDeveloperEngagementUkm(
         test_ukm_recorder_, form, /*is_for_credit_card=*/false,
         {FormType::ADDRESS_FORM},
@@ -8193,7 +8193,7 @@
   // Expect a notification when the form is first seen.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     histogram_tester.ExpectTotalCount("Autofill.UserHappiness", 0);
     histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
     histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
@@ -8234,7 +8234,7 @@
   {
     SCOPED_TRACE("First seen");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
                                         AutofillMetrics::FORMS_LOADED, 1);
     histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
@@ -8398,7 +8398,7 @@
   // Expect a notification when the form is first seen.
   {
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
                                         AutofillMetrics::FORMS_LOADED, 1);
     histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
@@ -8433,7 +8433,7 @@
   }
 
   autofill_manager_->Reset();
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   // Simulate suggestions shown twice for a single edit (i.e. multiple
   // keystrokes in a single field).
   {
@@ -8674,7 +8674,7 @@
   {
     SCOPED_TRACE("Test 1");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     base::TimeTicks parse_time = autofill_manager_->form_structures()
                                      .begin()
                                      ->second->form_parsed_timestamp();
@@ -8698,7 +8698,7 @@
   {
     SCOPED_TRACE("Test 2");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     base::TimeTicks parse_time = autofill_manager_->form_structures()
                                      .begin()
                                      ->second->form_parsed_timestamp();
@@ -8727,7 +8727,7 @@
   {
     SCOPED_TRACE("Test 3");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     base::TimeTicks parse_time = autofill_manager_->form_structures()
                                      .begin()
                                      ->second->form_parsed_timestamp();
@@ -8757,7 +8757,7 @@
     SCOPED_TRACE("Test 4");
     base::HistogramTester histogram_tester;
 
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     base::TimeTicks parse_time = autofill_manager_->form_structures()
                                      .begin()
                                      ->second->form_parsed_timestamp();
@@ -8789,11 +8789,11 @@
   {
     SCOPED_TRACE("Test 5");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
     base::TimeTicks parse_time = autofill_manager_->form_structures()
                                      .begin()
                                      ->second->form_parsed_timestamp();
-    autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(second_forms);
     autofill_manager_->OnDidFillAutofillFormData(
         form, parse_time + base::TimeDelta::FromMicroseconds(5));
     autofill_manager_->OnTextFieldDidChange(
@@ -8821,8 +8821,8 @@
   {
     SCOPED_TRACE("Test 6");
     base::HistogramTester histogram_tester;
-    autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
-    autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
+    autofill_manager_->OnFormsSeen(forms);
+    autofill_manager_->OnFormsSeen(second_forms);
     base::TimeTicks parse_time{};
     for (const auto& kv : autofill_manager_->form_structures()) {
       if (kv.second->form_parsed_timestamp() > parse_time)
@@ -9128,7 +9128,7 @@
 
   // Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
   // submitted.
-  autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_manager_->OnFormSubmitted(form, false,
                                      SubmissionSource::FORM_SUBMISSION);
   histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9141,7 +9141,7 @@
 
   // Expect to log EXISTING_PROFILE_USED for the metric since the same profile
   // is submitted.
-  autofill_manager_->OnFormsSeen(second_forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(second_forms);
   autofill_manager_->OnFormSubmitted(second_form, false,
                                      SubmissionSource::FORM_SUBMISSION);
   histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9154,7 +9154,7 @@
 
   // Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
   // submitted.
-  autofill_manager_->OnFormsSeen(third_forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(third_forms);
   autofill_manager_->OnFormSubmitted(third_form, false,
                                      SubmissionSource::FORM_SUBMISSION);
   histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9167,7 +9167,7 @@
 
   // Expect to log EXISTING_PROFILE_UPDATED for the metric since the profile was
   // updated.
-  autofill_manager_->OnFormsSeen(fourth_forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(fourth_forms);
   autofill_manager_->OnFormSubmitted(fourth_form, false,
                                      SubmissionSource::FORM_SUBMISSION);
   histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9706,7 +9706,7 @@
     base::HistogramTester histogram_tester;
     autofill_client_.set_security_level(
         security_state::SecurityLevel::DANGEROUS);
-    autofill_manager_->OnFormsSeen(forms, TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
     histogram_tester.ExpectBucketCount(
         "Autofill.UserHappiness.Address.DANGEROUS",
         AutofillMetrics::FORMS_LOADED, 1);
@@ -10092,7 +10092,7 @@
   forms_with_one_time_code.back().fields.push_back(field);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_with_one_time_code, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_with_one_time_code);
   autofill_manager_.reset();
   // Verifies that autocomplete="one-time-code" in a form is correctly recorded.
   histogram_tester.ExpectBucketCount(
@@ -10120,7 +10120,7 @@
   forms_without_one_time_code.back().fields.push_back(field);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_without_one_time_code, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_without_one_time_code);
   autofill_manager_.reset();
   histogram_tester.ExpectBucketCount(
       "Autofill.WebOTP.OneTimeCode.FromAutocomplete",
@@ -10154,7 +10154,7 @@
   forms_with_phone_number.back().fields.push_back(field);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_with_phone_number, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_with_phone_number);
   autofill_manager_.reset();
   histogram_tester.ExpectBucketCount(
       "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
@@ -10183,8 +10183,7 @@
   forms_with_single_phone_number_field.back().fields.push_back(field);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_with_single_phone_number_field,
-                                 TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_with_single_phone_number_field);
   autofill_manager_.reset();
   histogram_tester.ExpectBucketCount(
       "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
@@ -10203,7 +10202,7 @@
   std::vector<FormData> forms_with_phone_number(1, form);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_with_phone_number, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_with_phone_number);
   autofill_manager_.reset();
   histogram_tester.ExpectBucketCount(
       "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
@@ -10230,7 +10229,7 @@
   forms_without_phone_number.back().fields.push_back(field);
 
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms_without_phone_number, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms_without_phone_number);
   autofill_manager_.reset();
   histogram_tester.ExpectBucketCount(
       "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
@@ -10251,7 +10250,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(false);
@@ -10269,7 +10268,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(false);
@@ -10301,7 +10300,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(true);
@@ -10320,7 +10319,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(false);
@@ -10339,7 +10338,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(false);
@@ -10358,7 +10357,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(true);
@@ -10380,7 +10379,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(true);
@@ -10406,7 +10405,7 @@
 
   std::vector<FormData> forms(1, form);
   base::HistogramTester histogram_tester;
-  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
   static_cast<ContentAutofillDriver*>(autofill_driver_.get())
       ->ReportAutofillWebOTPMetrics(/* Document uses WebOTP */ true);
@@ -10527,7 +10526,7 @@
   FormData form;
   FormStructure form_structure(form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->OnFormsSeen(forms, AutofillTickClock::NowTicks());
+  autofill_manager_->OnFormsSeen(forms);
   autofill_manager_->Reset();
 
   {
@@ -10680,7 +10679,7 @@
   const bool user_submitted_form = GetParam() >= 4;
 
   // Simulate that the autofill manager has seen this form on page load.
-  autofill_manager_->OnFormsSeen({form}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form});
 
   if (!user_saw_suggestion) {
     // Remove the profile to prevent suggestion from being shown.
@@ -10837,7 +10836,7 @@
   base::HistogramTester histogram_tester;
 
   // Simulate page load.
-  autofill_manager_->OnFormsSeen({form_}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form_});
   autofill_manager_->OnQueryFormFieldAutofill(
       0, form_, form_.fields[0], gfx::RectF(),
       /*autoselect_first_suggestion=*/false);
@@ -10868,7 +10867,7 @@
 
   // Simulate that no data is available.
   personal_data_->ClearProfiles();
-  autofill_manager_->OnFormsSeen({form_}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form_});
   autofill_manager_->OnQueryFormFieldAutofill(
       0, form_, form_.fields[0], gfx::RectF(),
       /*autoselect_first_suggestion=*/false);
@@ -10903,7 +10902,7 @@
   base::HistogramTester histogram_tester;
 
   // Simulate that suggestion is shown but user does not accept it.
-  autofill_manager_->OnFormsSeen({form_}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form_});
   autofill_manager_->OnQueryFormFieldAutofill(
       0, form_, form_.fields[0], gfx::RectF(),
       /*autoselect_first_suggestion=*/false);
@@ -10940,7 +10939,7 @@
   base::HistogramTester histogram_tester;
 
   // Simulate that suggestion is shown and user accepts it.
-  autofill_manager_->OnFormsSeen({form_}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form_});
   autofill_manager_->OnQueryFormFieldAutofill(
       0, form_, form_.fields[0], gfx::RectF(),
       /*autoselect_first_suggestion=*/false);
@@ -10979,7 +10978,7 @@
   base::HistogramTester histogram_tester;
 
   // Simulate that suggestion is shown and user accepts it.
-  autofill_manager_->OnFormsSeen({form_}, TimeTicks());
+  autofill_manager_->OnFormsSeen({form_});
   autofill_manager_->OnQueryFormFieldAutofill(
       0, form_, form_.fields[0], gfx::RectF(),
       /*autoselect_first_suggestion=*/false);
diff --git a/components/autofill/core/browser/autofill_provider.h b/components/autofill/core/browser/autofill_provider.h
index 1d9b93d..c624e6f 100644
--- a/components/autofill/core/browser/autofill_provider.h
+++ b/components/autofill/core/browser/autofill_provider.h
@@ -65,8 +65,7 @@
                                          base::TimeTicks timestamp) = 0;
 
   virtual void OnFormsSeen(AutofillHandlerProxy* handler,
-                           const std::vector<FormData>& forms,
-                           const base::TimeTicks timestamp) = 0;
+                           const std::vector<FormData>& forms) = 0;
 
   virtual void OnHidePopup(AutofillHandlerProxy* handler) = 0;
 
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index ac7434b..2cd4c4275 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -658,7 +658,7 @@
   // prediction routines.
   if (ShouldRunHeuristics()) {
     const FieldCandidatesMap field_type_map = FormField::ParseFormFields(
-        fields_, original_page_language_, is_form_tag_, log_manager);
+        fields_, current_page_language_, is_form_tag_, log_manager);
     for (const auto& field : fields_) {
       const auto iter = field_type_map.find(field->unique_renderer_id);
       if (iter != field_type_map.end()) {
@@ -711,8 +711,8 @@
   upload->set_data_present(EncodeFieldTypes(available_field_types));
   upload->set_passwords_revealed(passwords_were_revealed_);
   upload->set_has_form_tag(is_form_tag_);
-  if (!original_page_language_->empty() && randomized_encoder_ != nullptr) {
-    upload->set_language(original_page_language_.value());
+  if (!current_page_language_->empty() && randomized_encoder_ != nullptr) {
+    upload->set_language(current_page_language_.value());
   }
 
   auto triggering_event = (submission_event_ != SubmissionIndicatorEvent::NONE)
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index cee4187..fbbdf198 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -366,12 +366,12 @@
 
   void set_is_rich_query_enabled(bool v) { is_rich_query_enabled_ = v; }
 
-  const LanguageCode& original_page_language() const {
-    return original_page_language_;
+  const LanguageCode& current_page_language() const {
+    return current_page_language_;
   }
 
-  void set_original_page_language(LanguageCode language) {
-    original_page_language_ = std::move(language);
+  void set_current_page_language(LanguageCode language) {
+    current_page_language_ = std::move(language);
   }
 
   bool value_from_dynamic_change_form() const {
@@ -588,7 +588,7 @@
 
   // The language detected for this form's page, before any translations
   // performed by Chrome.
-  LanguageCode original_page_language_;
+  LanguageCode current_page_language_;
 
   // The id attribute of the form.
   base::string16 id_attribute_;
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index d6dbaf2..b4a0d25 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -174,7 +174,7 @@
   }
 
   void FormsSeen(const std::vector<FormData>& forms) {
-    autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
   }
 
   void FormSubmitted(const FormData& form) {
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index 5843d193..bb3b770 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -110,7 +110,7 @@
   }
 
   void FormsSeen(const std::vector<FormData>& forms) {
-    autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
+    autofill_manager_->OnFormsSeen(forms);
   }
 
   void FormSubmitted(const FormData& form) {
diff --git a/components/autofill/core/browser/test_autofill_provider.cc b/components/autofill/core/browser/test_autofill_provider.cc
deleted file mode 100644
index ac9248b..0000000
--- a/components/autofill/core/browser/test_autofill_provider.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/test_autofill_provider.h"
-
-namespace autofill {
-
-void TestAutofillProvider::OnQueryFormFieldAutofill(
-    AutofillHandlerProxy* handler,
-    int32_t id,
-    const FormData& form,
-    const FormFieldData& field,
-    const gfx::RectF& bounding_box,
-    bool autoselect_first_suggestion) {}
-
-void TestAutofillProvider::OnTextFieldDidChange(
-    AutofillHandlerProxy* handler,
-    const FormData& form,
-    const FormFieldData& field,
-    const gfx::RectF& bounding_box,
-    const base::TimeTicks timestamp) {}
-
-void TestAutofillProvider::OnTextFieldDidScroll(
-    AutofillHandlerProxy* handler,
-    const FormData& form,
-    const FormFieldData& field,
-    const gfx::RectF& bounding_box) {}
-
-void TestAutofillProvider::OnSelectControlDidChange(
-    AutofillHandlerProxy* handler,
-    const FormData& form,
-    const FormFieldData& field,
-    const gfx::RectF& bounding_box) {}
-
-void TestAutofillProvider::OnFocusNoLongerOnForm(AutofillHandlerProxy* handler,
-                                                 bool had_interacted_form) {}
-
-void TestAutofillProvider::OnFocusOnFormField(AutofillHandlerProxy* handler,
-                                              const FormData& form,
-                                              const FormFieldData& field,
-                                              const gfx::RectF& bounding_box) {}
-
-void TestAutofillProvider::OnDidFillAutofillFormData(
-    AutofillHandlerProxy* handler,
-    const FormData& form,
-    base::TimeTicks timestamp) {}
-
-void TestAutofillProvider::OnFormsSeen(AutofillHandlerProxy* handler,
-                                       const std::vector<FormData>& forms,
-                                       const base::TimeTicks timestamp) {}
-
-void TestAutofillProvider::OnHidePopup(AutofillHandlerProxy* handler) {}
-
-void TestAutofillProvider::Reset(AutofillHandlerProxy* handler) {}
-
-}  // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_provider.h b/components/autofill/core/browser/test_autofill_provider.h
index db72341..25a3c10e 100644
--- a/components/autofill/core/browser/test_autofill_provider.h
+++ b/components/autofill/core/browser/test_autofill_provider.h
@@ -19,38 +19,37 @@
                                 const FormData& form,
                                 const FormFieldData& field,
                                 const gfx::RectF& bounding_box,
-                                bool autoselect_first_suggestion) override;
+                                bool autoselect_first_suggestion) override {}
   void OnTextFieldDidChange(AutofillHandlerProxy* handler,
                             const FormData& form,
                             const FormFieldData& field,
                             const gfx::RectF& bounding_box,
-                            const base::TimeTicks timestamp) override;
+                            const base::TimeTicks timestamp) override {}
   void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
                             const FormData& form,
                             const FormFieldData& field,
-                            const gfx::RectF& bounding_box) override;
+                            const gfx::RectF& bounding_box) override {}
   void OnSelectControlDidChange(AutofillHandlerProxy* handler,
                                 const FormData& form,
                                 const FormFieldData& field,
-                                const gfx::RectF& bounding_box) override;
+                                const gfx::RectF& bounding_box) override {}
   void OnFormSubmitted(AutofillHandlerProxy* handler,
                        const FormData& form,
                        bool known_success,
                        mojom::SubmissionSource source) override {}
   void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler,
-                             bool had_interacted_form) override;
+                             bool had_interacted_form) override {}
   void OnFocusOnFormField(AutofillHandlerProxy* handler,
                           const FormData& form,
                           const FormFieldData& field,
-                          const gfx::RectF& bounding_box) override;
+                          const gfx::RectF& bounding_box) override {}
   void OnDidFillAutofillFormData(AutofillHandlerProxy* handler,
                                  const FormData& form,
-                                 base::TimeTicks timestamp) override;
+                                 base::TimeTicks timestamp) override {}
   void OnFormsSeen(AutofillHandlerProxy* handler,
-                   const std::vector<FormData>& forms,
-                   const base::TimeTicks timestamp) override;
-  void OnHidePopup(AutofillHandlerProxy* handler) override;
-  void Reset(AutofillHandlerProxy* handler) override;
+                   const std::vector<FormData>& forms) override {}
+  void OnHidePopup(AutofillHandlerProxy* handler) override {}
+  void Reset(AutofillHandlerProxy* handler) override {}
 };
 
 }  // namespace autofill
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index c33daac..fc6be39 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -270,7 +270,7 @@
                   ofFormsSeen:(const FormDataVector&)forms {
   DCHECK(autofillManager);
   DCHECK(!forms.empty());
-  autofillManager->OnFormsSeen(forms, base::TimeTicks::Now());
+  autofillManager->OnFormsSeen(forms);
 }
 
 // Notifies the autofill manager when forms are submitted.
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
index 595d5d71..519600c 100644
--- a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
+++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
@@ -213,8 +213,11 @@
 ClientDiscardableSharedMemoryManager::~ClientDiscardableSharedMemoryManager() {
   base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
       this);
-  // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533
-  // DCHECK_EQ(heap_->GetSize(), heap_->GetSizeOfFreeLists());
+  // Any memory allocated by a ClientDiscardableSharedMemoryManager must not be
+  // touched after it is destroyed, or it will cause a use-after-free. This
+  // check ensures that we stop before that can happen, instead of continuing
+  // with dangling pointers.
+  CHECK_EQ(heap_->GetSize(), heap_->GetSizeOfFreeLists());
   if (heap_->GetSize())
     MemoryUsageChanged(0, 0);
 
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
index 86feda6..f5ce98b 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -204,23 +204,63 @@
     }
 
     /**
+     * Types of async action that can be taken for a navigation.
+     */
+    @IntDef({OverrideUrlLoadingAsyncActionType.UI_GATING_BROWSER_NAVIGATION,
+            OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
+            OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface OverrideUrlLoadingAsyncActionType {
+        /* The user has been presented with a consent dialog gating a browser navigation. */
+        int UI_GATING_BROWSER_NAVIGATION = 0;
+        /* The user has been presented with a consent dialog gating an intent launch. */
+        int UI_GATING_INTENT_LAUNCH = 1;
+        /* No async action has been taken. */
+        int NO_ASYNC_ACTION = 2;
+
+        int NUM_ENTRIES = 3;
+    }
+  
+    /**
      * Packages information about the result of a check of whether we should override URL loading.
      */
     public static class OverrideUrlLoadingResult {
         @OverrideUrlLoadingResultType
         int mResultType;
 
+        @OverrideUrlLoadingAsyncActionType
+        int mAsyncActionType;
+
         OverrideUrlLoadingResult(@OverrideUrlLoadingResultType int resultType) {
+            this(resultType, OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION);
+        }
+
+        OverrideUrlLoadingResult(@OverrideUrlLoadingResultType int resultType,
+                @OverrideUrlLoadingAsyncActionType int asyncActionType) {
+            // The async action type should be set only for async actions...
+            assert (asyncActionType == OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION
+                    || resultType == OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION);
+
+            // ...and it *must* be set for async actions.
+            assert (!(asyncActionType == OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION
+                    && resultType == OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION));
+
             mResultType = resultType;
+            mAsyncActionType = asyncActionType;
         }
 
         public @OverrideUrlLoadingResultType int getResultType() {
             return mResultType;
         }
 
-        public static OverrideUrlLoadingResult forAsyncAction() {
+        public @OverrideUrlLoadingAsyncActionType int getAsyncActionType() {
+            return mAsyncActionType;
+        }
+
+        public static OverrideUrlLoadingResult forAsyncAction(
+                @OverrideUrlLoadingAsyncActionType int asyncActionType) {
             return new OverrideUrlLoadingResult(
-                    OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION);
+                    OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, asyncActionType);
         }
         public static OverrideUrlLoadingResult forNoOverride() {
             return new OverrideUrlLoadingResult(OverrideUrlLoadingResultType.NO_OVERRIDE);
@@ -990,7 +1030,8 @@
                     params.shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent(),
                     shouldProxyForInstantApps)) {
             if (DEBUG) Log.i(TAG, "Incognito navigation out");
-            return OverrideUrlLoadingResult.forAsyncAction();
+            return OverrideUrlLoadingResult.forAsyncAction(
+                    OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH);
         }
         if (DEBUG) Log.i(TAG, "Failed to show incognito alert dialog.");
         return OverrideUrlLoadingResult.forNoOverride();
@@ -1184,7 +1225,8 @@
         // This check should happen for reloads, navigations, etc..., which is why
         // it occurs before the subsequent blocks.
         if (startFileIntentIfNecessary(params, targetIntent)) {
-            return OverrideUrlLoadingResult.forAsyncAction();
+            return OverrideUrlLoadingResult.forAsyncAction(
+                    OverrideUrlLoadingAsyncActionType.UI_GATING_BROWSER_NAVIGATION);
         }
 
         // This should come after file intents, but before any returns of
@@ -1374,7 +1416,8 @@
                 return OverrideUrlLoadingResult.forNoOverride();
             }
             if (DEBUG) Log.i(TAG, "Incognito intent to Play Store.");
-            return OverrideUrlLoadingResult.forAsyncAction();
+            return OverrideUrlLoadingResult.forAsyncAction(
+                    OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH);
         } else {
             startActivity(intent, false, mDelegate);
             if (DEBUG) Log.i(TAG, "Intent to Play Store.");
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index fe07bf1..65b43d8 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -34,6 +34,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
+import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingAsyncActionType;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -862,6 +863,7 @@
                 .withIsIncognito(true)
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+                        OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
                         START_INCOGNITO | START_OTHER_ACTIVITY);
 
         Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
@@ -1089,6 +1091,7 @@
                 .withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
                 .withIsIncognito(true)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+                        OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
                         START_INCOGNITO | START_OTHER_ACTIVITY);
 
         Intent invokedIntent = mUrlHandler.mStartActivityInIncognitoIntent;
@@ -1464,7 +1467,8 @@
         // Verify that the file intent action is triggered if file access is not allowed.
         checkUrl(fileUrl)
                 .withPageTransition(PageTransition.AUTO_TOPLEVEL)
-                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, START_FILE);
+                .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+                        OverrideUrlLoadingAsyncActionType.UI_GATING_BROWSER_NAVIGATION, START_FILE);
     }
 
     @Test
@@ -1608,6 +1612,7 @@
         checkUrl("market://1234")
                 .withIsIncognito(true)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+                        OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
                         START_INCOGNITO | START_OTHER_ACTIVITY);
 
         Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
@@ -1650,6 +1655,7 @@
                 .withHasUserGesture(true)
                 .withIsIncognito(true)
                 .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+                        OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
                         START_INCOGNITO | START_OTHER_ACTIVITY);
         Assert.assertTrue(mDelegate.maybeSetRequestMetadataCalled);
         Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
@@ -2389,6 +2395,13 @@
 
         public void expecting(
                 @OverrideUrlLoadingResultType int expectedOverrideResult, int otherExpectation) {
+            expecting(expectedOverrideResult, OverrideUrlLoadingAsyncActionType.NO_ASYNC_ACTION,
+                    otherExpectation);
+        }
+
+        public void expecting(@OverrideUrlLoadingResultType int expectedOverrideResult,
+                @OverrideUrlLoadingAsyncActionType int expectedOverrideAsyncAction,
+                int otherExpectation) {
             boolean expectStartIncognito = (otherExpectation & START_INCOGNITO) != 0;
             boolean expectStartActivity =
                     (otherExpectation & (START_WEBAPK | START_OTHER_ACTIVITY)) != 0;
@@ -2431,6 +2444,7 @@
             }
 
             Assert.assertEquals(expectedOverrideResult, result.getResultType());
+            Assert.assertEquals(expectedOverrideAsyncAction, result.getAsyncActionType());
             Assert.assertEquals(expectStartIncognito, mUrlHandler.mStartIncognitoIntentCalled);
             Assert.assertEquals(expectStartActivity, startActivityCalled);
             Assert.assertEquals(expectStartWebApk, startWebApkCalled);
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc
index 7eeae75..e08c8f4 100644
--- a/components/password_manager/core/browser/votes_uploader.cc
+++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -369,7 +369,7 @@
   }
 
   // Annotate the form with the source language of the page.
-  form_structure.set_original_page_language(client_->GetPageLanguage());
+  form_structure.set_current_page_language(client_->GetPageLanguage());
 
   // Attach the Randomized Encoder.
   form_structure.set_randomized_encoder(
@@ -423,7 +423,7 @@
   form_structure.set_upload_required(UPLOAD_REQUIRED);
 
   // Annotate the form with the source language of the page.
-  form_structure.set_original_page_language(client_->GetPageLanguage());
+  form_structure.set_current_page_language(client_->GetPageLanguage());
 
   // Attach the Randomized Encoder.
   form_structure.set_randomized_encoder(
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index 283150e3..d470e380 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -207,3 +207,33 @@
 java_cpp_enum("payments_journey_logger_enum_javagen") {
   sources = [ "//components/payments/core/journey_logger.h" ]
 }
+
+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/PaymentRequestServiceBuilder.java",
+    "junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java",
+  ]
+  deps = [
+    ":java",
+    "//base:base_java",
+    "//base:base_java_test_support",
+    "//base:base_junit_test_support",
+    "//base:jni_java",
+    "//components/payments/content/android:service_java",
+    "//components/payments/mojom:mojom_java",
+    "//content/public/android:content_java",
+    "//mojo/public/java:system_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//third_party/android_deps:androidx_collection_collection_java",
+    "//third_party/android_deps:material_design_java",
+    "//third_party/android_deps:robolectric_all_java",
+    "//third_party/blink/public/mojom:android_mojo_bindings_java",
+    "//third_party/junit",
+    "//third_party/mockito:mockito_java",
+    "//url:gurl_java",
+    "//url:origin_java",
+  ]
+}
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
index db79b539..a6a8ab34a 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -19,7 +19,6 @@
 import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsStatics;
 import org.chromium.mojo.system.MojoException;
 import org.chromium.payments.mojom.CanMakePaymentQueryResult;
 import org.chromium.payments.mojom.HasEnrolledInstrumentQueryResult;
@@ -42,6 +41,7 @@
 import org.chromium.url.Origin;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -200,6 +200,88 @@
          */
         @Nullable
         String getTwaPackageName();
+
+        /**
+         * Gets the WebContents from a RenderFrameHost if the WebContents has not been destroyed;
+         * otherwise, return null.
+         * @param renderFrameHost The {@link RenderFrameHost} of any frame in which the intended
+         *         WebContents contains.
+         * @return The WebContents.
+         */
+        @Nullable
+        default WebContents getLiveWebContents(RenderFrameHost renderFrameHost) {
+            return PaymentRequestServiceUtil.getLiveWebContents(renderFrameHost);
+        }
+
+        /**
+         * Returns true for a valid URL from a secure origin.
+         * @param url The URL to check.
+         * @return Whether the origin of the URL is secure.
+         */
+        default boolean isOriginSecure(String url) {
+            return OriginSecurityChecker.isOriginSecure(url);
+        }
+
+        /**
+         * Creates a journey logger.
+         * @param isIncognito Whether the user profile is incognito.
+         * @param webContents The web contents where PaymentRequest API is invoked. Should not be
+         *         null.
+         */
+        default JourneyLogger createJourneyLogger(boolean isIncognito, WebContents webContents) {
+            return new JourneyLogger(isIncognito, webContents);
+        }
+
+        /**
+         * Builds a String that strips down |uri| to its scheme, host, and port.
+         * @param uri The URI to break down.
+         * @return Stripped-down String containing the essential bits of the URL, or the original
+         *         URL if it fails to parse it.
+         */
+        default String formatUrlForSecurityDisplay(String uri) {
+            return UrlFormatter.formatUrlForSecurityDisplay(uri);
+        }
+
+        /**
+         * @param webContents The WebContents to get site certificate chain from.
+         * @return The site certificate chain of the given WebContents.
+         */
+        default byte[][] getCertificateChain(WebContents webContents) {
+            return CertificateChainHelper.getCertificateChain(webContents);
+        }
+
+        /**
+         * Checks whether the page at the given URL should be allowed to use the web payment APIs.
+         * @param url The URL to check.
+         * @return Whether the page is allowed to use web payment APIs.
+         */
+        default boolean isOriginAllowedToUseWebPaymentApis(String url) {
+            return UrlUtil.isOriginAllowedToUseWebPaymentApis(url);
+        }
+
+        /**
+         * @param details The payment details to verify.
+         * @return Whether the details are valid.
+         */
+        default boolean validatePaymentDetails(PaymentDetails details) {
+            return PaymentValidator.validatePaymentDetails(details);
+        }
+
+        /**
+         * Creates an instance of {@link PaymentRequestSpec} that stores the given info.
+         * @param options The payment options, e.g., whether shipping is requested.
+         * @param details The payment details, e.g., the total amount.
+         * @param methodData The list of supported payment method identifiers and corresponding
+         *         payment
+         * method specific data.
+         * @param appLocale The current application locale.
+         * @return The payment request spec.
+         */
+        default PaymentRequestSpec createPaymentRequestSpec(PaymentOptions options,
+                PaymentDetails details, Collection<PaymentMethodData> methodData,
+                String appLocale) {
+            return new PaymentRequestSpec(options, details, methodData, appLocale);
+        }
     }
 
     /**
@@ -264,32 +346,30 @@
      * Create an instance of {@link PaymentRequest} that provides the Android PaymentRequest
      * service.
      * @param renderFrameHost The RenderFrameHost of the merchant page.
-     * @param isOffTheRecord Whether the merchant page is in a off-the-record (e.g., incognito,
-     *         guest mode) Tab.
      * @param delegate The delegate of this class.
      * @param browserPaymentRequestFactory The factory that generates BrowserPaymentRequest.
      * @return The created instance.
      */
     public static PaymentRequest createPaymentRequest(RenderFrameHost renderFrameHost,
-            boolean isOffTheRecord, Delegate delegate,
-            BrowserPaymentRequest.Factory browserPaymentRequestFactory) {
+            Delegate delegate, Factory browserPaymentRequestFactory) {
         return new MojoPaymentRequestGateKeeper(
                 (client, methodData, details, options, googlePayBridgeEligible, onClosedListener)
-                        -> createIfParamsValid(renderFrameHost, isOffTheRecord,
-                                browserPaymentRequestFactory, client, methodData, details, options,
-                                googlePayBridgeEligible, onClosedListener, delegate));
+                        -> createIfParamsValid(renderFrameHost, browserPaymentRequestFactory,
+                                client, methodData, details, options, googlePayBridgeEligible,
+                                onClosedListener, delegate));
     }
 
     /**
      * @return An instance of {@link PaymentRequestService} only if the parameters are deemed
      *         valid; Otherwise, null.
      */
+    @VisibleForTesting
     @Nullable
-    private static PaymentRequestService createIfParamsValid(RenderFrameHost renderFrameHost,
-            boolean isOffTheRecord, BrowserPaymentRequest.Factory browserPaymentRequestFactory,
-            @Nullable PaymentRequestClient client, @Nullable PaymentMethodData[] methodData,
-            @Nullable PaymentDetails details, @Nullable PaymentOptions options,
-            boolean googlePayBridgeEligible, Runnable onClosedListener, Delegate delegate) {
+    public static PaymentRequestService createIfParamsValid(RenderFrameHost renderFrameHost,
+            Factory browserPaymentRequestFactory, @Nullable PaymentRequestClient client,
+            @Nullable PaymentMethodData[] methodData, @Nullable PaymentDetails details,
+            @Nullable PaymentOptions options, boolean googlePayBridgeEligible,
+            Runnable onClosedListener, Delegate delegate) {
         assert renderFrameHost != null;
         assert browserPaymentRequestFactory != null;
         assert onClosedListener != null;
@@ -301,14 +381,15 @@
             return null;
         }
 
-        WebContents webContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost);
+        WebContents webContents = delegate.getLiveWebContents(renderFrameHost);
         if (webContents == null || webContents.isDestroyed()) {
             abortBeforeInstantiation(/*client=*/null, /*journeyLogger=*/null,
                     ErrorStrings.NO_WEB_CONTENTS, AbortReason.INVALID_DATA_FROM_RENDERER);
             return null;
         }
 
-        JourneyLogger journeyLogger = new JourneyLogger(isOffTheRecord, webContents);
+        boolean isOffTheRecord = delegate.isOffTheRecord();
+        JourneyLogger journeyLogger = delegate.createJourneyLogger(isOffTheRecord, webContents);
 
         if (client == null) {
             abortBeforeInstantiation(/*client=*/null, journeyLogger, ErrorStrings.INVALID_STATE,
@@ -316,7 +397,7 @@
             return null;
         }
 
-        if (!OriginSecurityChecker.isOriginSecure(webContents.getLastCommittedUrl())) {
+        if (!delegate.isOriginSecure(webContents.getLastCommittedUrl())) {
             abortBeforeInstantiation(client, journeyLogger, ErrorStrings.NOT_IN_A_SECURE_ORIGIN,
                     AbortReason.INVALID_DATA_FROM_RENDERER);
             return null;
@@ -437,9 +518,8 @@
 
         // TODO(crbug.com/992593): replace UrlFormatter with GURL operations.
         mPaymentRequestOrigin =
-                UrlFormatter.formatUrlForSecurityDisplay(mRenderFrameHost.getLastCommittedURL());
-        mTopLevelOrigin =
-                UrlFormatter.formatUrlForSecurityDisplay(mWebContents.getLastCommittedUrl());
+                delegate.formatUrlForSecurityDisplay(mRenderFrameHost.getLastCommittedURL());
+        mTopLevelOrigin = delegate.formatUrlForSecurityDisplay(mWebContents.getLastCommittedUrl());
 
         mPaymentOptions = options;
         mRequestShipping = mPaymentOptions.requestShipping;
@@ -449,7 +529,7 @@
         mShippingType = mPaymentOptions.shippingType;
 
         mMerchantName = mWebContents.getTitle();
-        mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents);
+        mCertificateChain = delegate.getCertificateChain(mWebContents);
         mIsOffTheRecord = isOffTheRecord;
         mClient = client;
         mJourneyLogger = journeyLogger;
@@ -479,7 +559,7 @@
         mBrowserPaymentRequest = factory.createBrowserPaymentRequest(this);
         mJourneyLogger.recordCheckoutStep(CheckoutFunnelStep.INITIATED);
 
-        if (!UrlUtil.isOriginAllowedToUseWebPaymentApis(mWebContents.getLastCommittedUrl())) {
+        if (!mDelegate.isOriginAllowedToUseWebPaymentApis(mWebContents.getLastCommittedUrl())) {
             Log.d(TAG, ErrorStrings.PROHIBITED_ORIGIN);
             Log.d(TAG, ErrorStrings.PROHIBITED_ORIGIN_OR_INVALID_SSL_EXPLANATION);
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
@@ -518,7 +598,7 @@
         mBrowserPaymentRequest.modifyQueryForQuotaCreatedIfNeeded(mQueryForQuota, mPaymentOptions);
 
         if (details == null || details.id == null || details.total == null
-                || !PaymentValidator.validatePaymentDetails(details)) {
+                || !mDelegate.validatePaymentDetails(details)) {
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage(
                     ErrorStrings.INVALID_PAYMENT_DETAILS, PaymentErrorReason.USER_CANCEL);
@@ -530,7 +610,7 @@
             return false;
         }
 
-        PaymentRequestSpec spec = new PaymentRequestSpec(mPaymentOptions, details,
+        PaymentRequestSpec spec = mDelegate.createPaymentRequestSpec(mPaymentOptions, details,
                 methodData.values(), LocaleUtils.getDefaultLocaleString());
         if (spec.getRawTotal() == null) {
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
@@ -1079,7 +1159,7 @@
         // mSpec.updateWith() can be used only when mSpec has not been destroyed.
         assert !mSpec.isDestroyed();
 
-        if (!PaymentValidator.validatePaymentDetails(details)
+        if (!mDelegate.validatePaymentDetails(details)
                 || !mBrowserPaymentRequest.parseAndValidateDetailsFurtherIfNeeded(details)) {
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             return ErrorStrings.INVALID_PAYMENT_DETAILS;
@@ -1129,8 +1209,7 @@
         }
 
         // ID cannot be updated. Updating the total is optional.
-        if (details == null || details.id != null
-                || !PaymentValidator.validatePaymentDetails(details)
+        if (details == null || details.id != null || !mDelegate.validatePaymentDetails(details)
                 || !mBrowserPaymentRequest.parseAndValidateDetailsFurtherIfNeeded(details)) {
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage(
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
new file mode 100644
index 0000000..15769f5f
--- /dev/null
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceBuilder.java
@@ -0,0 +1,238 @@
+// 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.components.payments;
+
+import androidx.annotation.Nullable;
+
+import org.mockito.Mockito;
+
+import org.chromium.components.payments.BrowserPaymentRequest.Factory;
+import org.chromium.components.payments.PaymentRequestService.Delegate;
+import org.chromium.content_public.browser.RenderFrameHost;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.payments.mojom.PaymentDetails;
+import org.chromium.payments.mojom.PaymentItem;
+import org.chromium.payments.mojom.PaymentMethodData;
+import org.chromium.payments.mojom.PaymentOptions;
+import org.chromium.payments.mojom.PaymentRequestClient;
+import org.chromium.url.Origin;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/** A builder of PaymentRequestService for testing. */
+public class PaymentRequestServiceBuilder implements PaymentRequestService.Delegate {
+    private static final String TWA_PACKAGE_NAME = "twa.package.name";
+    private final Delegate mDelegate;
+    private final RenderFrameHost mRenderFrameHost;
+    private final Runnable mOnClosedListener;
+    private final Factory mBrowserPaymentRequestFactory;
+    private WebContents mWebContents;
+    private boolean mIsOffTheRecord = true;
+    private PaymentRequestClient mClient;
+    private PaymentMethodData[] mMethodData;
+    private PaymentDetails mDetails;
+    private PaymentOptions mOptions;
+    private boolean mGooglePayBridgeEligible;
+    private boolean mPrefsCanMakePayment;
+    private String mInvalidSslCertificateErrorMessage;
+    private boolean mIsOriginSecure = true;
+    private JourneyLogger mJourneyLogger;
+    private String mTopLevelOrigin;
+    private String mFrameOrigin;
+    private boolean mIsOriginAllowedToUseWebPaymentApis = true;
+    private boolean mIsPaymentDetailsValid = true;
+    private PaymentRequestSpec mSpec;
+
+    /* package */ static PaymentRequestServiceBuilder defaultBuilder(Runnable onClosedListener,
+            PaymentRequestClient client, BrowserPaymentRequest browserPaymentRequest) {
+        return new PaymentRequestServiceBuilder(onClosedListener, client, browserPaymentRequest);
+    }
+
+    private PaymentRequestServiceBuilder(Runnable onClosedListener, PaymentRequestClient client,
+            BrowserPaymentRequest browserPaymentRequest) {
+        mDelegate = this;
+        mWebContents = Mockito.mock(WebContents.class);
+        setTopLevelOrigin("https://top.level.origin");
+        mRenderFrameHost = Mockito.mock(RenderFrameHost.class);
+        setFrameOrigin("https://frame.origin");
+        Origin origin = Mockito.mock(Origin.class);
+        Mockito.doReturn(origin).when(mRenderFrameHost).getLastCommittedOrigin();
+        mJourneyLogger = Mockito.mock(JourneyLogger.class);
+        mMethodData = new PaymentMethodData[1];
+        mMethodData[0] = new PaymentMethodData();
+        mMethodData[0].supportedMethod = "https://www.chromium.org";
+        mDetails = new PaymentDetails();
+        mDetails.id = "testId";
+        mDetails.total = new PaymentItem();
+        mOptions = new PaymentOptions();
+        mSpec = Mockito.mock(PaymentRequestSpec.class);
+        Mockito.doReturn(new PaymentItem()).when(mSpec).getRawTotal();
+        Map<String, PaymentMethodData> methodDataMap = new HashMap<>();
+        Mockito.doReturn(methodDataMap).when(mSpec).getMethodData();
+        mBrowserPaymentRequestFactory = (paymentRequestService) -> browserPaymentRequest;
+        mOnClosedListener = onClosedListener;
+        mClient = client;
+    }
+
+    @Override
+    public boolean isOffTheRecord() {
+        return mIsOffTheRecord;
+    }
+
+    @Override
+    public String getInvalidSslCertificateErrorMessage() {
+        return mInvalidSslCertificateErrorMessage;
+    }
+
+    @Override
+    public boolean prefsCanMakePayment() {
+        return mPrefsCanMakePayment;
+    }
+
+    @Nullable
+    @Override
+    public String getTwaPackageName() {
+        return TWA_PACKAGE_NAME;
+    }
+
+    @Override
+    public WebContents getLiveWebContents(RenderFrameHost renderFrameHost) {
+        return mWebContents;
+    }
+
+    @Override
+    public boolean isOriginSecure(String url) {
+        return mIsOriginSecure;
+    }
+
+    @Override
+    public JourneyLogger createJourneyLogger(boolean isIncognito, WebContents webContents) {
+        return mJourneyLogger;
+    }
+
+    @Override
+    public String formatUrlForSecurityDisplay(String url) {
+        return url;
+    }
+
+    @Override
+    public byte[][] getCertificateChain(WebContents webContents) {
+        return new byte[0][];
+    }
+
+    @Override
+    public boolean isOriginAllowedToUseWebPaymentApis(String lastCommittedUrl) {
+        return mIsOriginAllowedToUseWebPaymentApis;
+    }
+
+    @Override
+    public boolean validatePaymentDetails(PaymentDetails details) {
+        return mIsPaymentDetailsValid;
+    }
+
+    @Override
+    public PaymentRequestSpec createPaymentRequestSpec(PaymentOptions paymentOptions,
+            PaymentDetails details, Collection<PaymentMethodData> values,
+            String defaultLocaleString) {
+        return mSpec;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setRenderFrameHostLastCommittedOrigin(
+            Origin origin) {
+        Mockito.doReturn(origin).when(mRenderFrameHost).getLastCommittedOrigin();
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setRenderFrameHostLastCommittedURL(String url) {
+        Mockito.doReturn(url).when(mRenderFrameHost).getLastCommittedURL();
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setOffTheRecord(boolean isOffTheRecord) {
+        mIsOffTheRecord = isOffTheRecord;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setOriginSecure(boolean isSecure) {
+        mIsOriginSecure = isSecure;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setJourneyLogger(JourneyLogger journeyLogger) {
+        mJourneyLogger = journeyLogger;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setPaymentRequestClient(
+            PaymentRequestClient client) {
+        mClient = client;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setMethodData(PaymentMethodData[] methodData) {
+        mMethodData = methodData;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setDetails(PaymentDetails details) {
+        mDetails = details;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setOptions(PaymentOptions options) {
+        mOptions = options;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setGooglePayBridgeEligible(boolean eligible) {
+        mGooglePayBridgeEligible = eligible;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setWebContents(WebContents webContents) {
+        mWebContents = webContents;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setTopLevelOrigin(String topLevelOrigin) {
+        Mockito.doReturn(topLevelOrigin).when(mWebContents).getLastCommittedUrl();
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setFrameOrigin(String frameOrigin) {
+        Mockito.doReturn(frameOrigin).when(mRenderFrameHost).getLastCommittedURL();
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setInvalidSslCertificateErrorMessage(
+            String invalidSslCertificateErrorMessage) {
+        mInvalidSslCertificateErrorMessage = invalidSslCertificateErrorMessage;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setOriginAllowedToUseWebPaymentApis(
+            boolean isAllowed) {
+        mIsOriginAllowedToUseWebPaymentApis = isAllowed;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setIsPaymentDetailsValid(boolean isValid) {
+        mIsPaymentDetailsValid = isValid;
+        return this;
+    }
+
+    /* package */ PaymentRequestServiceBuilder setPaymentRequestSpec(PaymentRequestSpec spec) {
+        mSpec = spec;
+        return this;
+    }
+
+    /* package */ PaymentRequestService build() {
+        return PaymentRequestService.createIfParamsValid(mRenderFrameHost,
+                mBrowserPaymentRequestFactory, mClient, mMethodData, mDetails, mOptions,
+                mGooglePayBridgeEligible, mOnClosedListener, mDelegate);
+    }
+}
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
new file mode 100644
index 0000000..bd801518
--- /dev/null
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
@@ -0,0 +1,266 @@
+// 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.components.payments;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.mojo.system.MojoException;
+import org.chromium.payments.mojom.PayerDetail;
+import org.chromium.payments.mojom.PaymentAddress;
+import org.chromium.payments.mojom.PaymentErrorReason;
+import org.chromium.payments.mojom.PaymentMethodData;
+import org.chromium.payments.mojom.PaymentRequestClient;
+import org.chromium.payments.mojom.PaymentResponse;
+
+/** A test for PaymentRequestService. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class PaymentRequestServiceTest implements PaymentRequestClient {
+    private static final int NO_PAYMENT_ERROR = PaymentErrorReason.MIN_VALUE;
+    private final BrowserPaymentRequest mBrowserPaymentRequest;
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.WARN);
+
+    private boolean mIsOnCloseListenerInvoked;
+    private String mSentMethodName;
+    private String mSentStringifiedDetails;
+    private PaymentAddress mSentAddress;
+    private String mSentShippingOptionId;
+    private PayerDetail mSentPayerDetail;
+    private PaymentResponse mSentPaymentResponse;
+    private int mSentErrorReason;
+    private String mSentErrorMessage;
+    private boolean mOnCompleteCalled;
+    private boolean mIsAbortedSuccessfully;
+    private int mSentCanMakePayment;
+    private int mSentHasEnrolledInstrument;
+    private boolean mWarnNoFaviconCalled;
+    private boolean mIsClientClosed;
+    private MojoException mConnectionError;
+
+    public PaymentRequestServiceTest() {
+        mBrowserPaymentRequest = Mockito.mock(BrowserPaymentRequest.class);
+    }
+
+    @Override
+    public void onPaymentMethodChange(String methodName, String stringifiedDetails) {
+        mSentMethodName = methodName;
+        mSentStringifiedDetails = stringifiedDetails;
+    }
+
+    @Override
+    public void onShippingAddressChange(PaymentAddress address) {
+        mSentAddress = address;
+    }
+
+    @Override
+    public void onShippingOptionChange(String shippingOptionId) {
+        mSentShippingOptionId = shippingOptionId;
+    }
+
+    @Override
+    public void onPayerDetailChange(PayerDetail detail) {
+        mSentPayerDetail = detail;
+    }
+
+    @Override
+    public void onPaymentResponse(PaymentResponse response) {
+        mSentPaymentResponse = response;
+    }
+
+    @Override
+    public void onError(int error, String errorMessage) {
+        mSentErrorReason = error;
+        mSentErrorMessage = errorMessage;
+    }
+
+    @Override
+    public void onComplete() {
+        mOnCompleteCalled = true;
+    }
+
+    @Override
+    public void onAbort(boolean abortedSuccessfully) {
+        mIsAbortedSuccessfully = abortedSuccessfully;
+    }
+
+    @Override
+    public void onCanMakePayment(int result) {
+        mSentCanMakePayment = result;
+    }
+
+    @Override
+    public void onHasEnrolledInstrument(int result) {
+        mSentHasEnrolledInstrument = result;
+    }
+
+    @Override
+    public void warnNoFavicon() {
+        mWarnNoFaviconCalled = true;
+    }
+
+    @Override
+    public void close() {
+        mIsClientClosed = true;
+    }
+
+    @Override
+    public void onConnectionError(MojoException e) {
+        mConnectionError = e;
+    }
+
+    private void assertNoError() {
+        assertErrorAndReason(null, NO_PAYMENT_ERROR);
+    }
+
+    private void assertErrorAndReason(String errorMessage, int errorReason) {
+        Assert.assertEquals(errorMessage, mSentErrorMessage);
+        Assert.assertEquals(errorReason, mSentErrorReason);
+    }
+
+    private PaymentRequestServiceBuilder defaultBuilder() {
+        return PaymentRequestServiceBuilder.defaultBuilder(
+                () -> mIsOnCloseListenerInvoked = true, /*client=*/this, mBrowserPaymentRequest);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullFrameOriginFailsCreation() {
+        Assert.assertNull(defaultBuilder().setRenderFrameHostLastCommittedOrigin(null).build());
+        // Not asserting error because no frame to receive the error message and error reason.
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullFrameUrlFailsCreation() {
+        Assert.assertNull(defaultBuilder().setRenderFrameHostLastCommittedURL(null).build());
+        // Not asserting error because no frame to receive the error message and error reason.
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullWebContentsFailsCreation() {
+        Assert.assertNull(defaultBuilder().setWebContents(null).build());
+        // Not asserting error because no WebContents to receive the error message and error reason.
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testDestroyedWebContentsFailsCreation() {
+        WebContents webContents = Mockito.mock(WebContents.class);
+        Mockito.doReturn(true).when(webContents).isDestroyed();
+        Assert.assertNull(defaultBuilder().setWebContents(webContents).build());
+        // Not asserting error because no WebContents to receive the error message and error reason.
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullClientFailsCreation() {
+        Assert.assertNull(defaultBuilder().setPaymentRequestClient(null).build());
+        // Not asserting error because no client to receive the error message and error reason.
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testInsecureOriginFailsCreation() {
+        Assert.assertNull(defaultBuilder().setOriginSecure(false).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullMethodDataFailsCreation() {
+        Assert.assertNull(defaultBuilder().setMethodData(null).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullDetailsFailsCreation() {
+        Assert.assertNull(defaultBuilder().setDetails(null).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullOptionsFailsCreation() {
+        Assert.assertNull(defaultBuilder().setOptions(null).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testSslErrorFailsCreation() {
+        Assert.assertNull(
+                defaultBuilder().setInvalidSslCertificateErrorMessage("StubbedError").build());
+        assertErrorAndReason(
+                "StubbedError", PaymentErrorReason.NOT_SUPPORTED_FOR_INVALID_ORIGIN_OR_SSL);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testDisallowedOriginFailsCreation() {
+        Assert.assertNull(defaultBuilder().setOriginAllowedToUseWebPaymentApis(false).build());
+        assertErrorAndReason(ErrorStrings.PROHIBITED_ORIGIN,
+                PaymentErrorReason.NOT_SUPPORTED_FOR_INVALID_ORIGIN_OR_SSL);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testMethodDataNullElementFailsCreation() {
+        PaymentMethodData[] methodData = new PaymentMethodData[1];
+        Assert.assertNull(defaultBuilder().setMethodData(methodData).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testEmptyMethodNameFailsCreation() {
+        PaymentMethodData[] methodData = new PaymentMethodData[1];
+        methodData[0] = new PaymentMethodData();
+        methodData[0].supportedMethod = "";
+        Assert.assertNull(defaultBuilder().setMethodData(methodData).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullMethodNameFailsCreation() {
+        PaymentMethodData[] methodData = new PaymentMethodData[1];
+        methodData[0] = new PaymentMethodData();
+        methodData[0].supportedMethod = null;
+        Assert.assertNull(defaultBuilder().setMethodData(methodData).build());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testInvalidDetailsFailsCreation() {
+        Assert.assertNull(defaultBuilder().setIsPaymentDetailsValid(false).build());
+        assertErrorAndReason(ErrorStrings.INVALID_PAYMENT_DETAILS, PaymentErrorReason.USER_CANCEL);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testNullRawTotalFailsCreation() {
+        PaymentRequestSpec spec = Mockito.mock(PaymentRequestSpec.class);
+        Mockito.doReturn(null).when(spec).getRawTotal();
+        Assert.assertNull(defaultBuilder().setPaymentRequestSpec(spec).build());
+        assertErrorAndReason(ErrorStrings.TOTAL_REQUIRED, PaymentErrorReason.USER_CANCEL);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testDefaultParamsMakeCreationSuccess() {
+        PaymentRequestService service = defaultBuilder().build();
+        Assert.assertNotNull(service);
+        Mockito.verify(mBrowserPaymentRequest, Mockito.times(1)).onSpecValidated(Mockito.notNull());
+        assertNoError();
+    }
+}
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn
index 6db79a00..754fd3b 100644
--- a/components/performance_manager/BUILD.gn
+++ b/components/performance_manager/BUILD.gn
@@ -10,15 +10,18 @@
 
 static_library("performance_manager") {
   sources = [
+    "binders.cc",
     "decorators/frame_visibility_decorator.cc",
     "decorators/frame_visibility_decorator.h",
+    "decorators/freezing_vote_decorator.cc",
+    "decorators/freezing_vote_decorator.h",
     "decorators/page_live_state_decorator.cc",
     "decorators/page_load_tracker_decorator.cc",
     "decorators/page_load_tracker_decorator.h",
     "decorators/page_load_tracker_decorator_helper.cc",
     "decorators/tab_properties_decorator.cc",
-    "embedder/binders.cc",
     "embedder/binders.h",
+    "embedder/graph_features_helper.h",
     "embedder/performance_manager_lifetime.h",
     "embedder/performance_manager_registry.h",
     "execution_context/execution_context_impl.cc",
@@ -74,6 +77,7 @@
     "graph/worker_node_impl.h",
     "graph/worker_node_impl_describer.cc",
     "graph/worker_node_impl_describer.h",
+    "graph_features_helper.cc",
     "mechanisms/tab_loading_frame_navigation_scheduler.cc",
     "owned_objects.h",
     "performance_manager.cc",
@@ -100,6 +104,7 @@
     "public/execution_context_priority/max_vote_aggregator.h",
     "public/execution_context_priority/override_vote_aggregator.h",
     "public/features.h",
+    "public/freezing/freezing.h",
     "public/graph/frame_node.h",
     "public/graph/graph.h",
     "public/graph/graph_operations.h",
@@ -210,6 +215,7 @@
   sources = [
     "decorators/decorators_utils_unittest.cc",
     "decorators/frame_visibility_decorator_unittest.cc",
+    "decorators/freezing_vote_decorator_unittest.cc",
     "decorators/page_live_state_decorator_unittest.cc",
     "decorators/page_load_tracker_decorator_unittest.cc",
     "decorators/tab_properties_decorator_unittest.cc",
@@ -234,6 +240,7 @@
     "graph/properties_unittest.cc",
     "graph/system_node_impl_unittest.cc",
     "graph/worker_node_impl_unittest.cc",
+    "graph_features_helper_unittest.cc",
     "mechanisms/tab_loading_frame_navigation_scheduler_unittest.cc",
     "owned_objects_unittest.cc",
     "performance_manager_impl_unittest.cc",
diff --git a/components/performance_manager/embedder/binders.cc b/components/performance_manager/binders.cc
similarity index 100%
rename from components/performance_manager/embedder/binders.cc
rename to components/performance_manager/binders.cc
diff --git a/components/performance_manager/decorators/freezing_vote_decorator.cc b/components/performance_manager/decorators/freezing_vote_decorator.cc
new file mode 100644
index 0000000..b314314e7
--- /dev/null
+++ b/components/performance_manager/decorators/freezing_vote_decorator.cc
@@ -0,0 +1,47 @@
+// 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 "components/performance_manager/decorators/freezing_vote_decorator.h"
+
+#include "base/optional.h"
+#include "components/performance_manager/graph/page_node_impl.h"
+
+namespace performance_manager {
+
+FreezingVoteDecorator::FreezingVoteDecorator() {
+  freezing_vote_aggregator_.SetUpstreamVotingChannel(
+      vote_consumer_default_impl_.BuildVotingChannel());
+}
+
+FreezingVoteDecorator::~FreezingVoteDecorator() = default;
+
+void FreezingVoteDecorator::OnPassedToGraph(Graph* graph) {
+  graph->RegisterObject(&freezing_vote_aggregator_);
+}
+
+void FreezingVoteDecorator::OnTakenFromGraph(Graph* graph) {
+  graph->UnregisterObject(&freezing_vote_aggregator_);
+}
+
+void FreezingVoteDecorator::OnVoteSubmitted(
+    freezing::FreezingVoterId voter_id,
+    const PageNode* page_node,
+    const freezing::FreezingVote& vote) {
+  PageNodeImpl::FromNode(page_node)->set_freezing_vote(vote);
+}
+
+void FreezingVoteDecorator::OnVoteChanged(
+    freezing::FreezingVoterId voter_id,
+    const PageNode* page_node,
+    const freezing::FreezingVote& new_vote) {
+  PageNodeImpl::FromNode(page_node)->set_freezing_vote(new_vote);
+}
+
+void FreezingVoteDecorator::OnVoteInvalidated(
+    freezing::FreezingVoterId voter_id,
+    const PageNode* page_node) {
+  PageNodeImpl::FromNode(page_node)->set_freezing_vote(base::nullopt);
+}
+
+}  // namespace performance_manager
\ No newline at end of file
diff --git a/components/performance_manager/decorators/freezing_vote_decorator.h b/components/performance_manager/decorators/freezing_vote_decorator.h
new file mode 100644
index 0000000..dc027b2
--- /dev/null
+++ b/components/performance_manager/decorators/freezing_vote_decorator.h
@@ -0,0 +1,62 @@
+// 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 COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FREEZING_VOTE_DECORATOR_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FREEZING_VOTE_DECORATOR_H_
+
+#include <memory>
+
+#include "components/performance_manager/freezing/freezing_vote_aggregator.h"
+#include "components/performance_manager/public/freezing/freezing.h"
+#include "components/performance_manager/public/graph/graph.h"
+
+namespace performance_manager {
+
+class PageNode;
+
+// Decorator that adorns PageNodes with a FreezingVote.
+//
+// This decorator owns a GraphRegistered FreezingVoteAggregator instance that
+// can be used to submit votes for a given PageNode. Components interested in
+// submitting a freezing vote should do the following:
+//   voting::VotingChannelWrapper<FreezingVote> voter;
+//   voter.SetVotingChannel(
+//      graph()->GetRegisteredObjectAs<freezing::FreezingVoteAggregator>()
+//          ->GetVotingChannel());
+//   voter.SubmitVote(page_node,
+//       FreezingVote(FreezingVoteValue::kCannotFreeze, "reason"));
+//
+// The aggregator is responsible for upstreaming the final vote to this
+// decorator.
+class FreezingVoteDecorator : public GraphOwnedDefaultImpl,
+                              public freezing::FreezingVoteObserver {
+ public:
+  FreezingVoteDecorator();
+  ~FreezingVoteDecorator() override;
+
+  FreezingVoteDecorator(const FreezingVoteDecorator&) = delete;
+  FreezingVoteDecorator& operator=(const FreezingVoteDecorator&) = delete;
+
+ private:
+  // GraphOwned:
+  void OnPassedToGraph(Graph* graph) override;
+  void OnTakenFromGraph(Graph* graph) override;
+
+  // FreezingVoteObserver implementation:
+  void OnVoteSubmitted(freezing::FreezingVoterId voter_id,
+                       const PageNode* page_node,
+                       const freezing::FreezingVote& vote) override;
+  void OnVoteChanged(freezing::FreezingVoterId voter_id,
+                     const PageNode* page_node,
+                     const freezing::FreezingVote& new_vote) override;
+  void OnVoteInvalidated(freezing::FreezingVoterId voter_id,
+                         const PageNode* page_node) override;
+
+  freezing::FreezingVoteConsumerDefaultImpl vote_consumer_default_impl_{this};
+  freezing::FreezingVoteAggregator freezing_vote_aggregator_;
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FREEZING_VOTE_DECORATOR_H_
diff --git a/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc b/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc
new file mode 100644
index 0000000..d416567
--- /dev/null
+++ b/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc
@@ -0,0 +1,60 @@
+// 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 "components/performance_manager/decorators/freezing_vote_decorator.h"
+
+#include "components/performance_manager/freezing/freezing_vote_aggregator.h"
+#include "components/performance_manager/graph/page_node_impl.h"
+#include "components/performance_manager/public/freezing/freezing.h"
+#include "components/performance_manager/test_support/graph_test_harness.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace performance_manager {
+
+namespace {
+static const freezing::FreezingVote kCannotFreezeVote(
+    freezing::FreezingVoteValue::kCannotFreeze,
+    "cannot freeze");
+static const freezing::FreezingVote kCanFreezeVote(
+    freezing::FreezingVoteValue::kCanFreeze,
+    "can freeze");
+}  // namespace
+
+class FreezingVoteDecoratorTest : public GraphTestHarness {
+ public:
+  FreezingVoteDecoratorTest() = default;
+  ~FreezingVoteDecoratorTest() override = default;
+
+  void SetUp() override {
+    graph()->PassToGraph(std::make_unique<FreezingVoteDecorator>());
+  }
+};
+
+TEST_F(FreezingVoteDecoratorTest, VotesAreForwarded) {
+  auto page_node = CreateNode<PageNodeImpl>();
+  EXPECT_FALSE(page_node->freezing_vote());
+
+  freezing::FreezingVotingChannelWrapper voter;
+  voter.SetVotingChannel(
+      graph()
+          ->GetRegisteredObjectAs<freezing::FreezingVoteAggregator>()
+          ->GetVotingChannel());
+
+  voter.SubmitVote(page_node.get(), kCannotFreezeVote);
+  ASSERT_TRUE(page_node->freezing_vote().has_value());
+  EXPECT_EQ(kCannotFreezeVote, page_node->freezing_vote().value());
+
+  voter.ChangeVote(page_node.get(), kCanFreezeVote);
+  ASSERT_TRUE(page_node->freezing_vote().has_value());
+  EXPECT_EQ(kCanFreezeVote, page_node->freezing_vote().value());
+
+  voter.ChangeVote(page_node.get(), kCannotFreezeVote);
+  ASSERT_TRUE(page_node->freezing_vote().has_value());
+  EXPECT_EQ(kCannotFreezeVote, page_node->freezing_vote().value());
+
+  voter.InvalidateVote(page_node.get());
+  EXPECT_FALSE(page_node->freezing_vote());
+}
+
+}  // namespace performance_manager
\ No newline at end of file
diff --git a/components/performance_manager/embedder/graph_features_helper.h b/components/performance_manager/embedder/graph_features_helper.h
new file mode 100644
index 0000000..a8c5ea4
--- /dev/null
+++ b/components/performance_manager/embedder/graph_features_helper.h
@@ -0,0 +1,137 @@
+// 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 COMPONENTS_PERFORMANCE_MANAGER_EMBEDDER_GRAPH_FEATURES_HELPER_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_EMBEDDER_GRAPH_FEATURES_HELPER_H_
+
+#include <cstdint>
+
+namespace performance_manager {
+
+class Graph;
+
+// A helper for configuring and enabling Graph features. This object is
+// constexpr so that it can be easily used with static storage without
+// requiring an initializer.
+class GraphFeaturesHelper {
+ public:
+  // Helper for housing the actual configuration data.
+  union Flags {
+    uint32_t flags;
+    struct {
+      // When adding new features here, the following also needs to happen:
+      // (1) Add a corresponding EnableFeatureFoo() member function.
+      // (2) Add the feature to EnableDefault() if necessary.
+      // (3) Add the feature to the implementation of ConfigureGraph().
+      bool execution_context_registry : 1;
+      bool frame_node_impl_describer : 1;
+      bool frame_visibility_decorator : 1;
+      bool page_live_state_decorator : 1;
+      bool page_load_tracker_decorator : 1;
+      bool page_node_impl_describer : 1;
+      bool process_node_impl_describer : 1;
+      bool site_data_recorder : 1;
+      bool tab_properties_decorator : 1;
+      bool v8_context_tracker : 1;
+      bool worker_node_impl_describer : 1;
+    };
+  };
+
+  constexpr GraphFeaturesHelper() = default;
+  constexpr GraphFeaturesHelper(const GraphFeaturesHelper& other) = default;
+  GraphFeaturesHelper& operator=(const GraphFeaturesHelper& other) = default;
+
+  constexpr GraphFeaturesHelper& EnableExecutionContextRegistry() {
+    flags_.execution_context_registry = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableFrameNodeImplDescriber() {
+    flags_.frame_node_impl_describer = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableFrameVisibilityDecorator() {
+    flags_.frame_visibility_decorator = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnablePageLiveStateDecorator() {
+    flags_.page_live_state_decorator = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnablePageLoadTrackerDecorator() {
+    flags_.page_load_tracker_decorator = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnablePageNodeImplDescriber() {
+    flags_.page_node_impl_describer = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableProcessNodeImplDescriber() {
+    flags_.process_node_impl_describer = true;
+    return *this;
+  }
+
+  // This is a nop on the Android platform, as the feature isn't available
+  // there.
+  constexpr GraphFeaturesHelper& EnableSiteDataRecorder() {
+    flags_.site_data_recorder = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableTabPropertiesDecorator() {
+    flags_.tab_properties_decorator = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableV8ContextTracker() {
+    EnableExecutionContextRegistry();
+    flags_.v8_context_tracker = true;
+    return *this;
+  }
+
+  constexpr GraphFeaturesHelper& EnableWorkerNodeImplDescriber() {
+    flags_.worker_node_impl_describer = true;
+    return *this;
+  }
+
+  // Helper to enable the default set of features. This is only intended for use
+  // from production code.
+  constexpr GraphFeaturesHelper& EnableDefault() {
+    EnableExecutionContextRegistry();
+    EnableFrameNodeImplDescriber();
+    EnableFrameVisibilityDecorator();
+    EnablePageLiveStateDecorator();
+    EnablePageLoadTrackerDecorator();
+    EnablePageNodeImplDescriber();
+    EnableProcessNodeImplDescriber();
+    EnableSiteDataRecorder();
+    EnableTabPropertiesDecorator();
+    EnableV8ContextTracker();
+    EnableWorkerNodeImplDescriber();
+    return *this;
+  }
+
+  // Accessor for the current set of flags_.
+  constexpr const Flags& flags() const { return flags_; }
+
+  // Applies the configuration specified on this object to the provided
+  // graph. This will unconditionally try to install all of the enabled
+  // features, even if they have already been installed; it is generally
+  // preferable to call this exactly once on a brand new |graph| instance that
+  // has had no features installed. Otherwise, it is safe to call this to
+  // install new features that the caller knows have not yet been installed.
+  void ConfigureGraph(Graph* graph) const;
+
+ private:
+  Flags flags_ = {0};
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_EMBEDDER_GRAPH_FEATURES_HELPER_H_
diff --git a/components/performance_manager/freezing/freezing_vote_aggregator.h b/components/performance_manager/freezing/freezing_vote_aggregator.h
index c30548f..5050695 100644
--- a/components/performance_manager/freezing/freezing_vote_aggregator.h
+++ b/components/performance_manager/freezing/freezing_vote_aggregator.h
@@ -8,27 +8,18 @@
 #include "base/compiler_specific.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/flat_map.h"
+#include "components/performance_manager/public/freezing/freezing.h"
+#include "components/performance_manager/public/graph/graph_registered.h"
 #include "components/performance_manager/public/voting/voting.h"
 
 namespace performance_manager {
 
+class FreezingVoteDecorator;
 class PageNode;
 
 namespace freezing {
 
-enum class FreezingVoteValue {
-  kCannotFreeze,
-  kCanFreeze,
-};
-
-using FreezingVote =
-    voting::Vote<PageNode, FreezingVoteValue, FreezingVoteValue::kCannotFreeze>;
-using FreezingVoterId = voting::VoterId<FreezingVote>;
 using FreezingVoteReceipt = voting::VoteReceipt<FreezingVote>;
-using FreezingVotingChannel = voting::VotingChannel<FreezingVote>;
-using FreezingVoteObserver = voting::VoteObserver<FreezingVote>;
-using FreezingVoteConsumerDefaultImpl =
-    voting::VoteConsumerDefaultImpl<FreezingVote>;
 using FreezingVotingChannelWrapper = voting::VotingChannelWrapper<FreezingVote>;
 
 // An aggregator for freezing votes. It upstreams an aggregated vote to an
@@ -37,9 +28,14 @@
 // kCanFreeze vote for this node. Any kCannotFreeze vote received will have
 // priority over the kCanFreeze votes and will prevent the PageNode from being
 // frozen.
-class FreezingVoteAggregator final : public FreezingVoteObserver {
+//
+// This is a GraphRegistered object, once created this instance can be
+// retrieved via:
+//     graph()->GetRegisteredObjectAs<freezing::FreezingVoteAggregator>();
+class FreezingVoteAggregator final
+    : public FreezingVoteObserver,
+      public GraphRegisteredImpl<FreezingVoteAggregator> {
  public:
-  FreezingVoteAggregator();
   FreezingVoteAggregator(const FreezingVoteAggregator& rhs) = delete;
   FreezingVoteAggregator& operator=(const FreezingVoteAggregator& rhs) = delete;
   ~FreezingVoteAggregator() override;
@@ -61,8 +57,14 @@
                          const PageNode* page_node) override;
 
  private:
+  friend class performance_manager::FreezingVoteDecorator;
+  friend class FreezingVoteAggregatorTest;
   friend class FreezingVoteAggregatorTestAccess;
 
+  // Private constructor, in practice the FreezingVoteDecorator is responsible
+  // for maintaining the lifetime of this object.
+  FreezingVoteAggregator();
+
   // Contains the freezing votes for a given PageNode.
   class FreezingVoteData {
    public:
diff --git a/components/performance_manager/graph/graph_impl.cc b/components/performance_manager/graph/graph_impl.cc
index 2eaf547..1ca7119 100644
--- a/components/performance_manager/graph/graph_impl.cc
+++ b/components/performance_manager/graph/graph_impl.cc
@@ -63,12 +63,14 @@
  public:
   ~NodeDataDescriberRegistryImpl() override;
 
+  // NodeDataDescriberRegistry impl:
   void RegisterDescriber(const NodeDataDescriber* describer,
                          base::StringPiece name) override;
   void UnregisterDescriber(const NodeDataDescriber* describer) override;
-
   base::Value DescribeNodeData(const Node* node) const override;
 
+  size_t size() const { return describers_.size(); }
+
  private:
   template <typename NodeType, typename NodeImplType>
   base::Value DescribeNodeImpl(
@@ -540,6 +542,14 @@
   DCHECK_EQ(1u, erased);
 }
 
+size_t GraphImpl::NodeDataDescriberCountForTesting() const {
+  if (!describer_registry_)
+    return 0;
+  auto* registry = static_cast<const NodeDataDescriberRegistryImpl*>(
+      describer_registry_.get());
+  return registry->size();
+}
+
 void GraphImpl::BeforeProcessPidChange(ProcessNodeImpl* process,
                                        base::ProcessId new_pid) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/performance_manager/graph/graph_impl.h b/components/performance_manager/graph/graph_impl.h
index 1f42085..72b3d496 100644
--- a/components/performance_manager/graph/graph_impl.h
+++ b/components/performance_manager/graph/graph_impl.h
@@ -130,6 +130,14 @@
   // Returns the number of objects in the |graph_owned_| map, for testing.
   size_t GraphOwnedCountForTesting() const { return graph_owned_.size(); }
 
+  // Returns the number of GraphRegistered objects, for testing.
+  size_t GraphRegisteredCountForTesting() const {
+    return registered_objects_.size();
+  }
+
+  // Returns the number of registered NodeDataDescribers, for testing.
+  size_t NodeDataDescriberCountForTesting() const;
+
  protected:
   friend class NodeBase;
 
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index 47693cc..e8352a8 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -241,6 +241,12 @@
   return had_form_interaction_.value();
 }
 
+const base::Optional<freezing::FreezingVote>& PageNodeImpl::freezing_vote()
+    const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return freezing_vote_.value();
+}
+
 void PageNodeImpl::SetOpenerFrameNodeAndOpenedType(FrameNodeImpl* opener,
                                                    OpenedType opened_type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -296,6 +302,12 @@
   has_nonempty_beforeunload_ = has_nonempty_beforeunload;
 }
 
+void PageNodeImpl::set_freezing_vote(
+    base::Optional<freezing::FreezingVote> freezing_vote) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  freezing_vote_.SetAndMaybeNotify(this, freezing_vote);
+}
+
 void PageNodeImpl::OnJoiningGraph() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #if DCHECK_IS_ON()
@@ -421,6 +433,12 @@
   return contents_proxy();
 }
 
+const base::Optional<freezing::FreezingVote>& PageNodeImpl::GetFreezingVote()
+    const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return freezing_vote();
+}
+
 void PageNodeImpl::SetLifecycleState(LifecycleState lifecycle_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   lifecycle_state_.SetAndMaybeNotify(this, lifecycle_state);
diff --git a/components/performance_manager/graph/page_node_impl.h b/components/performance_manager/graph/page_node_impl.h
index 799aa86..7242e1ae 100644
--- a/components/performance_manager/graph/page_node_impl.h
+++ b/components/performance_manager/graph/page_node_impl.h
@@ -12,10 +12,12 @@
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "base/types/pass_key.h"
 #include "components/performance_manager/graph/node_attached_data.h"
 #include "components/performance_manager/graph/node_base.h"
+#include "components/performance_manager/public/freezing/freezing.h"
 #include "components/performance_manager/public/graph/page_node.h"
 #include "components/performance_manager/public/web_contents_proxy.h"
 #include "url/gurl.h"
@@ -97,6 +99,7 @@
   int64_t navigation_id() const;
   const std::string& contents_mime_type() const;
   bool had_form_interaction() const;
+  const base::Optional<freezing::FreezingVote>& freezing_vote() const;
 
   // Invoked to set/clear the opener of this page.
   void SetOpenerFrameNodeAndOpenedType(FrameNodeImpl* opener,
@@ -107,6 +110,7 @@
   void set_private_footprint_kb_estimate(
       uint64_t private_footprint_kb_estimate);
   void set_has_nonempty_beforeunload(bool has_nonempty_beforeunload);
+  void set_freezing_vote(base::Optional<freezing::FreezingVote> freezing_vote);
 
   void SetLifecycleStateForTesting(LifecycleState lifecycle_state) {
     SetLifecycleState(lifecycle_state);
@@ -190,6 +194,8 @@
   const GURL& GetMainFrameUrl() const override;
   bool HadFormInteraction() const override;
   const WebContentsProxy& GetContentsProxy() const override;
+  const base::Optional<freezing::FreezingVote>& GetFreezingVote()
+      const override;
 
   // NodeBase:
   void OnJoiningGraph() override;
@@ -297,6 +303,13 @@
       bool,
       &PageNodeObserver::OnHadFormInteractionChanged>
       had_form_interaction_{false};
+  // The freezing vote associated with this page, see the comment of to
+  // Page::GetFreezingVote for a description of the different values this can
+  // take.
+  ObservedProperty::NotifiesOnlyOnChanges<
+      base::Optional<freezing::FreezingVote>,
+      &PageNodeObserver::OnFreezingVoteChanged>
+      freezing_vote_;
 
   // Storage for PageLoadTracker user data.
   std::unique_ptr<NodeAttachedData> page_load_tracker_data_;
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc
index 1fc30d5..050c4c2 100644
--- a/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -4,10 +4,12 @@
 
 #include "components/performance_manager/graph/page_node_impl.h"
 
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "components/performance_manager/graph/frame_node_impl.h"
 #include "components/performance_manager/graph/graph_impl_operations.h"
 #include "components/performance_manager/graph/process_node_impl.h"
+#include "components/performance_manager/public/freezing/freezing.h"
 #include "components/performance_manager/public/graph/page_node.h"
 #include "components/performance_manager/test_support/graph_test_harness.h"
 #include "components/performance_manager/test_support/mock_graphs.h"
@@ -23,6 +25,10 @@
 const std::string kHtmlMimeType = "text/html";
 const std::string kPdfMimeType = "application/pdf";
 
+static const freezing::FreezingVote kFreezingVote(
+    freezing::FreezingVoteValue::kCannotFreeze,
+    "cannot freeze");
+
 const PageNode* ToPublic(PageNodeImpl* page_node) {
   return page_node;
 }
@@ -192,6 +198,21 @@
   EXPECT_FALSE(page_node->had_form_interaction());
 }
 
+TEST_F(PageNodeImplTest, GetFreezingVote) {
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  auto* page_node = mock_graph.page.get();
+
+  // This should be initialized to base::nullopt.
+  EXPECT_FALSE(page_node->freezing_vote());
+
+  page_node->set_freezing_vote(kFreezingVote);
+  ASSERT_TRUE(page_node->freezing_vote().has_value());
+  EXPECT_EQ(kFreezingVote, page_node->freezing_vote().value());
+
+  page_node->set_freezing_vote(base::nullopt);
+  EXPECT_FALSE(page_node->freezing_vote());
+}
+
 namespace {
 
 class LenientMockObserver : public PageNodeImpl::Observer {
@@ -217,6 +238,7 @@
   MOCK_METHOD1(OnTitleUpdated, void(const PageNode*));
   MOCK_METHOD1(OnFaviconUpdated, void(const PageNode*));
   MOCK_METHOD1(OnHadFormInteractionChanged, void(const PageNode*));
+  MOCK_METHOD1(OnFreezingVoteChanged, void(const PageNode*));
 
   void SetNotifiedPageNode(const PageNode* page_node) {
     notified_page_node_ = page_node;
@@ -302,6 +324,11 @@
   page_node->OnFaviconUpdated();
   EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
 
+  EXPECT_CALL(obs, OnFreezingVoteChanged(_))
+      .WillOnce(Invoke(&obs, &MockObserver::SetNotifiedPageNode));
+  page_node->set_freezing_vote(kFreezingVote);
+  EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
+
   // Release the page node and expect a call to "OnBeforePageNodeRemoved".
   EXPECT_CALL(obs, OnBeforePageNodeRemoved(_))
       .WillOnce(Invoke(&obs, &MockObserver::SetNotifiedPageNode));
@@ -334,6 +361,7 @@
   EXPECT_EQ(page_node->main_frame_url(), public_page_node->GetMainFrameUrl());
   EXPECT_EQ(page_node->contents_mime_type(),
             public_page_node->GetContentsMimeType());
+  EXPECT_EQ(page_node->freezing_vote(), public_page_node->GetFreezingVote());
 }
 
 TEST_F(PageNodeImplTest, GetMainFrameNodes) {
diff --git a/components/performance_manager/graph_features_helper.cc b/components/performance_manager/graph_features_helper.cc
new file mode 100644
index 0000000..37691c2
--- /dev/null
+++ b/components/performance_manager/graph_features_helper.cc
@@ -0,0 +1,68 @@
+// 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 "components/performance_manager/embedder/graph_features_helper.h"
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "components/performance_manager/decorators/frame_visibility_decorator.h"
+#include "components/performance_manager/decorators/page_load_tracker_decorator.h"
+#include "components/performance_manager/execution_context/execution_context_registry_impl.h"
+#include "components/performance_manager/graph/frame_node_impl_describer.h"
+#include "components/performance_manager/graph/page_node_impl_describer.h"
+#include "components/performance_manager/graph/process_node_impl_describer.h"
+#include "components/performance_manager/graph/worker_node_impl_describer.h"
+#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
+#include "components/performance_manager/public/decorators/tab_properties_decorator.h"
+#include "components/performance_manager/public/graph/graph.h"
+#include "components/performance_manager/v8_memory/v8_context_tracker.h"
+
+#if !defined(OS_ANDROID)
+#include "components/performance_manager/public/decorators/site_data_recorder.h"
+#endif
+
+namespace performance_manager {
+
+namespace {
+
+template <typename ObjectType>
+void Install(Graph* graph) {
+  graph->PassToGraph(std::make_unique<ObjectType>());
+}
+
+}  // namespace
+
+void GraphFeaturesHelper::ConfigureGraph(Graph* graph) const {
+  if (flags_.execution_context_registry)
+    Install<execution_context::ExecutionContextRegistryImpl>(graph);
+  if (flags_.frame_node_impl_describer)
+    Install<FrameNodeImplDescriber>(graph);
+  if (flags_.frame_visibility_decorator)
+    Install<FrameVisibilityDecorator>(graph);
+  if (flags_.page_live_state_decorator)
+    Install<PageLiveStateDecorator>(graph);
+  if (flags_.page_load_tracker_decorator)
+    Install<PageLoadTrackerDecorator>(graph);
+  if (flags_.page_node_impl_describer)
+    Install<PageNodeImplDescriber>(graph);
+  if (flags_.process_node_impl_describer)
+    Install<ProcessNodeImplDescriber>(graph);
+  if (flags_.tab_properties_decorator)
+    Install<TabPropertiesDecorator>(graph);
+  if (flags_.worker_node_impl_describer)
+    Install<WorkerNodeImplDescriber>(graph);
+
+#if !defined(OS_ANDROID)
+  if (flags_.site_data_recorder)
+    Install<SiteDataRecorder>(graph);
+#endif
+
+  // This class has a dependency on ExecutionContextRegistry, so must be
+  // installed after it.
+  if (flags_.v8_context_tracker)
+    Install<v8_memory::V8ContextTracker>(graph);
+}
+
+}  // namespace performance_manager
\ No newline at end of file
diff --git a/components/performance_manager/graph_features_helper_unittest.cc b/components/performance_manager/graph_features_helper_unittest.cc
new file mode 100644
index 0000000..da31609
--- /dev/null
+++ b/components/performance_manager/graph_features_helper_unittest.cc
@@ -0,0 +1,72 @@
+// 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 "components/performance_manager/embedder/graph_features_helper.h"
+
+#include "build/build_config.h"
+#include "components/performance_manager/public/execution_context/execution_context_registry.h"
+#include "components/performance_manager/test_support/graph_test_harness.h"
+#include "components/performance_manager/v8_memory/v8_context_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace performance_manager {
+
+TEST(GraphFeaturesHelperTest, ConfigureGraph) {
+  GraphFeaturesHelper features;
+
+  EXPECT_FALSE(features.flags().execution_context_registry);
+  EXPECT_FALSE(features.flags().v8_context_tracker);
+  features.EnableV8ContextTracker();
+  EXPECT_TRUE(features.flags().execution_context_registry);
+  EXPECT_TRUE(features.flags().v8_context_tracker);
+
+  TestGraphImpl graph;
+  EXPECT_FALSE(v8_memory::V8ContextTracker::GetFromGraph(&graph));
+  features.ConfigureGraph(&graph);
+  EXPECT_TRUE(v8_memory::V8ContextTracker::GetFromGraph(&graph));
+
+  graph.TearDown();
+}
+
+TEST(GraphFeaturesHelperTest, EnableDefault) {
+  GraphFeaturesHelper features;
+  TestGraphImpl graph;
+
+  EXPECT_EQ(0u, graph.GraphOwnedCountForTesting());
+  EXPECT_EQ(0u, graph.GraphRegisteredCountForTesting());
+  EXPECT_EQ(0u, graph.NodeDataDescriberCountForTesting());
+  EXPECT_FALSE(
+      execution_context::ExecutionContextRegistry::GetFromGraph(&graph));
+  EXPECT_FALSE(v8_memory::V8ContextTracker::GetFromGraph(&graph));
+
+  // An empty config should install nothing.
+  features.ConfigureGraph(&graph);
+  EXPECT_EQ(0u, graph.GraphOwnedCountForTesting());
+  EXPECT_EQ(0u, graph.GraphRegisteredCountForTesting());
+  EXPECT_EQ(0u, graph.NodeDataDescriberCountForTesting());
+  EXPECT_FALSE(
+      execution_context::ExecutionContextRegistry::GetFromGraph(&graph));
+  EXPECT_FALSE(v8_memory::V8ContextTracker::GetFromGraph(&graph));
+
+  size_t graph_owned_count = 10;
+#if !defined(OS_ANDROID)
+  // The SiteDataRecorder is not available on Android.
+  graph_owned_count++;
+#endif
+
+  // Validate that the default configuration works as expected.
+  features.EnableDefault();
+  features.ConfigureGraph(&graph);
+  EXPECT_EQ(graph_owned_count, graph.GraphOwnedCountForTesting());
+  EXPECT_EQ(2u, graph.GraphRegisteredCountForTesting());
+  EXPECT_EQ(8u, graph.NodeDataDescriberCountForTesting());
+  // Ensure the GraphRegistered objects can be queried directly.
+  EXPECT_TRUE(
+      execution_context::ExecutionContextRegistry::GetFromGraph(&graph));
+  EXPECT_TRUE(v8_memory::V8ContextTracker::GetFromGraph(&graph));
+
+  graph.TearDown();
+}
+
+}  // namespace performance_manager
diff --git a/components/performance_manager/performance_manager_lifetime.cc b/components/performance_manager/performance_manager_lifetime.cc
index fb5ffb08..9d2123f 100644
--- a/components/performance_manager/performance_manager_lifetime.cc
+++ b/components/performance_manager/performance_manager_lifetime.cc
@@ -10,6 +10,7 @@
 #include "build/build_config.h"
 #include "components/performance_manager/decorators/frame_visibility_decorator.h"
 #include "components/performance_manager/decorators/page_load_tracker_decorator.h"
+#include "components/performance_manager/embedder/graph_features_helper.h"
 #include "components/performance_manager/execution_context/execution_context_registry_impl.h"
 #include "components/performance_manager/graph/frame_node_impl_describer.h"
 #include "components/performance_manager/graph/page_node_impl_describer.h"
@@ -38,22 +39,9 @@
 void DefaultGraphCreatedCallback(
     GraphCreatedCallback external_graph_created_callback,
     GraphImpl* graph) {
-  graph->PassToGraph(
-      std::make_unique<execution_context::ExecutionContextRegistryImpl>());
-  graph->PassToGraph(std::make_unique<FrameNodeImplDescriber>());
-  graph->PassToGraph(std::make_unique<FrameVisibilityDecorator>());
-  graph->PassToGraph(std::make_unique<PageLiveStateDecorator>());
-  graph->PassToGraph(std::make_unique<PageLoadTrackerDecorator>());
-  graph->PassToGraph(std::make_unique<PageNodeImplDescriber>());
-  graph->PassToGraph(std::make_unique<ProcessNodeImplDescriber>());
-  graph->PassToGraph(std::make_unique<TabPropertiesDecorator>());
-  graph->PassToGraph(std::make_unique<WorkerNodeImplDescriber>());
-#if !defined(OS_ANDROID)
-  graph->PassToGraph(std::make_unique<SiteDataRecorder>());
-#endif
-
-  // This depends on ExecutionContextRegistry, so must be added afterwards.
-  graph->PassToGraph(std::make_unique<v8_memory::V8ContextTracker>());
+  GraphFeaturesHelper features_helper;
+  features_helper.EnableDefault();
+  features_helper.ConfigureGraph(graph);
 
   // Run graph created callbacks.
   std::move(external_graph_created_callback).Run(graph);
diff --git a/components/performance_manager/public/freezing/freezing.h b/components/performance_manager/public/freezing/freezing.h
new file mode 100644
index 0000000..0b62e80
--- /dev/null
+++ b/components/performance_manager/public/freezing/freezing.h
@@ -0,0 +1,35 @@
+// 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.
+//
+// This header contains some definition for some types used by the page freezing
+// logic.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_FREEZING_FREEZING_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_FREEZING_FREEZING_H_
+
+#include "components/performance_manager/public/voting/voting.h"
+
+namespace performance_manager {
+
+class PageNode;
+
+namespace freezing {
+
+enum class FreezingVoteValue {
+  kCannotFreeze,
+  kCanFreeze,
+};
+
+using FreezingVote =
+    voting::Vote<PageNode, FreezingVoteValue, FreezingVoteValue::kCannotFreeze>;
+using FreezingVoterId = voting::VoterId<FreezingVote>;
+using FreezingVoteObserver = voting::VoteObserver<FreezingVote>;
+using FreezingVotingChannel = voting::VotingChannel<FreezingVote>;
+using FreezingVoteConsumerDefaultImpl =
+    voting::VoteConsumerDefaultImpl<FreezingVote>;
+
+}  // namespace freezing
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_FREEZING_FREEZING_H_
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
index e64414e4..4ceace3 100644
--- a/components/performance_manager/public/graph/page_node.h
+++ b/components/performance_manager/public/graph/page_node.h
@@ -10,6 +10,8 @@
 
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
+#include "base/optional.h"
+#include "components/performance_manager/public/freezing/freezing.h"
 #include "components/performance_manager/public/graph/node.h"
 #include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
 #include "components/performance_manager/public/mojom/lifecycle.mojom.h"
@@ -145,6 +147,16 @@
   // dereferenced on the UI thread.
   virtual const WebContentsProxy& GetContentsProxy() const = 0;
 
+  // Indicates if there's a freezing vote for this page node. This has 3
+  // possible values:
+  //   - base::nullopt: There's no active freezing vote for this page.
+  //   - freezing::FreezingVoteValue::kCanFreeze: There's one or more positive
+  //     freezing vote for this page and no negative vote.
+  //   - freezing::FreezingVoteValue::kCannotFreeze: There's at least one
+  //     negative freezing vote for this page.
+  virtual const base::Optional<freezing::FreezingVote>& GetFreezingVote()
+      const = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(PageNode);
 };
@@ -219,6 +231,9 @@
   // not directly reflected on the node.
   virtual void OnFaviconUpdated(const PageNode* page_node) = 0;
 
+  // Called every time the aggregated freezing vote changes or gets invalidated.
+  virtual void OnFreezingVoteChanged(const PageNode* page_node) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(PageNodeObserver);
 };
@@ -250,6 +265,7 @@
   void OnHadFormInteractionChanged(const PageNode* page_node) override {}
   void OnTitleUpdated(const PageNode* page_node) override {}
   void OnFaviconUpdated(const PageNode* page_node) override {}
+  void OnFreezingVoteChanged(const PageNode* page_node) override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
diff --git a/components/prefs/json_pref_store.cc b/components/prefs/json_pref_store.cc
index 97fe935..2948e67 100644
--- a/components/prefs/json_pref_store.cc
+++ b/components/prefs/json_pref_store.cc
@@ -34,21 +34,17 @@
  public:
   ReadResult();
   ~ReadResult();
+  ReadResult(const ReadResult&) = delete;
+  ReadResult& operator=(const ReadResult&) = delete;
 
   std::unique_ptr<base::Value> value;
-  PrefReadError error;
-  bool no_dir;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ReadResult);
+  PrefReadError error = PersistentPrefStore::PREF_READ_ERROR_NONE;
+  bool no_dir = false;
+  size_t num_bytes_read = 0u;
 };
 
-JsonPrefStore::ReadResult::ReadResult()
-    : error(PersistentPrefStore::PREF_READ_ERROR_NONE), no_dir(false) {
-}
-
-JsonPrefStore::ReadResult::~ReadResult() {
-}
+JsonPrefStore::ReadResult::ReadResult() = default;
+JsonPrefStore::ReadResult::~ReadResult() = default;
 
 namespace {
 
@@ -121,13 +117,13 @@
     const base::FilePath& path) {
   int error_code;
   std::string error_msg;
-  std::unique_ptr<JsonPrefStore::ReadResult> read_result(
-      new JsonPrefStore::ReadResult);
+  auto read_result = std::make_unique<JsonPrefStore::ReadResult>();
   JSONFileValueDeserializer deserializer(path);
   read_result->value = deserializer.Deserialize(&error_code, &error_msg);
   read_result->error =
       HandleReadErrors(read_result->value.get(), path, error_code, error_msg);
   read_result->no_dir = !base::PathExists(path.DirName());
+  read_result->num_bytes_read = deserializer.get_last_read_size();
 
   if (read_result->error == PersistentPrefStore::PREF_READ_ERROR_NONE)
     RecordJsonDataSizeHistogram(path, deserializer.get_last_read_size());
@@ -413,8 +409,7 @@
 
   DCHECK(read_result);
 
-  std::unique_ptr<base::DictionaryValue> unfiltered_prefs(
-      new base::DictionaryValue);
+  auto unfiltered_prefs = std::make_unique<base::DictionaryValue>();
 
   read_error_ = read_result->error;
 
@@ -431,6 +426,7 @@
         break;
       case PREF_READ_ERROR_NONE:
         DCHECK(read_result->value);
+        writer_.set_previous_data_size(read_result->num_bytes_read);
         unfiltered_prefs.reset(
             static_cast<base::DictionaryValue*>(read_result->value.release()));
         break;
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h
index 78f7d6e..c3d6b60 100644
--- a/components/prefs/json_pref_store.h
+++ b/components/prefs/json_pref_store.h
@@ -122,6 +122,10 @@
 
   void OnStoreDeletionFromDisk() override;
 
+#if defined(UNIT_TEST)
+  base::ImportantFileWriter& get_writer() { return writer_; }
+#endif
+
  private:
   friend class base::JsonPrefStoreCallbackTest;
   friend class base::JsonPrefStoreLossyWriteTest;
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc
index 21ee0e2..58c0fd0 100644
--- a/components/prefs/json_pref_store_unittest.cc
+++ b/components/prefs/json_pref_store_unittest.cc
@@ -201,6 +201,7 @@
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
             pref_store->ReadPrefs());
   EXPECT_FALSE(pref_store->ReadOnly());
+  EXPECT_EQ(0u, pref_store->get_writer().previous_data_size());
 }
 
 // Test fallback behavior for an invalid file.
@@ -310,6 +311,7 @@
   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
   EXPECT_FALSE(pref_store->ReadOnly());
   EXPECT_TRUE(pref_store->IsInitializationComplete());
+  EXPECT_GT(pref_store->get_writer().previous_data_size(), 0u);
 
   // The JSON file looks like this:
   // {
@@ -348,6 +350,7 @@
 
     EXPECT_FALSE(pref_store->ReadOnly());
     EXPECT_TRUE(pref_store->IsInitializationComplete());
+    EXPECT_GT(pref_store->get_writer().previous_data_size(), 0u);
   }
 
   // The JSON file looks like this:
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 5675cc8..07be91e 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -39,6 +39,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/log/net_log_util.h"
 #include "services/cert_verifier/cert_verifier_service_factory.h"
+#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/network_switches.h"
@@ -506,6 +507,9 @@
 
 namespace {
 
+cert_verifier::mojom::CertVerifierServiceFactory*
+    g_cert_verifier_service_factory_for_testing = nullptr;
+
 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
 GetNewCertVerifierServiceRemote(
     cert_verifier::mojom::CertVerifierServiceFactory*
@@ -519,68 +523,60 @@
   return cert_verifier_remote;
 }
 
-void CreateInProcessCertVerifierServiceOnThread(
+void RunInProcessCertVerifierServiceFactory(
     mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory>
         receiver) {
-  // Except in tests, our CertVerifierServiceFactoryImpl is a singleton.
-  static base::NoDestructor<cert_verifier::CertVerifierServiceFactoryImpl>
-      cv_service_factory(std::move(receiver));
+#if defined(OS_CHROMEOS)
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
+         BrowserThread::CurrentlyOn(BrowserThread::IO));
+#else
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
+         BrowserThread::CurrentlyOn(BrowserThread::UI));
+#endif
+  static base::NoDestructor<base::SequenceLocalStorageSlot<
+      std::unique_ptr<cert_verifier::CertVerifierServiceFactoryImpl>>>
+      service_factory_slot;
+  service_factory_slot->GetOrCreateValue() =
+      std::make_unique<cert_verifier::CertVerifierServiceFactoryImpl>(
+          std::move(receiver));
 }
 
 // Owns the CertVerifierServiceFactory used by the browser.
 // Lives on the UI thread.
-class CertVerifierServiceFactoryOwner {
- public:
-  CertVerifierServiceFactoryOwner() = default;
-  CertVerifierServiceFactoryOwner(const CertVerifierServiceFactoryOwner&) =
-      delete;
-  CertVerifierServiceFactoryOwner& operator=(
-      const CertVerifierServiceFactoryOwner&) = delete;
-  ~CertVerifierServiceFactoryOwner() = delete;
+mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
+GetCertVerifierServiceFactoryRemoteStorage() {
+  static base::NoDestructor<base::SequenceLocalStorageSlot<
+      mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>>>
+      cert_verifier_service_factory_remote;
+  return cert_verifier_service_factory_remote->GetOrCreateValue();
+}
 
-  static CertVerifierServiceFactoryOwner* Get() {
-    static base::NoDestructor<CertVerifierServiceFactoryOwner>
-        cert_verifier_service_factory_owner;
-    return &*cert_verifier_service_factory_owner;
-  }
+// Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
+cert_verifier::mojom::CertVerifierServiceFactory*
+GetCertVerifierServiceFactory() {
+  if (g_cert_verifier_service_factory_for_testing)
+    return g_cert_verifier_service_factory_for_testing;
 
-  // Passing nullptr will reset the current remote.
-  void SetCertVerifierServiceFactoryForTesting(
-      cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
-    if (service_factory) {
-      DCHECK(!service_factory_);
-    }
-    service_factory_ = service_factory;
-    service_factory_remote_.reset();
-  }
-
-  // Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
-  cert_verifier::mojom::CertVerifierServiceFactory*
-  GetCertVerifierServiceFactory() {
-    if (!service_factory_) {
+  mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
+      factory_remote_storage = GetCertVerifierServiceFactoryRemoteStorage();
+  if (!factory_remote_storage.is_bound() ||
+      !factory_remote_storage.is_connected()) {
+    factory_remote_storage.reset();
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-      // ChromeOS's in-process CertVerifierService should run on the IO thread
-      // because it interacts with IO-bound NSS and ChromeOS user slots.
-      // See for example InitializeNSSForChromeOSUser().
-      GetIOThreadTaskRunner({})->PostTask(
-          FROM_HERE,
-          base::BindOnce(&CreateInProcessCertVerifierServiceOnThread,
-                         service_factory_remote_.BindNewPipeAndPassReceiver()));
+    // ChromeOS's in-process CertVerifierService should run on the IO thread
+    // because it interacts with IO-bound NSS and ChromeOS user slots.
+    // See for example InitializeNSSForChromeOSUser().
+    GetIOThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RunInProcessCertVerifierServiceFactory,
+                       factory_remote_storage.BindNewPipeAndPassReceiver()));
 #else
-      CreateInProcessCertVerifierServiceOnThread(
-          service_factory_remote_.BindNewPipeAndPassReceiver());
+    RunInProcessCertVerifierServiceFactory(
+        factory_remote_storage.BindNewPipeAndPassReceiver());
 #endif
-      service_factory_ = service_factory_remote_.get();
-    }
-    return service_factory_;
   }
-
- private:
-  // Bound to UI thread.
-  mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>
-      service_factory_remote_;
-  cert_verifier::mojom::CertVerifierServiceFactory* service_factory_ = nullptr;
-};
+  return factory_remote_storage.get();
+}
 
 }  // namespace
 
@@ -596,10 +592,9 @@
       network::mojom::CertVerifierServiceRemoteParams::New();
 
   // Create a cert verifier service.
-  cv_service_remote_params
-      ->cert_verifier_service = GetNewCertVerifierServiceRemote(
-      CertVerifierServiceFactoryOwner::Get()->GetCertVerifierServiceFactory(),
-      std::move(cert_verifier_creation_params));
+  cv_service_remote_params->cert_verifier_service =
+      GetNewCertVerifierServiceRemote(GetCertVerifierServiceFactory(),
+                                      std::move(cert_verifier_creation_params));
 
   return network::mojom::CertVerifierParams::NewRemoteParams(
       std::move(cv_service_remote_params));
@@ -607,8 +602,7 @@
 
 void SetCertVerifierServiceFactoryForTesting(
     cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
-  CertVerifierServiceFactoryOwner::Get()
-      ->SetCertVerifierServiceFactoryForTesting(service_factory);
+  g_cert_verifier_service_factory_for_testing = service_factory;
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc
index f0fe587..0196d04 100644
--- a/content/browser/service_worker/service_worker_registry.cc
+++ b/content/browser/service_worker/service_worker_registry.cc
@@ -537,10 +537,12 @@
 void ServiceWorkerRegistry::StoreUncommittedResourceId(int64_t resource_id,
                                                        const GURL& origin) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  GetRemoteStorageControl()->StoreUncommittedResourceId(
-      resource_id, origin,
-      base::BindOnce(&ServiceWorkerRegistry::DidWriteUncommittedResourceIds,
-                     weak_factory_.GetWeakPtr()));
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::StoreUncommittedResourceId,
+      base::BindRepeating(
+          &ServiceWorkerRegistry::DidWriteUncommittedResourceIds,
+          weak_factory_.GetWeakPtr()),
+      static_cast<const int64_t>(resource_id), origin);
 }
 
 void ServiceWorkerRegistry::DoomUncommittedResource(int64_t resource_id) {
@@ -729,11 +731,12 @@
     return;
   }
 
-  GetRemoteStorageControl()->FindRegistrationForId(
-      registration_id, origin,
-      base::BindOnce(&ServiceWorkerRegistry::DidFindRegistrationForId,
-                     weak_factory_.GetWeakPtr(), registration_id,
-                     std::move(callback)));
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::FindRegistrationForId,
+      base::BindRepeating(&ServiceWorkerRegistry::DidFindRegistrationForId,
+                          weak_factory_.GetWeakPtr(), registration_id,
+                          base::Passed(&callback)),
+      static_cast<const int64_t>(registration_id), origin);
 }
 
 ServiceWorkerRegistration*
@@ -855,10 +858,11 @@
 void ServiceWorkerRegistry::DoomUncommittedResources(
     const std::vector<int64_t>& resource_ids) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  GetRemoteStorageControl()->DoomUncommittedResources(
-      resource_ids,
-      base::BindOnce(&ServiceWorkerRegistry::DidDoomUncommittedResourceIds,
-                     weak_factory_.GetWeakPtr()));
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::DoomUncommittedResources,
+      base::BindRepeating(&ServiceWorkerRegistry::DidDoomUncommittedResourceIds,
+                          weak_factory_.GetWeakPtr()),
+      resource_ids);
 }
 
 void ServiceWorkerRegistry::DidFindRegistrationForClientUrl(
@@ -949,9 +953,11 @@
 void ServiceWorkerRegistry::DidFindRegistrationForId(
     int64_t registration_id,
     FindRegistrationCallback callback,
+    uint64_t call_id,
     storage::mojom::ServiceWorkerDatabaseStatus database_status,
     storage::mojom::ServiceWorkerFindRegistrationResultPtr result) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
   if (database_status != storage::mojom::ServiceWorkerDatabaseStatus::kOk &&
       database_status !=
           storage::mojom::ServiceWorkerDatabaseStatus::kErrorNotFound) {
@@ -1221,13 +1227,19 @@
 }
 
 void ServiceWorkerRegistry::DidWriteUncommittedResourceIds(
+    uint64_t call_id,
     storage::mojom::ServiceWorkerDatabaseStatus status) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
   if (status != storage::mojom::ServiceWorkerDatabaseStatus::kOk)
     ScheduleDeleteAndStartOver();
 }
 
 void ServiceWorkerRegistry::DidDoomUncommittedResourceIds(
+    uint64_t call_id,
     storage::mojom::ServiceWorkerDatabaseStatus status) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
   if (status != storage::mojom::ServiceWorkerDatabaseStatus::kOk)
     ScheduleDeleteAndStartOver();
 }
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h
index 2b2a37f..372d48e1 100644
--- a/content/browser/service_worker/service_worker_registry.h
+++ b/content/browser/service_worker/service_worker_registry.h
@@ -292,6 +292,7 @@
   void DidFindRegistrationForId(
       int64_t registration_id,
       FindRegistrationCallback callback,
+      uint64_t call_id,
       storage::mojom::ServiceWorkerDatabaseStatus database_status,
       storage::mojom::ServiceWorkerFindRegistrationResultPtr result);
 
@@ -333,8 +334,10 @@
       uint64_t call_id,
       storage::mojom::ServiceWorkerDatabaseStatus status);
   void DidWriteUncommittedResourceIds(
+      uint64_t call_id,
       storage::mojom::ServiceWorkerDatabaseStatus status);
   void DidDoomUncommittedResourceIds(
+      uint64_t call_id,
       storage::mojom::ServiceWorkerDatabaseStatus status);
   void DidGetUserData(GetUserDataCallback callback,
                       storage::mojom::ServiceWorkerDatabaseStatus status,
diff --git a/content/browser/service_worker/service_worker_registry_unittest.cc b/content/browser/service_worker/service_worker_registry_unittest.cc
index 982a0e4..4830ff33b 100644
--- a/content/browser/service_worker/service_worker_registry_unittest.cc
+++ b/content/browser/service_worker/service_worker_registry_unittest.cc
@@ -304,6 +304,13 @@
     InitializeTestHelper();
   }
 
+  void EnsureRemoteCallsAreExecuted() {
+    storage_control().FlushForTesting();
+    // ServiceWorkerRegistry has an internal queue for inflight remote calls.
+    // Run all tasks until all calls in the queue are executed.
+    content::RunAllTasksUntilIdle();
+  }
+
   std::vector<url::Origin> GetRegisteredOrigins() {
     std::vector<url::Origin> result;
     base::RunLoop loop;
@@ -1347,8 +1354,6 @@
     EXPECT_EQ(inflight_call_count(), 2U);
     registry()->SimulateStorageRestartForTesting();
 
-    // TODO(crbug.com/1133143): Add test for FindRegistrationForId().
-
     loop1.Run();
     loop2.Run();
     EXPECT_EQ(inflight_call_count(), 0U);
@@ -1447,6 +1452,67 @@
   }
 }
 
+// Tests that FindRegistrationForId methods are retried after the remote storage
+// is restarted. Separated from other FindRegistration method tests because
+// these methods skip remote calls when live registrations are alive.
+TEST_F(ServiceWorkerRegistryTest, RetryInflightCalls_FindRegistrationForId) {
+  // Prerequisite: Store two registrations.
+  const GURL origin1("https://www.example.com");
+  const GURL scope1("https://www.example.com/foo/");
+  const GURL script1(origin1.spec() + "/script.js");
+  const int64_t registration_id1 = 1;
+  std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources1;
+  resources1.push_back(CreateResourceRecord(1, script1, 100));
+  storage::mojom::ServiceWorkerRegistrationDataPtr data1 =
+      CreateRegistrationData(registration_id1,
+                             /*version_id=*/1000,
+                             /*scope=*/scope1,
+                             /*script_url=*/script1, resources1);
+  StoreRegistrationData(std::move(data1), std::move(resources1));
+
+  const GURL origin2("https://www.example.com");
+  const GURL scope2("https://www.example.com/bar/");
+  const GURL script2(origin2.spec() + "/script.js");
+  const int64_t registration_id2 = 2;
+  std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources2;
+  resources2.push_back(CreateResourceRecord(2, script2, 200));
+  storage::mojom::ServiceWorkerRegistrationDataPtr data2 =
+      CreateRegistrationData(registration_id2,
+                             /*version_id=*/2000,
+                             /*scope=*/scope2,
+                             /*script_url=*/script2, resources2);
+  StoreRegistrationData(std::move(data2), std::move(resources2));
+
+  base::RunLoop loop1;
+  registry()->FindRegistrationForId(
+      registration_id1, url::Origin::Create(origin1.GetOrigin()),
+      base::BindLambdaForTesting(
+          [&](blink::ServiceWorkerStatusCode status,
+              scoped_refptr<ServiceWorkerRegistration> found_registration) {
+            EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk);
+            EXPECT_EQ(found_registration->id(), registration_id1);
+            loop1.Quit();
+          }));
+
+  base::RunLoop loop2;
+  registry()->FindRegistrationForIdOnly(
+      registration_id2,
+      base::BindLambdaForTesting(
+          [&](blink::ServiceWorkerStatusCode status,
+              scoped_refptr<ServiceWorkerRegistration> found_registration) {
+            EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk);
+            EXPECT_EQ(found_registration->id(), registration_id2);
+            loop2.Quit();
+          }));
+
+  EXPECT_EQ(inflight_call_count(), 2U);
+  registry()->SimulateStorageRestartForTesting();
+
+  loop1.Run();
+  loop2.Run();
+  EXPECT_EQ(inflight_call_count(), 0U);
+}
+
 TEST_F(ServiceWorkerRegistryTest,
        RetryInflightCalls_CreateNewRegistrationAndVersion) {
   const GURL kScope("http://www.example.com/scope/");
@@ -1692,8 +1758,7 @@
     // Add the resources ids to the uncommitted list.
     registry()->StoreUncommittedResourceId(resource_id1_, scope_);
     registry()->StoreUncommittedResourceId(resource_id2_, scope_);
-    // Make sure that StoreUncommittedResourceId mojo message is received.
-    storage_control().FlushForTesting();
+    EnsureRemoteCallsAreExecuted();
 
     std::vector<int64_t> verify_ids = GetUncommittedResourceIds();
     EXPECT_EQ(2u, verify_ids.size());
@@ -2009,8 +2074,7 @@
   int64_t kStaleUncommittedResourceId = GetNewResourceIdSync(storage_control());
   registry()->StoreUncommittedResourceId(kStaleUncommittedResourceId,
                                          registration_->scope());
-  // Make sure that StoreUncommittedResourceId mojo message is received.
-  storage_control().FlushForTesting();
+  EnsureRemoteCallsAreExecuted();
   verify_ids = GetUncommittedResourceIds();
   EXPECT_EQ(1u, verify_ids.size());
   WriteBasicResponse(storage_control(), kStaleUncommittedResourceId);
@@ -2089,4 +2153,29 @@
   ASSERT_FALSE(VerifyBasicResponse(storage_control(), resource_id2_, false));
 }
 
+// Tests that StoreUncommittedResourceId() and DoomUncommittedResource() are
+// automatically retried after storage restarts.
+TEST_F(ServiceWorkerRegistryResourceTest, RetryInflightCalls_Resources) {
+  const int64_t kResourceId = GetNewResourceIdSync(storage_control());
+
+  registry()->StoreUncommittedResourceId(kResourceId, registration_->scope());
+  EXPECT_EQ(inflight_call_count(), 1U);
+
+  registry()->SimulateStorageRestartForTesting();
+  EnsureRemoteCallsAreExecuted();
+
+  EXPECT_EQ(inflight_call_count(), 0U);
+  EXPECT_THAT(GetUncommittedResourceIds(),
+              testing::UnorderedElementsAreArray({kResourceId}));
+
+  registry()->DoomUncommittedResource(kResourceId);
+  EXPECT_EQ(inflight_call_count(), 1U);
+
+  registry()->SimulateStorageRestartForTesting();
+  EnsureRemoteCallsAreExecuted();
+
+  EXPECT_EQ(inflight_call_count(), 0U);
+  EXPECT_EQ(GetUncommittedResourceIds().size(), 0U);
+}
+
 }  // namespace content
diff --git a/content/browser/sms/sms_browsertest.cc b/content/browser/sms/sms_browsertest.cc
index 7e61367..271b9699 100644
--- a/content/browser/sms/sms_browsertest.cc
+++ b/content/browser/sms/sms_browsertest.cc
@@ -898,8 +898,7 @@
   ExpectNoOutcomeUKM();
 }
 
-// Disabled test: crbug.com/1146218
-IN_PROC_BROWSER_TEST_F(SmsBrowserTest, DISABLED_RecordUserCancelledAsOutcome) {
+IN_PROC_BROWSER_TEST_F(SmsBrowserTest, RecordUserCancelledAsOutcome) {
   base::HistogramTester histogram_tester;
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kWebOtpBackend, switches::kWebOtpBackendUserConsent);
diff --git a/content/public/test/unittest_test_suite.cc b/content/public/test/unittest_test_suite.cc
index d650a83..78c7aceb 100644
--- a/content/public/test/unittest_test_suite.cc
+++ b/content/public/test/unittest_test_suite.cc
@@ -56,21 +56,6 @@
   DISALLOW_COPY_AND_ASSIGN(ResetNetworkServiceBetweenTests);
 };
 
-// Similarly to the above, the global CertVerifierServiceFactory object needs
-// to be destructed in between tests.
-class ResetCertVerifierServiceFactoryBetweenTests
-    : public testing::EmptyTestEventListener {
- public:
-  ResetCertVerifierServiceFactoryBetweenTests() = default;
-
-  void OnTestEnd(const testing::TestInfo& test_info) override {
-    SetCertVerifierServiceFactoryForTesting(nullptr);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ResetCertVerifierServiceFactoryBetweenTests);
-};
-
 }  // namespace
 
 UnitTestTestSuite::UnitTestTestSuite(base::TestSuite* test_suite)
@@ -87,7 +72,6 @@
   testing::TestEventListeners& listeners =
       testing::UnitTest::GetInstance()->listeners();
   listeners.Append(new ResetNetworkServiceBetweenTests);
-  listeners.Append(new ResetCertVerifierServiceFactoryBetweenTests);
 
   // The ThreadPool created by the test launcher is never destroyed.
   // Similarly, the FeatureList created here is never destroyed so it
diff --git a/gpu/config/vulkan_info.h b/gpu/config/vulkan_info.h
index be60f8ca..8538cf5 100644
--- a/gpu/config/vulkan_info.h
+++ b/gpu/config/vulkan_info.h
@@ -26,6 +26,7 @@
   VkPhysicalDevice device = VK_NULL_HANDLE;
 
   VkPhysicalDeviceProperties properties = {};
+  VkPhysicalDeviceDriverProperties driver_properties = {};
   std::vector<VkExtensionProperties> extensions;
 
   VkPhysicalDeviceFeatures features = {};
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py
index 346887a2..f9f6bf6 100755
--- a/gpu/vulkan/generate_bindings.py
+++ b/gpu/vulkan/generate_bindings.py
@@ -47,10 +47,12 @@
       'vkGetDeviceProcAddr',
       'vkGetPhysicalDeviceFeatures2',
       'vkGetPhysicalDeviceFormatProperties',
+      'vkGetPhysicalDeviceFormatProperties2',
       'vkGetPhysicalDeviceImageFormatProperties2',
       'vkGetPhysicalDeviceMemoryProperties',
       'vkGetPhysicalDeviceMemoryProperties2',
       'vkGetPhysicalDeviceProperties',
+      'vkGetPhysicalDeviceProperties2',
       'vkGetPhysicalDeviceQueueFamilyProperties',
     ]
   },
@@ -160,6 +162,7 @@
       'vkGetFenceStatus',
       'vkGetImageMemoryRequirements',
       'vkGetImageMemoryRequirements2',
+      'vkGetImageSubresourceLayout',
       'vkMapMemory',
       'vkQueueSubmit',
       'vkQueueWaitIdle',
@@ -244,8 +247,14 @@
       'vkGetSwapchainImagesKHR',
       'vkQueuePresentKHR',
     ]
+  },
+  {
+    'ifdef': 'defined(OS_LINUX)',
+    'extension': 'VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME',
+    'functions': [
+      'vkGetImageDrmFormatModifierPropertiesEXT',
+    ]
   }
-
 ]
 
 SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
diff --git a/gpu/vulkan/vulkan_device_queue.cc b/gpu/vulkan/vulkan_device_queue.cc
index e30bbd1..9b56d97 100644
--- a/gpu/vulkan/vulkan_device_queue.cc
+++ b/gpu/vulkan/vulkan_device_queue.cc
@@ -129,6 +129,8 @@
   const auto& physical_device_info = info.physical_devices[device_index];
   vk_physical_device_ = physical_device_info.device;
   vk_physical_device_properties_ = physical_device_info.properties;
+  vk_physical_device_driver_properties_ =
+      physical_device_info.driver_properties;
   vk_queue_index_ = queue_index;
 
   float queue_priority = 0.0f;
diff --git a/gpu/vulkan/vulkan_device_queue.h b/gpu/vulkan/vulkan_device_queue.h
index f7b23c0..34835a6 100644
--- a/gpu/vulkan/vulkan_device_queue.h
+++ b/gpu/vulkan/vulkan_device_queue.h
@@ -70,6 +70,11 @@
     return vk_physical_device_properties_;
   }
 
+  const VkPhysicalDeviceDriverProperties& vk_physical_device_driver_properties()
+      const {
+    return vk_physical_device_driver_properties_;
+  }
+
   VkDevice GetVulkanDevice() const {
     DCHECK_NE(static_cast<VkDevice>(VK_NULL_HANDLE), vk_device_);
     return vk_device_;
@@ -104,6 +109,7 @@
   gfx::ExtensionSet enabled_extensions_;
   VkPhysicalDevice vk_physical_device_ = VK_NULL_HANDLE;
   VkPhysicalDeviceProperties vk_physical_device_properties_;
+  VkPhysicalDeviceDriverProperties vk_physical_device_driver_properties_;
   VkDevice owned_vk_device_ = VK_NULL_HANDLE;
   VkDevice vk_device_ = VK_NULL_HANDLE;
   VkQueue vk_queue_ = VK_NULL_HANDLE;
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc
index 3fa104f..dbfb5ef7 100644
--- a/gpu/vulkan/vulkan_function_pointers.cc
+++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -146,6 +146,16 @@
     return false;
   }
 
+  vkGetPhysicalDeviceFormatProperties2 =
+      reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(
+          vkGetInstanceProcAddr(vk_instance,
+                                "vkGetPhysicalDeviceFormatProperties2"));
+  if (!vkGetPhysicalDeviceFormatProperties2) {
+    DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                  << "vkGetPhysicalDeviceFormatProperties2";
+    return false;
+  }
+
   vkGetPhysicalDeviceImageFormatProperties2 =
       reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
           vkGetInstanceProcAddr(vk_instance,
@@ -185,6 +195,15 @@
     return false;
   }
 
+  vkGetPhysicalDeviceProperties2 =
+      reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
+          vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties2"));
+  if (!vkGetPhysicalDeviceProperties2) {
+    DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                  << "vkGetPhysicalDeviceProperties2";
+    return false;
+  }
+
   vkGetPhysicalDeviceQueueFamilyProperties =
       reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(
           vkGetInstanceProcAddr(vk_instance,
@@ -782,6 +801,15 @@
     return false;
   }
 
+  vkGetImageSubresourceLayout =
+      reinterpret_cast<PFN_vkGetImageSubresourceLayout>(
+          vkGetDeviceProcAddr(vk_device, "vkGetImageSubresourceLayout"));
+  if (!vkGetImageSubresourceLayout) {
+    DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                  << "vkGetImageSubresourceLayout";
+    return false;
+  }
+
   vkMapMemory = reinterpret_cast<PFN_vkMapMemory>(
       vkGetDeviceProcAddr(vk_device, "vkMapMemory"));
   if (!vkMapMemory) {
@@ -1075,6 +1103,21 @@
     }
   }
 
+#if defined(OS_LINUX)
+  if (gfx::HasExtension(enabled_extensions,
+                        VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME)) {
+    vkGetImageDrmFormatModifierPropertiesEXT =
+        reinterpret_cast<PFN_vkGetImageDrmFormatModifierPropertiesEXT>(
+            vkGetDeviceProcAddr(vk_device,
+                                "vkGetImageDrmFormatModifierPropertiesEXT"));
+    if (!vkGetImageDrmFormatModifierPropertiesEXT) {
+      DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                    << "vkGetImageDrmFormatModifierPropertiesEXT";
+      return false;
+    }
+  }
+#endif  // defined(OS_LINUX)
+
   return true;
 }
 
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h
index e1a6e5c..83eece00 100644
--- a/gpu/vulkan/vulkan_function_pointers.h
+++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -115,6 +115,8 @@
   VulkanFunction<PFN_vkGetPhysicalDeviceFeatures2> vkGetPhysicalDeviceFeatures2;
   VulkanFunction<PFN_vkGetPhysicalDeviceFormatProperties>
       vkGetPhysicalDeviceFormatProperties;
+  VulkanFunction<PFN_vkGetPhysicalDeviceFormatProperties2>
+      vkGetPhysicalDeviceFormatProperties2;
   VulkanFunction<PFN_vkGetPhysicalDeviceImageFormatProperties2>
       vkGetPhysicalDeviceImageFormatProperties2;
   VulkanFunction<PFN_vkGetPhysicalDeviceMemoryProperties>
@@ -123,6 +125,8 @@
       vkGetPhysicalDeviceMemoryProperties2;
   VulkanFunction<PFN_vkGetPhysicalDeviceProperties>
       vkGetPhysicalDeviceProperties;
+  VulkanFunction<PFN_vkGetPhysicalDeviceProperties2>
+      vkGetPhysicalDeviceProperties2;
   VulkanFunction<PFN_vkGetPhysicalDeviceQueueFamilyProperties>
       vkGetPhysicalDeviceQueueFamilyProperties;
 
@@ -221,6 +225,7 @@
   VulkanFunction<PFN_vkGetImageMemoryRequirements> vkGetImageMemoryRequirements;
   VulkanFunction<PFN_vkGetImageMemoryRequirements2>
       vkGetImageMemoryRequirements2;
+  VulkanFunction<PFN_vkGetImageSubresourceLayout> vkGetImageSubresourceLayout;
   VulkanFunction<PFN_vkMapMemory> vkMapMemory;
   VulkanFunction<PFN_vkQueueSubmit> vkQueueSubmit;
   VulkanFunction<PFN_vkQueueWaitIdle> vkQueueWaitIdle;
@@ -285,6 +290,11 @@
   VulkanFunction<PFN_vkDestroySwapchainKHR> vkDestroySwapchainKHR;
   VulkanFunction<PFN_vkGetSwapchainImagesKHR> vkGetSwapchainImagesKHR;
   VulkanFunction<PFN_vkQueuePresentKHR> vkQueuePresentKHR;
+
+#if defined(OS_LINUX)
+  VulkanFunction<PFN_vkGetImageDrmFormatModifierPropertiesEXT>
+      vkGetImageDrmFormatModifierPropertiesEXT;
+#endif  // defined(OS_LINUX)
 };
 
 }  // namespace gpu
@@ -373,6 +383,13 @@
   return gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceFormatProperties(
       physicalDevice, format, pFormatProperties);
 }
+ALWAYS_INLINE void vkGetPhysicalDeviceFormatProperties2(
+    VkPhysicalDevice physicalDevice,
+    VkFormat format,
+    VkFormatProperties2* pFormatProperties) {
+  return gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceFormatProperties2(
+      physicalDevice, format, pFormatProperties);
+}
 ALWAYS_INLINE VkResult vkGetPhysicalDeviceImageFormatProperties2(
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
@@ -399,6 +416,12 @@
   return gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceProperties(
       physicalDevice, pProperties);
 }
+ALWAYS_INLINE void vkGetPhysicalDeviceProperties2(
+    VkPhysicalDevice physicalDevice,
+    VkPhysicalDeviceProperties2* pProperties) {
+  return gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceProperties2(
+      physicalDevice, pProperties);
+}
 ALWAYS_INLINE void vkGetPhysicalDeviceQueueFamilyProperties(
     VkPhysicalDevice physicalDevice,
     uint32_t* pQueueFamilyPropertyCount,
@@ -891,6 +914,14 @@
   return gpu::GetVulkanFunctionPointers()->vkGetImageMemoryRequirements2(
       device, pInfo, pMemoryRequirements);
 }
+ALWAYS_INLINE void vkGetImageSubresourceLayout(
+    VkDevice device,
+    VkImage image,
+    const VkImageSubresource* pSubresource,
+    VkSubresourceLayout* pLayout) {
+  return gpu::GetVulkanFunctionPointers()->vkGetImageSubresourceLayout(
+      device, image, pSubresource, pLayout);
+}
 ALWAYS_INLINE VkResult vkMapMemory(VkDevice device,
                                    VkDeviceMemory memory,
                                    VkDeviceSize offset,
@@ -1082,4 +1113,14 @@
                                                              pPresentInfo);
 }
 
+#if defined(OS_LINUX)
+ALWAYS_INLINE VkResult vkGetImageDrmFormatModifierPropertiesEXT(
+    VkDevice device,
+    VkImage image,
+    VkImageDrmFormatModifierPropertiesEXT* pProperties) {
+  return gpu::GetVulkanFunctionPointers()
+      ->vkGetImageDrmFormatModifierPropertiesEXT(device, image, pProperties);
+}
+#endif  // defined(OS_LINUX)
+
 #endif  // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
\ No newline at end of file
diff --git a/gpu/vulkan/vulkan_image.cc b/gpu/vulkan/vulkan_image.cc
index b14a276..029ecd40 100644
--- a/gpu/vulkan/vulkan_image.cc
+++ b/gpu/vulkan/vulkan_image.cc
@@ -67,10 +67,13 @@
     VkFormat format,
     VkImageUsageFlags usage,
     VkImageCreateFlags flags,
-    VkImageTiling image_tiling) {
+    VkImageTiling image_tiling,
+    void* image_create_info_next,
+    void* memory_allocation_info_next) {
   auto image = std::make_unique<VulkanImage>(base::PassKey<VulkanImage>());
-  if (!image->InitializeWithExternalMemory(device_queue, size, format, usage,
-                                           flags, image_tiling)) {
+  if (!image->InitializeWithExternalMemory(
+          device_queue, size, format, usage, flags, image_tiling,
+          image_create_info_next, memory_allocation_info_next)) {
     return nullptr;
   }
   return image;
@@ -270,12 +273,15 @@
   return true;
 }
 
-bool VulkanImage::InitializeWithExternalMemory(VulkanDeviceQueue* device_queue,
-                                               const gfx::Size& size,
-                                               VkFormat format,
-                                               VkImageUsageFlags usage,
-                                               VkImageCreateFlags flags,
-                                               VkImageTiling image_tiling) {
+bool VulkanImage::InitializeWithExternalMemory(
+    VulkanDeviceQueue* device_queue,
+    const gfx::Size& size,
+    VkFormat format,
+    VkImageUsageFlags usage,
+    VkImageCreateFlags flags,
+    VkImageTiling image_tiling,
+    void* image_create_info_next,
+    void* memory_allocation_info_next) {
 #if defined(OS_FUCHSIA)
   constexpr auto kHandleType =
       VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
@@ -293,12 +299,25 @@
       .usage = usage,
       .flags = flags,
   };
+
   VkPhysicalDeviceExternalImageFormatInfo external_info = {
       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
       .handleType = kHandleType,
   };
   format_info_2.pNext = &external_info;
 
+#if defined(OS_LINUX)
+  VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifier_info = {
+      .sType =
+          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+  };
+  // If image_tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, a modifier_info
+  // struct has to be appended.
+  if (image_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+    external_info.pNext = &modifier_info;
+#endif
+
   VkImageFormatProperties2 image_format_properties_2 = {
       .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
   };
@@ -332,11 +351,13 @@
 
   VkExternalMemoryImageCreateInfoKHR external_image_create_info = {
       .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
+      .pNext = image_create_info_next,
       .handleTypes = handle_types_,
   };
 
   VkExportMemoryAllocateInfoKHR external_memory_allocate_info = {
       .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
+      .pNext = memory_allocation_info_next,
       .handleTypes = handle_types_,
   };
 
diff --git a/gpu/vulkan/vulkan_image.h b/gpu/vulkan/vulkan_image.h
index 30e7b80..191598d4 100644
--- a/gpu/vulkan/vulkan_image.h
+++ b/gpu/vulkan/vulkan_image.h
@@ -55,7 +55,9 @@
       VkFormat format,
       VkImageUsageFlags usage,
       VkImageCreateFlags flags = 0,
-      VkImageTiling image_tiling = VK_IMAGE_TILING_OPTIMAL);
+      VkImageTiling image_tiling = VK_IMAGE_TILING_OPTIMAL,
+      void* image_create_info_next = nullptr,
+      void* memory_allocation_info_next = nullptr);
 
   static std::unique_ptr<VulkanImage> CreateFromGpuMemoryBufferHandle(
       VulkanDeviceQueue* device_queue,
@@ -136,7 +138,9 @@
                                     VkFormat format,
                                     VkImageUsageFlags usage,
                                     VkImageCreateFlags flags,
-                                    VkImageTiling image_tiling);
+                                    VkImageTiling image_tiling,
+                                    void* image_create_info_next,
+                                    void* memory_allocation_info_next);
   bool InitializeFromGpuMemoryBufferHandle(
       VulkanDeviceQueue* device_queue,
       gfx::GpuMemoryBufferHandle gmb_handle,
diff --git a/gpu/vulkan/vulkan_instance.cc b/gpu/vulkan/vulkan_instance.cc
index afb7b49..0007c65 100644
--- a/gpu/vulkan/vulkan_instance.cc
+++ b/gpu/vulkan/vulkan_instance.cc
@@ -265,7 +265,17 @@
     auto& info = vulkan_info_.physical_devices.back();
     info.device = device;
 
-    vkGetPhysicalDeviceProperties(device, &info.properties);
+    info.driver_properties = VkPhysicalDeviceDriverProperties{
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
+    };
+
+    VkPhysicalDeviceProperties2 properties2 = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+        .pNext = &info.driver_properties,
+    };
+
+    vkGetPhysicalDeviceProperties2(device, &properties2);
+    info.properties = properties2.properties;
 
     count = 0;
     result = vkEnumerateDeviceExtensionProperties(
diff --git a/gpu/vulkan/x/vulkan_implementation_x11.cc b/gpu/vulkan/x/vulkan_implementation_x11.cc
index 7d601938..638345b 100644
--- a/gpu/vulkan/x/vulkan_implementation_x11.cc
+++ b/gpu/vulkan/x/vulkan_implementation_x11.cc
@@ -118,11 +118,14 @@
 
 std::vector<const char*>
 VulkanImplementationX11::GetOptionalDeviceExtensions() {
-  return {VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
-          VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
-          VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
-          VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
-          VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME};
+  return {
+      VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+      VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
+      VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
+      VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
+      VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
+      VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
+  };
 }
 
 VkFence VulkanImplementationX11::CreateVkFenceForGpuFence(VkDevice vk_device) {
@@ -163,6 +166,8 @@
 
 bool VulkanImplementationX11::CanImportGpuMemoryBuffer(
     gfx::GpuMemoryBufferType memory_buffer_type) {
+  if (memory_buffer_type == gfx::GpuMemoryBufferType::NATIVE_PIXMAP)
+    return true;
   return false;
 }
 
@@ -171,9 +176,12 @@
     VulkanDeviceQueue* device_queue,
     gfx::GpuMemoryBufferHandle gmb_handle,
     gfx::Size size,
-    VkFormat vk_formae) {
-  NOTIMPLEMENTED();
-  return nullptr;
+    VkFormat vk_format) {
+  constexpr auto kUsage =
+      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
+      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+  return VulkanImage::CreateFromGpuMemoryBufferHandle(
+      device_queue, std::move(gmb_handle), size, vk_format, kUsage);
 }
 
 }  // namespace gpu
diff --git a/ios/chrome/browser/ui/incognito_reauth/BUILD.gn b/ios/chrome/browser/ui/incognito_reauth/BUILD.gn
index 6c675f0b..2fcb38e 100644
--- a/ios/chrome/browser/ui/incognito_reauth/BUILD.gn
+++ b/ios/chrome/browser/ui/incognito_reauth/BUILD.gn
@@ -13,6 +13,7 @@
 source_set("incognito_reauth_ui") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "incognito_reauth_consumer.h",
     "incognito_reauth_view.h",
     "incognito_reauth_view.mm",
   ]
@@ -26,11 +27,14 @@
 source_set("incognito_reauth_scene_agent") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "incognito_reauth_mediator.h",
+    "incognito_reauth_mediator.mm",
     "incognito_reauth_scene_agent.h",
     "incognito_reauth_scene_agent.mm",
   ]
   deps = [
     ":incognito_reauth_commands",
+    ":incognito_reauth_ui",
     "//base",
     "//components/pref_registry",
     "//components/prefs",
diff --git a/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_consumer.h b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_consumer.h
new file mode 100644
index 0000000..f81b988e
--- /dev/null
+++ b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_consumer.h
@@ -0,0 +1,18 @@
+// 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_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_CONSUMER_H_
+#define IOS_CHROME_BROWSER_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_CONSUMER_H_
+
+#import <UIKit/UIKit.h>
+
+@protocol IncognitoReauthConsumer <NSObject>
+
+// Notify consumer that the displayed items require authentication before they
+// can be accessed. Used for biometric incognito tab authentication.
+- (void)setItemsRequireAuthentication:(BOOL)requireAuthentication;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h
new file mode 100644
index 0000000..5b1cfc0
--- /dev/null
+++ b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h
@@ -0,0 +1,25 @@
+// 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_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_MEDIATOR_H_
+
+#import <UIKit/UIKit.h>
+
+@class IncognitoReauthSceneAgent;
+@protocol IncognitoReauthConsumer;
+
+// Mediator handling incognito reauthentication. Uses the reauth scene agent as
+// the source of truth for reauth state.
+@interface IncognitoReauthMediator : NSObject
+
+- (instancetype)initWithConsumer:(id<IncognitoReauthConsumer>)consumer
+                     reauthAgent:(IncognitoReauthSceneAgent*)reauthAgent
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_INCOGNITO_REAUTH_INCOGNITO_REAUTH_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.mm b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.mm
new file mode 100644
index 0000000..67045fd
--- /dev/null
+++ b/ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.mm
@@ -0,0 +1,47 @@
+// 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 "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h"
+
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_consumer.h"
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface IncognitoReauthMediator () <IncognitoReauthObserver>
+
+// Consumer for this mediator.
+@property(nonatomic, weak) id<IncognitoReauthConsumer> consumer;
+
+// Agent tracking the authentication status.
+@property(nonatomic, weak) IncognitoReauthSceneAgent* reauthAgent;
+
+@end
+
+@implementation IncognitoReauthMediator
+
+- (instancetype)initWithConsumer:(id<IncognitoReauthConsumer>)consumer
+                     reauthAgent:(IncognitoReauthSceneAgent*)reauthAgent {
+  self = [super init];
+  if (self) {
+    _consumer = consumer;
+    _reauthAgent = reauthAgent;
+    [reauthAgent addObserver:self];
+
+    [_consumer
+        setItemsRequireAuthentication:reauthAgent.authenticationRequired];
+  }
+  return self;
+}
+
+#pragma mark - IncognitoReauthObserver
+
+- (void)reauthAgent:(IncognitoReauthSceneAgent*)agent
+    didUpdateAuthenticationRequirement:(BOOL)isRequired {
+  [self.consumer setItemsRequireAuthentication:isRequired];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h
index f69abeed..8cb8c34 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h
@@ -12,10 +12,6 @@
 // Supports idempotent insert/delete/updates to a grid.
 @protocol GridConsumer
 
-// Notify consumer that the displayed items require authentication before they
-// can be accessed. Used for biometric incognito tab authentication.
-- (void)setItemsRequireAuthentication:(BOOL)requireAuthentication;
-
 // Many of the following methods pass a |selectedItemID| as a parameter,
 // indicating the identifier of the item that should be in the selected state
 // after the method is called. In every such case, a nil |selectedItemID|
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
index 417f3bc8..76c36c3 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
@@ -8,6 +8,7 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/chrome/browser/ui/gestures/layout_switcher.h"
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_consumer.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_theme.h"
 
@@ -54,7 +55,8 @@
 @end
 
 // A view controller that contains a grid of items.
-@interface GridViewController : UIViewController <GridConsumer, LayoutSwitcher>
+@interface GridViewController
+    : UIViewController <GridConsumer, LayoutSwitcher, IncognitoReauthConsumer>
 // The gridView is accessible to manage the content inset behavior.
 @property(nonatomic, readonly) UIScrollView* gridView;
 // The view that is shown when there are no items.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
index 4f2912dc..86f82b9 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -617,7 +617,7 @@
       base::UserMetricsAction("MobileTabGridCloseControlTapped"));
 }
 
-#pragma mark - GridConsumer
+#pragma mark - IncognitoReauthConsumer
 
 - (void)setItemsRequireAuthentication:(BOOL)require {
   self.contentNeedsAuthentication = require;
@@ -645,6 +645,8 @@
   }
 }
 
+#pragma mark - GridConsumer
+
 - (void)populateItems:(NSArray<TabSwitcherItem*>*)items
        selectedItemID:(NSString*)selectedItemID {
 #ifndef NDEBUG
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
index a588dc27b..fafc884 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -25,6 +25,7 @@
 #import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h"
 #import "ios/chrome/browser/ui/history/history_coordinator.h"
 #import "ios/chrome/browser/ui/history/public/history_presentation_delegate.h"
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h"
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h"
 #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
@@ -79,6 +80,8 @@
 @property(nonatomic, strong) TabGridMediator* regularTabsMediator;
 // Mediator for incognito Tabs.
 @property(nonatomic, strong) TabGridMediator* incognitoTabsMediator;
+// Mediator for incognito reauth.
+@property(nonatomic, strong) IncognitoReauthMediator* incognitoAuthMediator;
 // Mediator for remote Tabs.
 @property(nonatomic, strong) RecentTabsMediator* remoteTabsMediator;
 // Coordinator for history, which can be started from recent tabs.
@@ -325,8 +328,7 @@
   _baseViewController = baseViewController;
 
   self.regularTabsMediator = [[TabGridMediator alloc]
-      initWithConsumer:baseViewController.regularTabsConsumer
-           reauthAgent:nil];
+      initWithConsumer:baseViewController.regularTabsConsumer];
   ChromeBrowserState* regularBrowserState =
       _regularBrowser ? _regularBrowser->GetBrowserState() : nullptr;
   WebStateList* regularWebStateList =
@@ -341,8 +343,7 @@
   }
 
   self.incognitoTabsMediator = [[TabGridMediator alloc]
-      initWithConsumer:baseViewController.incognitoTabsConsumer
-           reauthAgent:reauthAgent];
+      initWithConsumer:baseViewController.incognitoTabsConsumer];
   self.incognitoTabsMediator.browser = _incognitoBrowser;
   self.incognitoTabsMediator.delegate = self;
   baseViewController.regularTabsDelegate = self.regularTabsMediator;
@@ -352,6 +353,10 @@
   baseViewController.regularTabsImageDataSource = self.regularTabsMediator;
   baseViewController.incognitoTabsImageDataSource = self.incognitoTabsMediator;
 
+  self.incognitoAuthMediator = [[IncognitoReauthMediator alloc]
+      initWithConsumer:self.baseViewController.incognitoTabsConsumer
+           reauthAgent:reauthAgent];
+
   if (@available(iOS 13.0, *)) {
     self.recentTabsContextMenuHelper =
         [[RecentTabsContextMenuHelper alloc] initWithBrowser:self.regularBrowser
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
index 6ea7574..8962ee7 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
@@ -13,7 +13,6 @@
 
 class Browser;
 @protocol GridConsumer;
-@class IncognitoReauthSceneAgent;
 @class TabGridMediator;
 
 namespace sessions {
@@ -48,7 +47,6 @@
 
 // Initializer with |consumer| as the receiver of model layer updates.
 - (instancetype)initWithConsumer:(id<GridConsumer>)consumer
-                     reauthAgent:(IncognitoReauthSceneAgent*)reauthAgent
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
index bcd8927..fe16bb8e 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -28,7 +28,6 @@
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
 #include "ios/chrome/browser/system_flags.h"
 #import "ios/chrome/browser/tabs/tab_title_util.h"
-#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h"
 #import "ios/chrome/browser/web/tab_id_tab_helper.h"
@@ -110,7 +109,6 @@
 }  // namespace
 
 @interface TabGridMediator () <CRWWebStateObserver,
-                               IncognitoReauthObserver,
                                SnapshotCacheObserver,
                                WebStateListObserving>
 // The list from the browser.
@@ -127,8 +125,6 @@
 // Short-term cache for grid thumbnails.
 @property(nonatomic, strong)
     NSMutableDictionary<NSString*, UIImage*>* appearanceCache;
-// Agent tracking the authentication status.
-@property(nonatomic, weak) IncognitoReauthSceneAgent* reauthAgent;
 @end
 
 @implementation TabGridMediator {
@@ -142,8 +138,7 @@
       _scopedWebStateObserver;
 }
 
-- (instancetype)initWithConsumer:(id<GridConsumer>)consumer
-                     reauthAgent:(IncognitoReauthSceneAgent*)agent {
+- (instancetype)initWithConsumer:(id<GridConsumer>)consumer {
   if (self = [super init]) {
     _consumer = consumer;
     _webStateListObserverBridge =
@@ -157,8 +152,6 @@
         std::make_unique<ScopedObserver<web::WebState, web::WebStateObserver>>(
             _webStateObserverBridge.get());
     _appearanceCache = [[NSMutableDictionary alloc] init];
-    _reauthAgent = agent;
-    [agent addObserver:self];
   }
   return self;
 }
@@ -564,13 +557,6 @@
   [self.appearanceCache removeAllObjects];
 }
 
-#pragma mark - IncognitoReauthObserver
-
-- (void)reauthAgent:(IncognitoReauthSceneAgent*)agent
-    didUpdateAuthenticationRequirement:(BOOL)isRequired {
-  [self.consumer setItemsRequireAuthentication:isRequired];
-}
-
 #pragma mark - Private
 
 // Calls |-populateItems:selectedItemID:| on the consumer.
@@ -579,9 +565,6 @@
     [self.consumer populateItems:CreateItems(self.webStateList)
                   selectedItemID:GetActiveTabId(self.webStateList)];
   }
-
-  [self.consumer
-      setItemsRequireAuthentication:self.reauthAgent.authenticationRequired];
 }
 
 // Removes |self.syncedClosedTabsCount| most recent entries from the
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm
index 2cb6b465..b071984 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm
@@ -268,8 +268,7 @@
         TabIdTabHelper::FromWebState(web_state_list_->GetWebStateAt(1))
             ->tab_id();
     consumer_ = [[FakeConsumer alloc] init];
-    mediator_ = [[TabGridMediator alloc] initWithConsumer:consumer_
-                                              reauthAgent:nil];
+    mediator_ = [[TabGridMediator alloc] initWithConsumer:consumer_];
     mediator_.browser = browser_.get();
     mediator_.tabRestoreService = tab_restore_service_;
   }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
index 1856e388..6bf172b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
@@ -14,6 +14,7 @@
 
 @protocol ApplicationCommands;
 @protocol IncognitoReauthCommands;
+@protocol IncognitoReauthConsumer;
 @protocol GridConsumer;
 @protocol GridCommands;
 @protocol GridDragDropHandler;
@@ -45,7 +46,8 @@
 
 // Consumers send updates from the model layer to the UI layer.
 @property(nonatomic, readonly) id<GridConsumer> regularTabsConsumer;
-@property(nonatomic, readonly) id<GridConsumer> incognitoTabsConsumer;
+@property(nonatomic, readonly) id<GridConsumer, IncognitoReauthConsumer>
+    incognitoTabsConsumer;
 @property(nonatomic, readonly) id<RecentTabsConsumer> remoteTabsConsumer;
 
 // Delegates send updates from the UI layer to the model layer.
diff --git a/rlz/BUILD.gn b/rlz/BUILD.gn
index a0d7318..71bd030 100644
--- a/rlz/BUILD.gn
+++ b/rlz/BUILD.gn
@@ -5,6 +5,7 @@
 # Note that this build file assumes rlz_use_chrome_net which is a condition in
 # the GYP file, but is always true for Chrome builds.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//rlz/buildflags/buildflags.gni")
 import("//testing/test.gni")
 
@@ -30,7 +31,10 @@
 
   public_deps = [ "//base" ]
 
-  deps = [ "//third_party/zlib" ]
+  deps = [
+    "//build:chromeos_buildflags",
+    "//third_party/zlib",
+  ]
 }
 
 if (enable_rlz_support) {
@@ -72,9 +76,10 @@
     deps = [
       ":rlz_utils",
       "//base",
+      "//build:chromeos_buildflags",
     ]
 
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       sources += [
         "chromeos/lib/rlz_value_store_chromeos.cc",
         "chromeos/lib/rlz_value_store_chromeos.h",
@@ -130,13 +135,14 @@
     deps = [
       ":rlz_utils",
       "//base/third_party/dynamic_annotations",
+      "//build:chromeos_buildflags",
       "//net",
       "//services/network/public/cpp:cpp",
       "//services/network/public/mojom",
       "//url",
     ]
 
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       deps += [
         "//chromeos/dbus",
         "//chromeos/system",
@@ -157,8 +163,11 @@
       "//base/test:test_support",
       "//testing/gtest",
     ]
-    deps = [ ":rlz_lib" ]
-    if (is_chromeos) {
+    deps = [
+      ":rlz_lib",
+      "//build:chromeos_buildflags",
+    ]
+    if (is_chromeos_ash) {
       public_deps += [ "//chromeos/system" ]
     }
   }
@@ -187,6 +196,7 @@
       ":rlz_utils",
       ":test_support",
       "//base",
+      "//build:chromeos_buildflags",
       "//mojo/core/embedder",
       "//net:test_support",
       "//services/network:test_support",
@@ -194,7 +204,7 @@
       "//testing/gtest",
       "//third_party/zlib",
     ]
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       deps += [
         "//chromeos/dbus:test_support",
         "//chromeos/system",
diff --git a/rlz/buildflags/buildflags.gni b/rlz/buildflags/buildflags.gni
index f70c30c..73d96517a 100644
--- a/rlz/buildflags/buildflags.gni
+++ b/rlz/buildflags/buildflags.gni
@@ -3,9 +3,10 @@
 # found in the LICENSE file.
 
 import("//build/config/chrome_build.gni")
+import("//build/config/chromeos/ui_mode.gni")
 
 # Whether we are using the rlz library or not.  Platforms like Android send
 # rlz codes for searches but do not use the library.
-enable_rlz_support = is_win || is_apple || is_chromeos
+enable_rlz_support = is_win || is_apple || is_chromeos_ash
 
 enable_rlz = is_chrome_branded && enable_rlz_support
diff --git a/rlz/lib/financial_ping_test.cc b/rlz/lib/financial_ping_test.cc
index a70adb8..f150c6d4 100644
--- a/rlz/lib/financial_ping_test.cc
+++ b/rlz/lib/financial_ping_test.cc
@@ -23,6 +23,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "rlz/lib/lib_values.h"
 #include "rlz/lib/machine_id.h"
 #include "rlz/lib/rlz_lib.h"
@@ -38,14 +39,14 @@
 #include "base/time/time.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/factory_ping_embargo_check.h"
 #include "rlz/chromeos/lib/rlz_value_store_chromeos.h"
 #endif
 
 namespace {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void RemoveMachineIdFromUrl(std::string* url) {
   size_t id_offset = url->find("&id=");
   EXPECT_NE(std::string::npos, id_offset);
@@ -104,7 +105,7 @@
   // Don't check the machine Id on Chrome OS since a random one is generated
   // each time.
   std::string machine_id;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool got_machine_id = false;
 #else
   bool got_machine_id = rlz_lib::GetMachineId(&machine_id);
@@ -114,7 +115,7 @@
   EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
       points, "swg", brand, NULL, "en", false, &request));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Ignore the machine Id of the request URL.  On Chrome OS a random Id is
   // generated with each request.
   RemoveMachineIdFromUrl(&request);
@@ -134,7 +135,7 @@
   EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
       points, "swg", brand, "IdOk2", NULL, false, &request));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Ignore the machine Id of the request URL.  On Chrome OS a random Id is
   // generated with each request.
   RemoveMachineIdFromUrl(&request);
@@ -328,7 +329,7 @@
                                                  false));
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(FinancialPingTest, RlzEmbargoEndDate) {
   // Do not set last ping time, verify that |IsPingTime| returns true.
   EXPECT_TRUE(
diff --git a/rlz/lib/machine_id.cc b/rlz/lib/machine_id.cc
index 615a2b82b..9d7b44b 100644
--- a/rlz/lib/machine_id.cc
+++ b/rlz/lib/machine_id.cc
@@ -9,6 +9,7 @@
 #include "base/hash/sha1.h"
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "rlz/lib/assert.h"
 #include "rlz/lib/crc8.h"
 #include "rlz/lib/string_utils.h"
@@ -19,7 +20,7 @@
   if (!machine_id)
     return false;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Generate a random machine Id each time this function is called.  This
   // prevents the RLZ server from correlating two RLZ pings from the same
@@ -60,7 +61,7 @@
   calculated_id = *machine_id;
   return true;
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 namespace testing {
diff --git a/rlz/lib/machine_id_unittest.cc b/rlz/lib/machine_id_unittest.cc
index 21a4f07..f0de67e 100644
--- a/rlz/lib/machine_id_unittest.cc
+++ b/rlz/lib/machine_id_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "rlz/test/rlz_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,7 +21,7 @@
                id.c_str());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST(MachineDealCodeTestMachineId, MachineIdIsUnique) {
   std::string id1;
   std::string id2;
diff --git a/rlz/lib/rlz_lib.cc b/rlz/lib/rlz_lib.cc
index 6a8256a..c1986799 100644
--- a/rlz/lib/rlz_lib.cc
+++ b/rlz/lib/rlz_lib.cc
@@ -15,6 +15,7 @@
 #include "base/syslog_logging.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "net/base/backoff_entry.h"
 #include "rlz/lib/assert.h"
 #include "rlz/lib/financial_ping.h"
@@ -441,7 +442,7 @@
   FinancialPing::UpdateLastPingTime(product);
   std::string response;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const net::BackoffEntry::Policy policy = {
       0,  // Number of initial errors to ignore.
       base::TimeDelta::FromSeconds(5).InMilliseconds(),  // Initial delay.
diff --git a/rlz/lib/rlz_lib_test.cc b/rlz/lib/rlz_lib_test.cc
index 2a5c827a..6813357 100644
--- a/rlz/lib/rlz_lib_test.cc
+++ b/rlz/lib/rlz_lib_test.cc
@@ -23,6 +23,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "rlz/lib/financial_ping.h"
 #include "rlz/lib/lib_values.h"
 #include "rlz/lib/net_response_check.h"
@@ -48,7 +49,7 @@
 #include "services/network/test/test_url_loader_factory.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/files/important_file_writer.h"
 #include "base/stl_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -219,7 +220,7 @@
   EXPECT_STREQ("IeTbRlz", rlz_50);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(RlzLibTest, SetAccessPointRlzOnlyOnce) {
   // On Chrome OS, and RLZ string can ne set only once.
   char rlz_50[50];
@@ -483,7 +484,7 @@
   EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
                                          kPingResponse2));
   EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, value, 50));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS, the RLZ string is not modified by response once set.
   EXPECT_STREQ("1T4_____en__252", value);
 #else
@@ -494,7 +495,7 @@
     "crc32: 0\r\n";  // Good RLZ - empty response.
   EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
                                          kPingResponse3));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS, the RLZ string is not modified by response once set.
   EXPECT_STREQ("1T4_____en__252", value);
 #else
@@ -1078,7 +1079,7 @@
 
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class TestDebugDaemonClient : public chromeos::FakeDebugDaemonClient {
  public:
   TestDebugDaemonClient() = default;
diff --git a/rlz/test/rlz_test_helpers.cc b/rlz/test/rlz_test_helpers.cc
index 040cbdb..d64d437 100644
--- a/rlz/test/rlz_test_helpers.cc
+++ b/rlz/test/rlz_test_helpers.cc
@@ -15,6 +15,7 @@
 #include "base/notreached.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "rlz/lib/rlz_lib.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -181,16 +182,16 @@
   EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IE_HOME_PAGE, ""));
 #endif  // defined(OS_POSIX)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   statistics_provider_ =
       std::make_unique<chromeos::system::FakeStatisticsProvider>();
   chromeos::system::StatisticsProvider::SetTestProvider(
       statistics_provider_.get());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void RlzLibTestBase::TearDown() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::system::StatisticsProvider::SetTestProvider(nullptr);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
diff --git a/rlz/test/rlz_test_helpers.h b/rlz/test/rlz_test_helpers.h
index 87c3600..1a03e69 100644
--- a/rlz/test/rlz_test_helpers.h
+++ b/rlz/test/rlz_test_helpers.h
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_POSIX)
@@ -19,7 +20,7 @@
 #include "base/test/test_reg_util_win.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/fake_statistics_provider.h"
 #endif
 
@@ -58,7 +59,7 @@
   void SetUp() override;
   void TearDown() override;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<chromeos::system::FakeStatisticsProvider>
       statistics_provider_;
 #endif
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index 1a72112..462cc96 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -24,8 +24,12 @@
     "cors/cors_url_loader.h",
     "cors/cors_url_loader_factory.cc",
     "cors/cors_url_loader_factory.h",
+    "cors/preflight_cache.cc",
+    "cors/preflight_cache.h",
     "cors/preflight_controller.cc",
     "cors/preflight_controller.h",
+    "cors/preflight_result.cc",
+    "cors/preflight_result.h",
     "crash_keys.cc",
     "crash_keys.h",
     "crl_set_distributor.cc",
@@ -296,7 +300,9 @@
     "cookie_settings_unittest.cc",
     "cors/cors_url_loader_factory_unittest.cc",
     "cors/cors_url_loader_unittest.cc",
+    "cors/preflight_cache_unittest.cc",
     "cors/preflight_controller_unittest.cc",
+    "cors/preflight_result_unittest.cc",
     "data_pipe_element_reader_unittest.cc",
     "dns_config_change_manager_unittest.cc",
     "host_resolver_unittest.cc",
diff --git a/services/network/public/cpp/cors/preflight_cache.cc b/services/network/cors/preflight_cache.cc
similarity index 98%
rename from services/network/public/cpp/cors/preflight_cache.cc
rename to services/network/cors/preflight_cache.cc
index 0049fa1..1513725 100644
--- a/services/network/public/cpp/cors/preflight_cache.cc
+++ b/services/network/cors/preflight_cache.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/network/public/cpp/cors/preflight_cache.h"
+#include "services/network/cors/preflight_cache.h"
 
 #include <iterator>
 
diff --git a/services/network/public/cpp/cors/preflight_cache.h b/services/network/cors/preflight_cache.h
similarity index 88%
rename from services/network/public/cpp/cors/preflight_cache.h
rename to services/network/cors/preflight_cache.h
index 1d35796..a547d9e4 100644
--- a/services/network/public/cpp/cors/preflight_cache.h
+++ b/services/network/cors/preflight_cache.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
+#ifndef SERVICES_NETWORK_CORS_PREFLIGHT_CACHE_H_
+#define SERVICES_NETWORK_CORS_PREFLIGHT_CACHE_H_
 
 #include <map>
 #include <memory>
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "net/base/network_isolation_key.h"
 #include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/cors/preflight_result.h"
+#include "services/network/cors/preflight_result.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "url/origin.h"
 
@@ -28,7 +28,7 @@
 // https://fetch.spec.whatwg.org/#concept-cache.
 // TODO(toyoshim): We may consider to clear all cached entries when users'
 // network configuration is changed.
-class COMPONENT_EXPORT(NETWORK_CPP) PreflightCache final {
+class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightCache final {
  public:
   PreflightCache();
   ~PreflightCache();
@@ -76,4 +76,4 @@
 
 }  // namespace network
 
-#endif  // SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
+#endif  // SERVICES_NETWORK_CORS_PREFLIGHT_CACHE_H_
diff --git a/services/network/public/cpp/cors/preflight_cache_unittest.cc b/services/network/cors/preflight_cache_unittest.cc
similarity index 98%
rename from services/network/public/cpp/cors/preflight_cache_unittest.cc
rename to services/network/cors/preflight_cache_unittest.cc
index 5bcbf485..6402d04e 100644
--- a/services/network/public/cpp/cors/preflight_cache_unittest.cc
+++ b/services/network/cors/preflight_cache_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/network/public/cpp/cors/preflight_cache.h"
+#include "services/network/cors/preflight_cache.h"
 
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/services/network/cors/preflight_controller.h b/services/network/cors/preflight_controller.h
index eba04a0..69d347c 100644
--- a/services/network/cors/preflight_controller.h
+++ b/services/network/cors/preflight_controller.h
@@ -16,9 +16,9 @@
 #include "base/optional.h"
 #include "base/types/strong_alias.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/cors/preflight_cache.h"
+#include "services/network/cors/preflight_result.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
-#include "services/network/public/cpp/cors/preflight_cache.h"
-#include "services/network/public/cpp/cors/preflight_result.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
diff --git a/services/network/public/cpp/cors/preflight_result.cc b/services/network/cors/preflight_result.cc
similarity index 98%
rename from services/network/public/cpp/cors/preflight_result.cc
rename to services/network/cors/preflight_result.cc
index b31b171..198621d 100644
--- a/services/network/public/cpp/cors/preflight_result.cc
+++ b/services/network/cors/preflight_result.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/network/public/cpp/cors/preflight_result.h"
+#include "services/network/cors/preflight_result.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/services/network/public/cpp/cors/preflight_result.h b/services/network/cors/preflight_result.h
similarity index 93%
rename from services/network/public/cpp/cors/preflight_result.h
rename to services/network/cors/preflight_result.h
index 49ef199..b1b5c06 100644
--- a/services/network/public/cpp/cors/preflight_result.h
+++ b/services/network/cors/preflight_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
+#ifndef SERVICES_NETWORK_CORS_PREFLIGHT_RESULT_H_
+#define SERVICES_NETWORK_CORS_PREFLIGHT_RESULT_H_
 
 #include <memory>
 #include <string>
@@ -30,7 +30,7 @@
 // Holds CORS-preflight request results, and provides access check methods.
 // Each instance can be cached by CORS-preflight cache.
 // See https://fetch.spec.whatwg.org/#concept-cache.
-class COMPONENT_EXPORT(NETWORK_CPP) PreflightResult final {
+class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightResult final {
  public:
   static void SetTickClockForTesting(const base::TickClock* tick_clock);
 
@@ -101,4 +101,4 @@
 
 }  // namespace network
 
-#endif  // SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
+#endif  // SERVICES_NETWORK_CORS_PREFLIGHT_RESULT_H_
diff --git a/services/network/public/cpp/cors/preflight_result_unittest.cc b/services/network/cors/preflight_result_unittest.cc
similarity index 99%
rename from services/network/public/cpp/cors/preflight_result_unittest.cc
rename to services/network/cors/preflight_result_unittest.cc
index 6706561..8b8a3d28 100644
--- a/services/network/public/cpp/cors/preflight_result_unittest.cc
+++ b/services/network/cors/preflight_result_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/network/public/cpp/cors/preflight_result.h"
+#include "services/network/cors/preflight_result.h"
 
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 1ba78613..f0785ca 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -43,10 +43,6 @@
     "cors/origin_access_entry.h",
     "cors/origin_access_list.cc",
     "cors/origin_access_list.h",
-    "cors/preflight_cache.cc",
-    "cors/preflight_cache.h",
-    "cors/preflight_result.cc",
-    "cors/preflight_result.h",
     "cross_origin_embedder_policy_parser.cc",
     "cross_origin_embedder_policy_parser.h",
     "cross_origin_opener_policy_parser.cc",
@@ -316,8 +312,6 @@
     "cors/cors_unittest.cc",
     "cors/origin_access_entry_unittest.cc",
     "cors/origin_access_list_unittest.cc",
-    "cors/preflight_cache_unittest.cc",
-    "cors/preflight_result_unittest.cc",
     "cross_origin_embedder_policy_parser_unittest.cc",
     "cross_origin_opener_policy_parser_unittest.cc",
     "cross_origin_read_blocking_unittest.cc",
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index d936ceb..0fcc0a9 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -161,7 +161,7 @@
 // performed in the network service, but will instead be brokered to a separate
 // cert verification service potentially running in a different process.
 const base::Feature kCertVerifierService{"CertVerifierService",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
+                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables preprocessing requests with the Trust Tokens API Fetch flags set,
 // and handling their responses, according to the protocol.
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html
index 1e4c732..54ea3ad 100644
--- a/styleguide/c++/c++11.html
+++ b/styleguide/c++/c++11.html
@@ -293,6 +293,15 @@
 </tr>
 
 <tr>
+<td>Status</td>
+<td><code>absl::Status</code></td>
+<td>Type for returning detailed errors.</td>
+<td><a href="https://source.chromium.org/chromium/chromium/src/+/master:third_party/abseil-cpp/absl/status/status.h">status.h</a></td>
+<td>Approved for use inside a wrapper type.  Use <a href="https://source.chromium.org/chromium/chromium/src/+/master:base/strings/abseil_string_conversions.h">abseil_string_conversions.h</a> to convert to and from <a href="https://source.chromium.org/chromium/chromium/src/+/master:third_party/abseil-cpp/absl/strings/string_view.h">absl::string_view</a> so the wrapper can expose <a href="https://source.chromium.org/chromium/chromium/src/+/master:base/strings/string_piece.h">base::StringPiece</a>.  Use <a href="https://source.chromium.org/chromium/chromium/src/+/master:third_party/abseil-cpp/absl/strings/cord.h">absl::Cord</a> directly as minimally necessary to interface; do not expose in the wrapper type API.<br>
+<a href="https://groups.google.com/a/chromium.org/g/cxx/c/ImdFCSZ-NMA">Discussion thread</a></td>
+</tr>
+
+<tr>
 <td>Variant</td>
 <td><code>absl::variant</code></td>
 <td>Early adaptation of C++17 std::variant.</td>
@@ -437,14 +446,6 @@
 </tr>
 
 <tr>
-<td>Status</td>
-<td><code>absl::Status</code></td>
-<td>Type for returning detailed errors.</td>
-<td><a href="https://source.chromium.org/chromium/chromium/src/+/master:third_party/abseil-cpp/absl/status/status.h">status.h</a></td>
-<td></td>
-</tr>
-
-<tr>
 <td>StatusOr</td>
 <td><code>absl::StatusOr&lt;T&gt;</td>
 <td>An object that is either a usable value, or an error Status explaining why such a value is not present.</td>
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 17ebf34..d1fc73a 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -2730,6 +2730,9 @@
         "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/"
       },
       {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.unit_tests.filter"
+        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4402,6 +4405,9 @@
         "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/"
       },
       {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.unit_tests.filter"
+        ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index b5856e9..ca1ad06e 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -12366,8 +12366,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12392,8 +12392,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12418,8 +12418,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12447,8 +12447,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12474,8 +12474,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12499,8 +12499,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12523,8 +12523,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12544,8 +12544,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12579,8 +12579,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12613,8 +12613,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12648,8 +12648,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12683,8 +12683,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12718,8 +12718,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12753,8 +12753,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12792,8 +12792,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12836,8 +12836,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12880,8 +12880,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12924,8 +12924,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -12968,8 +12968,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13004,8 +13004,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13040,8 +13040,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13075,8 +13075,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13112,8 +13112,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13150,8 +13150,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13187,8 +13187,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -13224,8 +13224,8 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "gpu": "8086:3e92-19.0.8",
-              "os": "Ubuntu-19.04",
+              "gpu": "8086:3e92-19.0.8|8086:3e92-20.0.8",
+              "os": "Ubuntu-19.04|Ubuntu-20.04",
               "pool": "chromium.tests.gpu"
             }
           ],
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 7686a87..b08ff8f 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -12271,7 +12271,7 @@
       {
         "args": [
           "--num-retries=3",
-          "--additional-driver-flag=--enable-features=BackForwardCache",
+          "--additional-driver-flag=--enable-features=BackForwardCache:enable_same_site/true",
           "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache"
         ],
         "isolate_name": "blink_web_tests",
diff --git a/testing/buildbot/filters/chromeos.unit_tests.filter b/testing/buildbot/filters/chromeos.unit_tests.filter
index 53fd6a2..251853b 100644
--- a/testing/buildbot/filters/chromeos.unit_tests.filter
+++ b/testing/buildbot/filters/chromeos.unit_tests.filter
@@ -1,9 +1,6 @@
 # TODO(crbug.com/970790): Enable this.
--InputMethodManagerImplTest.TestEnableLayouts
+-InputMethodManagerImplTest.SetLoginDefaultWithAllowedKeyboardLayouts
 -InputMethodManagerImplTest.TestEnableLayoutsNonUsHardwareKeyboard
 -InputMethodManagerImplTest.TestEnableMultipleHardwareKeyboardLayout
--InputMethodManagerImplTest.TestLastUsedInputMethod
--InputMethodManagerImplTest.TestNextInputMethod
--InputMethodManagerImplTest.TestObserver
 # TODO(crbug.com/970806): Enable this.
 -KeyboardShortcutViewerMetadataTest.ModifyAcceleratorShouldUpdateMetadata
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 7b42fafe..e026389 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -465,8 +465,8 @@
   'linux_intel_uhd_630_stable': {
     'swarming': {
       'dimensions': {
-        'gpu': '8086:3e92-19.0.8',
-        'os': 'Ubuntu-19.04',
+        'gpu': '8086:3e92-19.0.8|8086:3e92-20.0.8',
+        'os': 'Ubuntu-19.04|Ubuntu-20.04',
         'pool': 'chromium.tests.gpu',
       },
       # Same long expiration as win10_intel_uhd_630_stable due to capacity.
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 8aa751ba..b1d2f10 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -388,7 +388,7 @@
       },
       'linux-bfcache-rel': {
         'args': [
-          '--additional-driver-flag=--enable-features=BackForwardCache',
+          '--additional-driver-flag=--enable-features=BackForwardCache:enable_same_site/true',
           '--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache',
         ],
       },
@@ -2761,11 +2761,17 @@
         ],
       },
       'linux-chromeos-dbg': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.unit_tests.filter',
+        ],
         'swarming': {
           'shards': 2,
         },
       },
       'linux-chromeos-rel': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.unit_tests.filter',
+        ],
         'swarming': {
           'shards': 2,
         },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 0beeef1..b762b15 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1334,24 +1334,6 @@
             ]
         }
     ],
-    "CertVerifierService": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "CertVerifierService"
-                    ]
-                }
-            ]
-        }
-    ],
     "ChangeExtensionEventPageSuspendDelay": [
         {
             "platforms": [
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index f4ce21f..13b0ac0 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -74,7 +74,6 @@
     "css/navigation_controls.h",
     "css/page_orientation.h",
     "css/page_size_type.h",
-    "css/screen_spanning.h",
     "custom_handlers/protocol_handler_utils.h",
     "device_memory/approximated_device_memory.h",
     "dom_storage/session_storage_namespace_id.h",
diff --git a/third_party/blink/public/common/css/screen_spanning.h b/third_party/blink/public/common/css/screen_spanning.h
deleted file mode 100644
index 6b3f5d0a..0000000
--- a/third_party/blink/public/common/css/screen_spanning.h
+++ /dev/null
@@ -1,14 +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 THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
-
-namespace blink {
-
-enum class ScreenSpanning { kNone, kSingleFoldHorizontal, kSingleFoldVertical };
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index e8e390f..8d25d55 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -5487,6 +5487,21 @@
       # WebSocket request data.
       WebSocketRequest request
 
+  # Fired upon WebTransport creation.
+  event webTransportCreated
+    parameters
+      # WebTransport identifier.
+      RequestId transportId
+      # WebTransport request URL.
+      string url
+      # Request initiator.
+      optional Initiator initiator
+
+  event webTransportClosed
+    parameters
+      # WebTransport identifier.
+      RequestId transportId
+
   experimental type PrivateNetworkRequestPolicy extends string
     enum
       Allow
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
index 697b1fe0..a0565f4 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -95,6 +95,14 @@
   return i;
 }
 
+MessagePort* CreateEntangledPort(ScriptState* script_state,
+                                 const MessagePortChannel& channel) {
+  MessagePort* const port =
+      MakeGarbageCollected<MessagePort>(*ExecutionContext::From(script_state));
+  port->Entangle(channel);
+  return port;
+}
+
 }  // namespace
 
 V8ScriptValueDeserializer::V8ScriptValueDeserializer(
@@ -183,12 +191,7 @@
     // TODO(ricea): Make ExtendableMessageEvent store an
     // UnpackedSerializedScriptValue like MessageEvent does, and then this
     // special case won't be necessary.
-    Vector<MessagePortChannel> channels;
-    for (auto& stream : serialized_script_value_->GetStreams()) {
-      channels.push_back(stream.channel);
-    }
-    transferred_stream_ports_ = MessagePort::EntanglePorts(
-        *ExecutionContext::From(script_state_), channels);
+    streams_ = std::move(serialized_script_value_->GetStreams());
   }
 
   // There's nothing else to transfer if the deserializer was not given an
@@ -558,43 +561,46 @@
       if (!TransferableStreamsEnabled())
         return nullptr;
       uint32_t index = 0;
-      if (!ReadUint32(&index) || !transferred_stream_ports_ ||
-          index >= transferred_stream_ports_->size()) {
+      if (!ReadUint32(&index) || index >= streams_.size()) {
         return nullptr;
       }
       return ReadableStream::Deserialize(
-          script_state_, (*transferred_stream_ports_)[index].Get(),
+          script_state_,
+          CreateEntangledPort(GetScriptState(), streams_[index].channel),
           exception_state);
     }
     case kWritableStreamTransferTag: {
       if (!TransferableStreamsEnabled())
         return nullptr;
       uint32_t index = 0;
-      if (!ReadUint32(&index) || !transferred_stream_ports_ ||
-          index >= transferred_stream_ports_->size()) {
+      if (!ReadUint32(&index) || index >= streams_.size()) {
         return nullptr;
       }
       return WritableStream::Deserialize(
-          script_state_, (*transferred_stream_ports_)[index].Get(),
+          script_state_,
+          CreateEntangledPort(GetScriptState(), streams_[index].channel),
           exception_state);
     }
     case kTransformStreamTransferTag: {
       if (!TransferableStreamsEnabled())
         return nullptr;
       uint32_t index = 0;
-      if (!ReadUint32(&index) || !transferred_stream_ports_ ||
+      if (!ReadUint32(&index) ||
           index == std::numeric_limits<decltype(index)>::max() ||
-          index + 1 >= transferred_stream_ports_->size()) {
+          index + 1 >= streams_.size()) {
         return nullptr;
       }
+      MessagePort* const port_for_readable =
+          CreateEntangledPort(GetScriptState(), streams_[index].channel);
+      MessagePort* const port_for_writable =
+          CreateEntangledPort(GetScriptState(), streams_[index + 1].channel);
 
       // https://streams.spec.whatwg.org/#ts-transfer
       // 1. Let readableRecord be !
       //    StructuredDeserializeWithTransfer(dataHolder.[[readable]], the
       //    current Realm).
       ReadableStream* readable = ReadableStream::Deserialize(
-          script_state_, (*transferred_stream_ports_)[index].Get(),
-          exception_state);
+          script_state_, port_for_readable, exception_state);
       if (!readable)
         return nullptr;
 
@@ -602,8 +608,7 @@
       //    StructuredDeserializeWithTransfer(dataHolder.[[writable]], the
       //    current Realm).
       WritableStream* writable = WritableStream::Deserialize(
-          script_state_, (*transferred_stream_ports_)[index + 1].Get(),
-          exception_state);
+          script_state_, port_for_writable, exception_state);
       if (!writable)
         return nullptr;
 
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
index cf8af825..b8e3309e 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
@@ -119,7 +119,7 @@
   // Message ports which were transferred in.
   const MessagePortArray* transferred_message_ports_ = nullptr;
 
-  MessagePortArray* transferred_stream_ports_ = nullptr;
+  Vector<SerializedScriptValue::Stream> streams_;
 
   // Blob info for blobs stored by index.
   const WebBlobInfoArray* blob_info_array_ = nullptr;
diff --git a/third_party/blink/renderer/build/scripts/scripts.gni b/third_party/blink/renderer/build/scripts/scripts.gni
index c8210664..7700c07 100644
--- a/third_party/blink/renderer/build/scripts/scripts.gni
+++ b/third_party/blink/renderer/build/scripts/scripts.gni
@@ -72,7 +72,7 @@
 # on Posix we want to run the system one on the path.
 if (host_os == "win") {
   gperf_exe = rebase_path("//third_party/gperf/bin/gperf.exe", root_build_dir)
-} else if (is_mac) {
+} else if (host_os == "mac") {
   gperf_exe = mac_bin_path + "gperf"
 } else {
   gperf_exe = "gperf"
diff --git a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
index 1cb90c8..b533148b 100644
--- a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
+++ b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include "base/metrics/histogram_functions.h"
 #include "third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h"
 
 namespace blink {
@@ -17,14 +18,8 @@
 constexpr char ContentCaptureTaskHistogramReporter::kTaskRunsPerCapture[];
 
 ContentCaptureTaskHistogramReporter::ContentCaptureTaskHistogramReporter()
-    : capture_content_delay_time_histogram_(kCaptureContentDelayTime,
-                                            500,
-                                            30000,
-                                            50),
-      capture_content_time_histogram_(kCaptureContentTime, 0, 50000, 50),
+    : capture_content_time_histogram_(kCaptureContentTime, 0, 50000, 50),
       send_content_time_histogram_(kSendContentTime, 0, 50000, 50),
-      sent_content_count_histogram_(kSentContentCount, 0, 10000, 50),
-      task_delay_time_in_ms_histogram_(kTaskDelayInMs, 1, 128000, 100),
       task_runs_per_capture_histogram_(kTaskRunsPerCapture, 0, 100, 50) {}
 
 ContentCaptureTaskHistogramReporter::~ContentCaptureTaskHistogramReporter() =
@@ -45,9 +40,10 @@
 
 void ContentCaptureTaskHistogramReporter::OnTaskRun() {
   if (!task_scheduled_time_.is_null()) {
-    task_delay_time_in_ms_histogram_.CountMilliseconds(base::TimeTicks::Now() -
-                                                       task_scheduled_time_);
-    task_scheduled_time_ = base::TimeTicks();
+    base::UmaHistogramCustomTimes(kTaskDelayInMs,
+                                  base::TimeTicks::Now() - task_scheduled_time_,
+                                  base::TimeDelta::FromMilliseconds(1),
+                                  base::TimeDelta::FromSeconds(128), 100);
   }
   task_runs_per_capture_++;
 }
@@ -81,8 +77,10 @@
   if (captured_content_change_time_) {
     base::TimeTicks content_change_time = captured_content_change_time_.value();
     captured_content_change_time_.reset();
-    capture_content_delay_time_histogram_.CountMilliseconds(
-        now - content_change_time);
+    base::UmaHistogramCustomTimes(kCaptureContentDelayTime,
+                                  now - content_change_time,
+                                  base::TimeDelta::FromMilliseconds(500),
+                                  base::TimeDelta::FromSeconds(30), 50);
   }
   if (!sent_content_count)
     return;
@@ -97,7 +95,7 @@
 
 void ContentCaptureTaskHistogramReporter::RecordsSentContentCountPerDocument(
     size_t sent_content_count) {
-  sent_content_count_histogram_.Count(sent_content_count);
+  base::UmaHistogramCounts10000(kSentContentCount, sent_content_count);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
index 388633de..4201456d 100644
--- a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
+++ b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.h
@@ -22,7 +22,8 @@
   static constexpr char kCaptureContentTime[] =
       "ContentCapture.CaptureContentTime2";
   static constexpr char kSendContentTime[] = "ContentCapture.SendContentTime";
-  static constexpr char kSentContentCount[] = "ContentCapture.SentContentCount";
+  static constexpr char kSentContentCount[] =
+      "ContentCapture.SentContentCount2";
   static constexpr char kTaskDelayInMs[] = "ContentCapture.TaskDelayTimeInMs";
   static constexpr char kTaskRunsPerCapture[] =
       "ContentCapture.TaskRunsPerCapture";
@@ -66,21 +67,12 @@
   // and sending the content.
   size_t task_runs_per_capture_ = 0;
 
-  // Records time from first content change to content that has been sent, its
-  // range is 500ms from to 30s.
-  CustomCountHistogram capture_content_delay_time_histogram_;
   // Records time to capture the content, its range is from 0 to 50,000
   // microseconds.
   CustomCountHistogram capture_content_time_histogram_;
   // Records time to send the content, its range is from 0 to 50,000
   // microseconds.
   CustomCountHistogram send_content_time_histogram_;
-  // Records total count has been sent, its range is from 0 to 10,000.
-  LinearHistogram sent_content_count_histogram_;
-  // Records time taken for the task to start after it is schedule, its range is
-  // 1ms to 128s. The time of task that was scheduled for the retry wasn't
-  // measured because it is always 500ms.
-  CustomCountHistogram task_delay_time_in_ms_histogram_;
   // Records the number of times ContentCapture task run to complete a capture
   // which includes capturing and sending the content.
   CustomCountHistogram task_runs_per_capture_histogram_;
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc
index 9fae71a..d67e83e9 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -31,7 +31,7 @@
 
 #include "third_party/blink/public/common/css/forced_colors.h"
 #include "third_party/blink/public/common/css/navigation_controls.h"
-#include "third_party/blink/public/common/css/screen_spanning.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
 
 #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index c900d3e..3f0434b 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -7,8 +7,8 @@
 #include <memory>
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/css/forced_colors.h"
-#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/renderer/core/css/media_list.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
 #include "third_party/blink/renderer/core/css/media_values_cached.h"
 #include "third_party/blink/renderer/core/css/media_values_initial_viewport.h"
 #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
index 61791fb6..8214cef 100644
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -4,12 +4,12 @@
 
 #include "third_party/blink/renderer/core/css/media_values.h"
 
-#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/public/common/widget/screen_info.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_theme_engine.h"
 #include "third_party/blink/renderer/core/css/css_resolution_units.h"
 #include "third_party/blink/renderer/core/css/media_feature_overrides.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
 #include "third_party/blink/renderer/core/css/media_values_cached.h"
 #include "third_party/blink/renderer/core/css/media_values_dynamic.h"
 #include "third_party/blink/renderer/core/dom/document.h"
diff --git a/third_party/blink/renderer/core/css/media_values.h b/third_party/blink/renderer/core/css/media_values.h
index 88640e7..ce13d87 100644
--- a/third_party/blink/renderer/core/css/media_values.h
+++ b/third_party/blink/renderer/core/css/media_values.h
@@ -23,7 +23,7 @@
 enum class ColorSpaceGamut;
 enum class ForcedColors;
 enum class NavigationControls;
-enum class ScreenSpanning;
+enum class ScreenSpanning { kNone, kSingleFoldHorizontal, kSingleFoldVertical };
 
 mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
     CSSValueID id);
diff --git a/third_party/blink/renderer/core/css/media_values_cached.cc b/third_party/blink/renderer/core/css/media_values_cached.cc
index 7420c85..2c5094a 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -6,10 +6,10 @@
 
 #include "third_party/blink/public/common/css/forced_colors.h"
 #include "third_party/blink/public/common/css/navigation_controls.h"
-#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink.h"
 #include "third_party/blink/public/mojom/css/preferred_contrast.mojom-blink.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index 78bceb89..427890fc 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/css/css_value_pair.h"
 #include "third_party/blink/renderer/core/css/css_value_pool.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
+#include "third_party/blink/renderer/core/css/properties/longhand.h"
 #include "third_party/blink/renderer/core/css_value_keywords.h"
 #include "third_party/blink/renderer/core/style_property_shorthand.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -1108,10 +1109,29 @@
     const StylePropertyShorthand& width,
     const StylePropertyShorthand& style,
     const StylePropertyShorthand& color) const {
-  const StylePropertyShorthand properties[3] = {width, style, color};
+  const CSSProperty* border_image_properties[] = {
+      &GetCSSPropertyBorderImageSource(), &GetCSSPropertyBorderImageSlice(),
+      &GetCSSPropertyBorderImageWidth(), &GetCSSPropertyBorderImageOutset(),
+      &GetCSSPropertyBorderImageRepeat()};
+
+  // If any of the border-image longhands differ from their initial
+  // specified values, we should not serialize to a border shorthand
+  // declaration.
+  for (const auto* border_image_property : border_image_properties) {
+    const CSSValue* value =
+        property_set_.GetPropertyCSSValue(*border_image_property);
+    const CSSValue* initial_specified_value =
+        To<Longhand>(*border_image_property).InitialValue();
+    if (value && !value->IsInitialValue() &&
+        *value != *initial_specified_value) {
+      return String();
+    }
+  }
+
+  const StylePropertyShorthand shorthand_properties[3] = {width, style, color};
   StringBuilder result;
-  for (size_t i = 0; i < base::size(properties); ++i) {
-    String value = GetCommonValue(properties[i]);
+  for (const auto& shorthand_property : shorthand_properties) {
+    const String value = GetCommonValue(shorthand_property);
     if (value.IsNull())
       return String();
     if (value == "initial")
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index e83d286..6a2683a 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -1374,15 +1374,28 @@
   const Node& node = *position.ComputeContainerNode();
   if (HasEditableStyle(node))
     return position_with_affinity;
+  // TODO(yosin): Once we fix |MostBackwardCaretPosition()| to handle
+  // positions other than |kOffsetInAnchor|, we don't need to use
+  // |adjusted_position|, e.g. <outer><inner contenteditable> with position
+  // before <inner> vs. outer@0[1].
+  // [1] editing/selection/click-outside-editable-div.html
+  const Position& adjusted_position = HasEditableStyle(*position.AnchorNode())
+                                          ? position.ToOffsetInAnchor()
+                                          : position;
   const Position& forward =
-      MostForwardCaretPosition(position, kCanCrossEditingBoundary);
+      MostForwardCaretPosition(adjusted_position, kCanCrossEditingBoundary);
   if (HasEditableStyle(*forward.ComputeContainerNode()))
     return PositionWithAffinity(forward);
   const Position& backward =
-      MostBackwardCaretPosition(position, kCanCrossEditingBoundary);
+      MostBackwardCaretPosition(adjusted_position, kCanCrossEditingBoundary);
   if (HasEditableStyle(*backward.ComputeContainerNode()))
     return PositionWithAffinity(backward);
-  return position_with_affinity;
+  return PositionWithAffinity(adjusted_position,
+                              position_with_affinity.Affinity());
+}
+
+PositionWithAffinity AdjustForEditingBoundary(const Position& position) {
+  return AdjustForEditingBoundary(PositionWithAffinity(position));
 }
 
 Position ComputePositionForNodeRemoval(const Position& position,
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.h b/third_party/blink/renderer/core/editing/editing_utilities.h
index 15fd671..0bd17e4 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.h
+++ b/third_party/blink/renderer/core/editing/editing_utilities.h
@@ -273,6 +273,7 @@
 //  =>
 //  <editable>|<non-editable>abc</non-editable></editable>
 PositionWithAffinity AdjustForEditingBoundary(const PositionWithAffinity&);
+PositionWithAffinity AdjustForEditingBoundary(const Position&);
 
 CORE_EXPORT Position ComputePositionForNodeRemoval(const Position&,
                                                    const Node&);
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc
index cd10e3e..9807ced0 100644
--- a/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -674,6 +674,14 @@
       position.AnchorNode(), Strategy::CaretMaxOffset(*position.AnchorNode()));
 }
 
+// TODO(yosin): We should make |Most{Back,For}kwardCaretPosition()| to work for
+// positions other than |kOffsetInAnchor|. When we convert |position| to
+// |kOffsetInAnchor|, following tests are failed:
+//  * editing/execCommand/delete-non-editable-range-crash.html
+//  * editing/execCommand/keep_typing_style.html
+//  * editing/selection/skip-over-contenteditable.html
+// See also |AdjustForEditingBoundary()|. It has workaround for before/after
+// positions.
 template <typename Strategy>
 static PositionTemplate<Strategy> MostBackwardCaretPosition(
     const PositionTemplate<Strategy>& position,
diff --git a/third_party/blink/renderer/core/execution_context/DEPS b/third_party/blink/renderer/core/execution_context/DEPS
new file mode 100644
index 0000000..292eac7
--- /dev/null
+++ b/third_party/blink/renderer/core/execution_context/DEPS
@@ -0,0 +1,7 @@
+specific_include_rules = {
+  "agent_metrics_collector\.cc": [
+    # Intentionally limited to scope to encourage use of histogram helpers over
+    # the raw factory getters.
+    "+base/metrics/histogram_base.h",
+  ],
+}
diff --git a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc b/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
index 18eff6e..4a30d7a6 100644
--- a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
+++ b/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
@@ -4,14 +4,14 @@
 
 #include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
 
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_base.h"
 #include "base/time/default_tick_clock.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/core/execution_context/window_agent.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/web_test_support.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -116,10 +116,10 @@
 }
 
 void AgentMetricsCollector::AddTimeToTotalAgents(int time_delta_to_add) {
-  DEFINE_STATIC_LOCAL(LinearHistogram, agents_per_renderer_histogram,
-                      (kAgentsPerRendererByTimeHistogram, 1, 100, 101));
-  agents_per_renderer_histogram.CountMany(agent_to_windows_map_.size(),
-                                          time_delta_to_add);
+  base::LinearHistogram::FactoryGet(
+      kAgentsPerRendererByTimeHistogram, 1, 100, 101,
+      base::HistogramBase::kUmaTargetedHistogramFlag)
+      ->AddCount(agent_to_windows_map_.size(), time_delta_to_add);
 }
 
 void AgentMetricsCollector::ReportToBrowser() {
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index 338d2af..6b180dc 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -1676,6 +1676,35 @@
       base::TimeTicks::Now().since_origin().InSecondsF(), error_message);
 }
 
+void InspectorNetworkAgent::WebTransportCreated(
+    ExecutionContext* execution_context,
+    uint64_t transport_id,
+    const KURL& request_url) {
+  std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
+      current_stack_trace =
+          SourceLocation::Capture(execution_context)->BuildInspectorObject();
+  if (!current_stack_trace) {
+    GetFrontend()->webTransportCreated(
+        IdentifiersFactory::SubresourceRequestId(transport_id),
+        UrlWithoutFragment(request_url).GetString());
+    return;
+  }
+
+  std::unique_ptr<protocol::Network::Initiator> initiator_object =
+      protocol::Network::Initiator::create()
+          .setType(protocol::Network::Initiator::TypeEnum::Script)
+          .build();
+  initiator_object->setStack(std::move(current_stack_trace));
+  GetFrontend()->webTransportCreated(
+      IdentifiersFactory::SubresourceRequestId(transport_id),
+      UrlWithoutFragment(request_url).GetString(), std::move(initiator_object));
+}
+
+void InspectorNetworkAgent::WebTransportClosed(uint64_t transport_id) {
+  GetFrontend()->webTransportClosed(
+      IdentifiersFactory::SubresourceRequestId(transport_id));
+}
+
 Response InspectorNetworkAgent::enable(Maybe<int> total_buffer_size,
                                        Maybe<int> resource_buffer_size,
                                        Maybe<int> max_post_data_size) {
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
index 6b25073..3b0199c0 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -196,6 +196,12 @@
                                const char* payload,
                                size_t payload_length);
   void DidReceiveWebSocketMessageError(uint64_t identifier, const String&);
+
+  void WebTransportCreated(ExecutionContext*,
+                           uint64_t transport_id,
+                           const KURL& request_url);
+  void WebTransportClosed(uint64_t transport_id);
+
   void SetDevToolsIds(ResourceRequest& request, const FetchInitiatorInfo&);
 
   // Called from frontend
diff --git a/third_party/blink/renderer/core/layout/api/line_layout_item.h b/third_party/blink/renderer/core/layout/api/line_layout_item.h
index 03165f6..0b1a61b 100644
--- a/third_party/blink/renderer/core/layout/api/line_layout_item.h
+++ b/third_party/blink/renderer/core/layout/api/line_layout_item.h
@@ -273,6 +273,14 @@
     return layout_object_->CreatePositionWithAffinity(offset, affinity);
   }
 
+  PositionWithAffinity PositionAfterThis() const {
+    return layout_object_->PositionAfterThis();
+  }
+
+  PositionWithAffinity PositionBeforeThis() const {
+    return layout_object_->PositionBeforeThis();
+  }
+
   LineLayoutItem PreviousInPreOrder(const LayoutObject* stay_within) const {
     return LineLayoutItem(layout_object_->PreviousInPreOrder(stay_within));
   }
diff --git a/third_party/blink/renderer/core/layout/hit_testing_test.cc b/third_party/blink/renderer/core/layout/hit_testing_test.cc
index 76f912f..a6f7248 100644
--- a/third_party/blink/renderer/core/layout/hit_testing_test.cc
+++ b/third_party/blink/renderer/core/layout/hit_testing_test.cc
@@ -4,7 +4,9 @@
 
 #include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/editing/text_affinity.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 
 namespace blink {
 
@@ -137,4 +139,38 @@
   EXPECT_EQ(result.InnerNode(), occluder);
 }
 
+// crbug.com/1153037
+TEST_F(HitTestingTest, LegacyInputElementInFragmentTraversal) {
+  ScopedLayoutNGFragmentTraversalForTest fragment_traversal_feature(true);
+  ScopedEditingNGForTest editing_feature(false);
+
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      body { margin:100px; }
+    </style>
+    <input id="target">
+  )HTML");
+
+  const HitTestRequest hit_request(HitTestRequest::kActive);
+  const HitTestLocation hit_location(PhysicalOffset(110, 110));
+  HitTestResult hit_result(hit_request, hit_location);
+  ASSERT_TRUE(GetLayoutView().HitTest(hit_location, hit_result));
+  ASSERT_TRUE(hit_result.InnerNode());
+  const auto* layout_object = hit_result.InnerNode()->GetLayoutObject();
+  ASSERT_TRUE(layout_object);
+
+  // In this test we'll use the legacy layout engine for form controls, so the
+  // INPUT element will generate a LayoutTextControl with an inner editable
+  // LayoutBlockFlow child. We'll hit-test by traversing the fragment tree
+  // (rather than the LayoutObject tree). We should hit the inner
+  // LayoutBlockFlow. Since it is a legacy object and it is also laid out by a
+  // legacy parent, it will not generate any NG fragments. Check that we hit the
+  // right node, and that the hit-testing code hasn't incorrectly set an NG
+  // fragment from an ancestor.
+
+  ASSERT_EQ(layout_object->Parent()->GetNode(),
+            GetDocument().getElementById("target"));
+  EXPECT_FALSE(hit_result.BoxFragment());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 6ca2f9db..4ca3409 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -1318,15 +1318,18 @@
   if (!box)
     return Position();
 
-  if (!box->GetLineLayoutItem().NonPseudoNode())
-    return Position::EditingPositionOf(
-        NonPseudoNode(), start ? CaretMinOffset() : CaretMaxOffset());
+  Node* const node = box->GetLineLayoutItem().NonPseudoNode();
+  if (!node) {
+    if (start)
+      return Position::FirstPositionInOrBeforeNode(*NonPseudoNode());
+    return Position::LastPositionInOrAfterNode(*NonPseudoNode());
+  }
 
-  if (!box->IsInlineTextBox())
-    return Position::EditingPositionOf(
-        box->GetLineLayoutItem().NonPseudoNode(),
-        start ? box->GetLineLayoutItem().CaretMinOffset()
-              : box->GetLineLayoutItem().CaretMaxOffset());
+  if (!box->IsInlineTextBox()) {
+    if (start)
+      return Position::FirstPositionInOrBeforeNode(*node);
+    return Position::LastPositionInOrAfterNode(*node);
+  }
 
   auto* text_box = To<InlineTextBox>(box);
   return Position::EditingPositionOf(
@@ -1382,10 +1385,14 @@
   LayoutUnit logical_left = IsHorizontalWritingMode()
                                 ? point_in_child_coordinates.left
                                 : point_in_child_coordinates.top;
-  if (logical_left < child_middle)
-    return ancestor->CreatePositionWithAffinity(child_node->NodeIndex());
-  return ancestor->CreatePositionWithAffinity(child_node->NodeIndex() + 1,
-                                              TextAffinity::kUpstream);
+  if (logical_left < child_middle) {
+    if (IsUserSelectContain(*ancestor->NonPseudoNode()))
+      return ancestor->PositionBeforeThis();
+    return child.PositionBeforeThis();
+  }
+  if (IsUserSelectContain(*ancestor->NonPseudoNode()))
+    return ancestor->PositionAfterThis();
+  return child.PositionAfterThis();
 }
 
 PositionWithAffinity LayoutBlock::PositionForPointIfOutsideAtomicInlineLevel(
@@ -1396,13 +1403,13 @@
       point.ConvertToLogical({StyleRef().GetWritingMode(), ResolvedDirection()},
                              PhysicalSize(Size()), PhysicalSize());
   if (logical_offset.inline_offset < 0)
-    return CreatePositionWithAffinity(CaretMinOffset());
+    return FirstPositionInOrBeforeThis();
   if (logical_offset.inline_offset >= LogicalWidth())
-    return CreatePositionWithAffinity(CaretMaxOffset());
+    return LastPositionInOrAfterThis();
   if (logical_offset.block_offset < 0)
-    return CreatePositionWithAffinity(CaretMinOffset());
+    return FirstPositionInOrBeforeThis();
   if (logical_offset.block_offset >= LogicalHeight())
-    return CreatePositionWithAffinity(CaretMaxOffset());
+    return LastPositionInOrAfterThis();
   return PositionWithAffinity();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index f1ed3479..23b9a8a 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -6565,19 +6565,16 @@
   // offset 0
   LayoutObject* first_child = SlowFirstChild();
   if (!first_child)
-    return CreatePositionWithAffinity(
-        NonPseudoNode() ? FirstPositionInOrBeforeNode(*NonPseudoNode())
-                        : Position());
+    return FirstPositionInOrBeforeThis();
 
   if (IsTable() && NonPseudoNode()) {
-    const Node& node = *NonPseudoNode();
     LayoutUnit x_in_block_direction = FlipForWritingMode(point.left);
     if (x_in_block_direction < 0 || x_in_block_direction > Size().Width() ||
         point.top < 0 || point.top > Size().Height()) {
       if (x_in_block_direction <= Size().Width() / 2) {
-        return CreatePositionWithAffinity(FirstPositionInOrBeforeNode(node));
+        return FirstPositionInOrBeforeThis();
       }
-      return CreatePositionWithAffinity(LastPositionInOrAfterNode(node));
+      return LastPositionInOrAfterThis();
     }
   }
 
@@ -6659,9 +6656,7 @@
     return closest_layout_object->PositionForPoint(
         adjusted_point - closest_layout_object->PhysicalLocation());
   }
-  return CreatePositionWithAffinity(
-      NonPseudoNode() ? FirstPositionInOrBeforeNode(*NonPseudoNode())
-                      : Position());
+  return FirstPositionInOrBeforeThis();
 }
 
 DISABLE_CFI_PERF
diff --git a/third_party/blink/renderer/core/layout/layout_br.cc b/third_party/blink/renderer/core/layout/layout_br.cc
index cb96635..b23f1d4 100644
--- a/third_party/blink/renderer/core/layout/layout_br.cc
+++ b/third_party/blink/renderer/core/layout/layout_br.cc
@@ -62,7 +62,7 @@
 
 PositionWithAffinity LayoutBR::PositionForPoint(const PhysicalOffset&) const {
   NOT_DESTROYED();
-  return CreatePositionWithAffinity(0);
+  return PositionBeforeThis();
 }
 
 Position LayoutBR::PositionForCaretOffset(unsigned offset) const {
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index e07879f..80413ef8 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1159,7 +1159,8 @@
         // ideally store the containing box fragment in the hit-test result
         // here, but doing that might prevent us from finding the right fragment
         // item later on in PositionForPoint(), if the inline has been offset
-        // from its static position.
+        // from its static position. So clear it.
+        result.SetBoxFragment(nullptr);
         return true;
       }
     }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index df934163..9e6f3957 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -4153,27 +4153,15 @@
   NOT_DESTROYED();
   // If this is a non-anonymous layoutObject in an editable area, then it's
   // simple.
-  if (Node* node = NonPseudoNode()) {
-    if (!HasEditableStyle(*node)) {
-      // If it can be found, we prefer a visually equivalent position that is
-      // editable.
-      // TODO(layout-dev): Once we fix callers of |CreatePositionWithAffinity()|
-      // we should use |Position| constructor. See http://crbug.com/827923
-      const Position position =
-          Position::CreateWithoutValidationDeprecated(*node, offset);
-      Position candidate =
-          MostForwardCaretPosition(position, kCanCrossEditingBoundary);
-      if (HasEditableStyle(*candidate.AnchorNode()))
-        return PositionWithAffinity(candidate, affinity);
-      candidate = MostBackwardCaretPosition(position, kCanCrossEditingBoundary);
-      if (HasEditableStyle(*candidate.AnchorNode()))
-        return PositionWithAffinity(candidate, affinity);
-    }
-    // FIXME: Eliminate legacy editing positions
-    return PositionWithAffinity(Position::EditingPositionOf(node, offset),
-                                affinity);
-  }
+  Node* const node = NonPseudoNode();
+  if (!node)
+    return FindPosition();
+  return AdjustForEditingBoundary(
+      PositionWithAffinity(Position(node, offset), affinity));
+}
 
+PositionWithAffinity LayoutObject::FindPosition() const {
+  NOT_DESTROYED();
   // We don't want to cross the boundary between editable and non-editable
   // regions of the document, but that is either impossible or at least
   // extremely unlikely in any normal case because we stop as soon as we
@@ -4211,22 +4199,40 @@
   return PositionWithAffinity();
 }
 
+PositionWithAffinity LayoutObject::FirstPositionInOrBeforeThis() const {
+  NOT_DESTROYED();
+  if (Node* node = NonPseudoNode())
+    return AdjustForEditingBoundary(FirstPositionInOrBeforeNode(*node));
+  return FindPosition();
+}
+
+PositionWithAffinity LayoutObject::LastPositionInOrAfterThis() const {
+  NOT_DESTROYED();
+  if (Node* node = NonPseudoNode())
+    return AdjustForEditingBoundary(LastPositionInOrAfterNode(*node));
+  return FindPosition();
+}
+
+PositionWithAffinity LayoutObject::PositionAfterThis() const {
+  NOT_DESTROYED();
+  if (Node* node = NonPseudoNode())
+    return AdjustForEditingBoundary(Position::AfterNode(*node));
+  return FindPosition();
+}
+
+PositionWithAffinity LayoutObject::PositionBeforeThis() const {
+  NOT_DESTROYED();
+  if (Node* node = NonPseudoNode())
+    return AdjustForEditingBoundary(Position::BeforeNode(*node));
+  return FindPosition();
+}
+
 PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
     int offset) const {
   NOT_DESTROYED();
   return CreatePositionWithAffinity(offset, TextAffinity::kDownstream);
 }
 
-PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
-    const Position& position) const {
-  NOT_DESTROYED();
-  if (position.IsNotNull())
-    return PositionWithAffinity(position);
-
-  DCHECK(!NonPseudoNode());
-  return CreatePositionWithAffinity(0);
-}
-
 CursorDirective LayoutObject::GetCursor(const PhysicalOffset&,
                                         ui::Cursor&) const {
   NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 39baae8c..3aea8e86 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2168,7 +2168,11 @@
   PositionWithAffinity CreatePositionWithAffinity(int offset,
                                                   TextAffinity) const;
   PositionWithAffinity CreatePositionWithAffinity(int offset) const;
-  PositionWithAffinity CreatePositionWithAffinity(const Position&) const;
+  PositionWithAffinity FindPosition() const;
+  PositionWithAffinity FirstPositionInOrBeforeThis() const;
+  PositionWithAffinity LastPositionInOrAfterThis() const;
+  PositionWithAffinity PositionAfterThis() const;
+  PositionWithAffinity PositionBeforeThis() const;
 
   virtual void DirtyLinesFromChangedChild(
       LayoutObject*,
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc
index 93d30845..00c8003b 100644
--- a/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -986,6 +986,7 @@
 PositionWithAffinity LayoutReplaced::PositionForPoint(
     const PhysicalOffset& point) const {
   NOT_DESTROYED();
+
   LayoutUnit top;
   LayoutUnit bottom;
   std::tie(top, bottom) = SelectionTopAndBottom(*this);
@@ -1000,20 +1001,18 @@
                                            : flipped_point_in_container.Y();
 
   if (block_direction_position < top)
-    return CreatePositionWithAffinity(
-        CaretMinOffset());  // coordinates are above
+    return PositionBeforeThis();  // coordinates are above
 
   if (block_direction_position >= bottom)
-    return CreatePositionWithAffinity(
-        CaretMaxOffset());  // coordinates are below
+    return PositionBeforeThis();  // coordinates are below
 
   if (GetNode()) {
     const bool is_at_left_side =
         line_direction_position <= LogicalLeft() + (LogicalWidth() / 2);
     const bool is_at_start = is_at_left_side == IsLtr(ResolvedDirection());
-    // TODO(crbug.com/827923): Stop creating positions using int offsets on
-    // non-text nodes.
-    return CreatePositionWithAffinity(is_at_start ? 0 : 1);
+    if (is_at_start)
+      return PositionBeforeThis();
+    return PositionAfterThis();
   }
 
   return LayoutBox::PositionForPoint(point);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
index a0fd6be..77889aea 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -651,6 +651,10 @@
 
   void MoveToPreviousSibling();
 
+  const NGPhysicalBoxFragment& ContainerFragment() const {
+    return cursor_.ContainerFragment();
+  }
+
  private:
   NGInlineCursorPosition current_;
   const NGInlineCursor& cursor_;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
index a7bfad1f..6c2da499 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
@@ -910,7 +910,7 @@
       SetupCursor("<div id=root>a<b id=target><div>x</div></b></div>");
   const Element& target = *GetElementById("target");
   cursor.MoveTo(*target.GetLayoutObject());
-  EXPECT_EQ(PositionWithAffinity(Position(target, 0)),
+  EXPECT_EQ(PositionWithAffinity(Position::FirstPositionInNode(target)),
             cursor.PositionForPointInChild(PhysicalOffset()));
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
index 2cf1279..ef5ac67 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
@@ -20,7 +20,7 @@
 PositionWithAffinity LayoutNGInsideListMarker::PositionForPoint(
     const PhysicalOffset&) const {
   NOT_DESTROYED();
-  return CreatePositionWithAffinity(0);
+  return PositionBeforeThis();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
index 4507904..471d8de 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
@@ -35,7 +35,7 @@
 
 PositionWithAffinity LayoutNGOutsideListMarker::PositionForPoint(
     const PhysicalOffset&) const {
-  return CreatePositionWithAffinity(0);
+  return PositionBeforeThis();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index aabfb7b..8524a584 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -924,9 +924,8 @@
   LogicalSize child_logical_size = converter.ToLogical(child.Size());
   LayoutUnit child_middle = child_logical_size.inline_size / 2;
   if (logical_point_in_child.inline_offset < child_middle)
-    return layout_object_->CreatePositionWithAffinity(child_node->NodeIndex());
-  return layout_object_->CreatePositionWithAffinity(child_node->NodeIndex() + 1,
-                                                    TextAffinity::kUpstream);
+    return child.GetLayoutObject()->PositionBeforeThis();
+  return child.GetLayoutObject()->PositionAfterThis();
 }
 
 UBiDiLevel NGPhysicalBoxFragment::BidiLevel() const {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 79617a86a..60c1894 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -359,18 +359,10 @@
 void UpdateHitTestResult(HitTestResult& result,
                          const NGPhysicalBoxFragment& fragment,
                          PhysicalOffset offset) {
-  Node* node = fragment.NodeForHitTest();
-  if (!node)
+  if (result.InnerNode())
     return;
-
-  // We may already have set an inner node, but not a box fragment, if the inner
-  // node was text or non-atomic inline content. Set the containing box fragment
-  // now, unless it's an anonymous CSS box.
-  if (!result.BoxFragment() && (!fragment.IsCSSBox() || fragment.GetNode()))
-    result.SetBoxFragment(&fragment);
-
-  if (!result.InnerNode())
-    result.SetNodeAndPosition(node, offset);
+  if (Node* node = fragment.NodeForHitTest())
+    result.SetNodeAndPosition(node, &fragment, offset);
 }
 
 // Return an ID for this fragmentainer, which is unique within the fragmentation
@@ -2141,12 +2133,14 @@
     return false;
 
   return hit_test.AddNodeToResult(
-      text_fragment.NodeForHitTest(), /* box_fragment */ nullptr, rect,
+      text_fragment.NodeForHitTest(), &cursor.ContainerFragment(), rect,
       physical_offset - text_paint_fragment->OffsetInContainerFragment());
 }
 
-bool NGBoxFragmentPainter::HitTestTextItem(const HitTestContext& hit_test,
-                                           const NGFragmentItem& text_item) {
+bool NGBoxFragmentPainter::HitTestTextItem(
+    const HitTestContext& hit_test,
+    const NGFragmentItem& text_item,
+    const NGInlineBackwardCursor& cursor) {
   DCHECK(text_item.IsText());
 
   if (hit_test.action != kHitTestForeground)
@@ -2168,7 +2162,7 @@
     return false;
 
   return hit_test.AddNodeToResult(text_item.NodeForHitTest(),
-                                  /* box_fragment */ nullptr, rect,
+                                  &cursor.ContainerFragment(), rect,
                                   hit_test.inline_root_offset);
 }
 
@@ -2328,7 +2322,7 @@
     bounds_rect = PhysicalRect(PixelSnappedIntRect(bounds_rect));
     if (hit_test.location.Intersects(bounds_rect)) {
       if (hit_test.AddNodeToResult(item.NodeForHitTest(),
-                                   /* box_fragment */ nullptr, bounds_rect,
+                                   &cursor.ContainerFragment(), bounds_rect,
                                    child_offset))
         return true;
     }
@@ -2501,7 +2495,7 @@
     }
 
     if (item->IsText()) {
-      if (HitTestTextItem(hit_test, *item))
+      if (HitTestTextItem(hit_test, *item, cursor))
         return true;
     } else if (item->Type() == NGFragmentItem::kLine) {
       const NGPhysicalLineBoxFragment* child_fragment = item->LineBoxFragment();
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index 7aabb96f..6558329 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -271,7 +271,8 @@
                            const NGInlineBackwardCursor& cursor,
                            const PhysicalOffset& physical_offset);
   bool HitTestTextItem(const HitTestContext& hit_test,
-                       const NGFragmentItem& text_item);
+                       const NGFragmentItem& text_item,
+                       const NGInlineBackwardCursor& cursor);
 
   // Hit tests the given line box fragment.
   // @param physical_offset Physical offset of the line box fragment in paint
diff --git a/third_party/blink/renderer/core/probe/core_probes.json5 b/third_party/blink/renderer/core/probe/core_probes.json5
index f15a5dc7..a3850e6 100644
--- a/third_party/blink/renderer/core/probe/core_probes.json5
+++ b/third_party/blink/renderer/core/probe/core_probes.json5
@@ -172,6 +172,8 @@
         "ShouldBlockRequest",
         "ShouldBypassServiceWorker",
         "ShouldForceCorsPreflight",
+        "WebTransportCreated",
+        "WebTransportClosed",
         "WillDispatchEventSourceEvent",
         "WillLoadXHR",
         "WillSendEventSourceRequest",
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl
index 2c6c58cc..bed43f34 100644
--- a/third_party/blink/renderer/core/probe/core_probes.pidl
+++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -133,6 +133,8 @@
   void DidReceiveWebSocketMessage(ExecutionContext*, uint64_t identifier, int opcode, bool masked, const Vector<base::span<const char>>& data);
   void DidSendWebSocketMessage(ExecutionContext*, uint64_t identifier, int opcode, bool masked, const char* payload, size_t payload_length);
   void DidReceiveWebSocketMessageError(ExecutionContext*, uint64_t identifier, const String& error_message);
+  void WebTransportCreated([Keep] ExecutionContext*, uint64_t transport_id, const KURL& request_url);
+  void WebTransportClosed(ExecutionContext*, uint64_t transport_id);
   void NetworkStateChanged([Keep] LocalFrame*, bool online);
   void UpdateApplicationCacheStatus([Keep] LocalFrame*);
   /* This is for pre-BlinkGenPropertyTrees. TODO(wangxianzhu): Remove this function for BlinkGenPropertyTrees. */
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_metrics.cc b/third_party/blink/renderer/modules/credentialmanager/credential_metrics.cc
index 0dd32f13..6aefd4c1 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credential_metrics.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credential_metrics.cc
@@ -13,19 +13,25 @@
 void RecordSmsOutcome(WebOTPServiceOutcome outcome,
                       ukm::SourceId source_id,
                       ukm::UkmRecorder* ukm_recorder) {
+  // In |SmsBrowserTest| we wait for UKM to be recorded to avoid race condition
+  // between outcome capture and evaluation. Recording UMA before UKM makes sure
+  // that |FetchHistogramsFromChildProcesses| reaches the child processes after
+  // UMA is recorded.
+  UMA_HISTOGRAM_ENUMERATION("Blink.Sms.Receive.Outcome", outcome);
+
   DCHECK_NE(source_id, ukm::kInvalidSourceId);
   DCHECK(ukm_recorder);
 
   ukm::builders::SMSReceiver builder(source_id);
   builder.SetOutcome(static_cast<int>(outcome));
   builder.Record(ukm_recorder);
-
-  UMA_HISTOGRAM_ENUMERATION("Blink.Sms.Receive.Outcome", outcome);
 }
 
 void RecordSmsSuccessTime(base::TimeDelta duration,
                           ukm::SourceId source_id,
                           ukm::UkmRecorder* ukm_recorder) {
+  UMA_HISTOGRAM_MEDIUM_TIMES("Blink.Sms.Receive.TimeSuccess", duration);
+
   DCHECK_NE(source_id, ukm::kInvalidSourceId);
   DCHECK(ukm_recorder);
 
@@ -34,13 +40,13 @@
   builder.SetTimeSuccessMs(
       ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds()));
   builder.Record(ukm_recorder);
-
-  UMA_HISTOGRAM_MEDIUM_TIMES("Blink.Sms.Receive.TimeSuccess", duration);
 }
 
 void RecordSmsUserCancelTime(base::TimeDelta duration,
                              ukm::SourceId source_id,
                              ukm::UkmRecorder* ukm_recorder) {
+  UMA_HISTOGRAM_MEDIUM_TIMES("Blink.Sms.Receive.TimeUserCancel", duration);
+
   DCHECK_NE(source_id, ukm::kInvalidSourceId);
   DCHECK(ukm_recorder);
 
@@ -49,8 +55,6 @@
   builder.SetTimeUserCancelMs(
       ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds()));
   builder.Record(ukm_recorder);
-
-  UMA_HISTOGRAM_MEDIUM_TIMES("Blink.Sms.Receive.TimeUserCancel", duration);
 }
 
 void RecordSmsCancelTime(base::TimeDelta duration) {
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.cc b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
index 9a5d552..5d5cf42 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.cc
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
 #include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
@@ -38,6 +39,7 @@
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -369,7 +371,8 @@
       url_(NullURL(), url),
       quic_transport_(context),
       handshake_client_receiver_(this, context),
-      client_receiver_(this, context) {}
+      client_receiver_(this, context),
+      inspector_transport_id_(CreateUniqueIdentifier()) {}
 
 ScriptPromise QuicTransport::createSendStream(ScriptState* script_state,
                                               ExceptionState& exception_state) {
@@ -701,7 +704,7 @@
   handshake_client_receiver_.set_disconnect_handler(
       WTF::Bind(&QuicTransport::OnConnectionError, WrapWeakPersistent(this)));
 
-  // TODO(ricea): Report something to devtools.
+  probe::WebTransportCreated(execution_context, inspector_transport_id_, url_);
 
   // The choice of 1 for the ReadableStream means that it will queue one
   // datagram even when read() is not being called. Unfortunately, that datagram
@@ -744,6 +747,7 @@
 
 void QuicTransport::Dispose() {
   DVLOG(1) << "QuicTransport::Dispose() this=" << this;
+  probe::WebTransportClosed(GetExecutionContext(), inspector_transport_id_);
   stream_map_.clear();
   quic_transport_.reset();
   handshake_client_receiver_.reset();
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.h b/third_party/blink/renderer/modules/webtransport/quic_transport.h
index 5a00b652..6c847d56 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.h
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.h
@@ -172,6 +172,8 @@
   Member<ReadableStream> received_bidirectional_streams_;
   Member<StreamVendingUnderlyingSource>
       received_bidirectional_streams_underlying_source_;
+
+  const uint64_t inspector_transport_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/instrumentation/histogram.cc b/third_party/blink/renderer/platform/instrumentation/histogram.cc
index 699cd428..2ae0db1 100644
--- a/third_party/blink/renderer/platform/instrumentation/histogram.cc
+++ b/third_party/blink/renderer/platform/instrumentation/histogram.cc
@@ -36,20 +36,4 @@
       delta.InMicroseconds()));
 }
 
-void CustomCountHistogram::CountMilliseconds(base::TimeDelta delta) {
-  Count(base::saturated_cast<base::HistogramBase::Sample>(
-      delta.InMilliseconds()));
-}
-
-LinearHistogram::LinearHistogram(const char* name,
-                                 base::HistogramBase::Sample min,
-                                 base::HistogramBase::Sample max,
-                                 int32_t bucket_count)
-    : CustomCountHistogram(base::LinearHistogram::FactoryGet(
-          name,
-          min,
-          max,
-          bucket_count,
-          base::HistogramBase::kUmaTargetedHistogramFlag)) {}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/instrumentation/histogram.h b/third_party/blink/renderer/platform/instrumentation/histogram.h
index e68f194..487f3408 100644
--- a/third_party/blink/renderer/platform/instrumentation/histogram.h
+++ b/third_party/blink/renderer/platform/instrumentation/histogram.h
@@ -31,7 +31,6 @@
   void Count(base::HistogramBase::Sample);
   void CountMany(base::HistogramBase::Sample, int count);
   void CountMicroseconds(base::TimeDelta);
-  void CountMilliseconds(base::TimeDelta);
 
  protected:
   explicit CustomCountHistogram(base::HistogramBase*);
@@ -39,14 +38,6 @@
   base::HistogramBase* histogram_;
 };
 
-class PLATFORM_EXPORT LinearHistogram : public CustomCountHistogram {
- public:
-  explicit LinearHistogram(const char* name,
-                           base::HistogramBase::Sample min,
-                           base::HistogramBase::Sample max,
-                           int32_t bucket_count);
-};
-
 template <typename Derived>
 class ScopedUsHistogramTimerBase {
   USING_FAST_MALLOC(ScopedUsHistogramTimerBase);
diff --git a/third_party/blink/tools/blinkpy/third_party/README.chromium b/third_party/blink/tools/blinkpy/third_party/README.chromium
index 3c1c1a00..08aee13 100644
--- a/third_party/blink/tools/blinkpy/third_party/README.chromium
+++ b/third_party/blink/tools/blinkpy/third_party/README.chromium
@@ -22,7 +22,7 @@
 Name: web-platform-tests - Test Suites for Web Platform specifications
 Short Name: wpt
 URL: https://github.com/web-platform-tests/wpt/
-Version: 62b62554b41e923801ee4790a89ae0597ea53f44
+Version: da46f68d5b82371132b4f877e05b9b457de89af9
 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
 License File: wpt/wpt/LICENSE.md
 Security Critical: no
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
index 27177bd..ddc656e8 100755
--- a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
@@ -9,7 +9,7 @@
 
 TARGET_DIR=$DIR/wpt
 REMOTE_REPO="https://github.com/web-platform-tests/wpt.git"
-WPT_HEAD=62b62554b41e923801ee4790a89ae0597ea53f44
+WPT_HEAD=da46f68d5b82371132b4f877e05b9b457de89af9
 
 function clone {
   # Remove existing repo if already exists.
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
index 4d10878..fee19cd1 100644
--- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
@@ -2,6 +2,7 @@
 import logging
 import os
 import re
+import subprocess
 import sys
 
 from collections import OrderedDict
@@ -76,8 +77,19 @@
                      if item and item != "^%s" % head]
 
         # get all commits on HEAD but not reachable from anything in not_heads
-        commits = git("rev-list", "--topo-order", "--parents", "HEAD", *not_heads)
+        cmd = ["git", "rev-list", "--topo-order", "--parents", "--stdin", "HEAD"]
+        proc = subprocess.Popen(cmd,
+                                stdin=subprocess.PIPE,
+                                stdout=subprocess.PIPE,
+                                cwd=wpt_root)
+        commits_bytes, _ = proc.communicate(b"\n".join(item.encode("ascii") for item in not_heads))
+        if proc.returncode != 0:
+            raise subprocess.CalledProcessError(proc.returncode,
+                                                cmd,
+                                                commits_bytes)
+
         commit_parents = OrderedDict()  # type: Dict[Text, List[Text]]
+        commits = commits_bytes.decode("ascii")
         if commits:
             for line in commits.split("\n"):
                 line_commits = line.split(" ")
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
index 1519ed7..6e5ee11 100644
--- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
@@ -41,11 +41,6 @@
        Boolean, default False, indicating whether the body content should be
        sent when the request method is HEAD.
 
-    .. attribute:: explicit_flush
-
-       Boolean indicating whether output should be flushed automatically or only
-       when requested.
-
     .. attribute:: writer
 
        The ResponseWriter for this response
@@ -73,7 +68,6 @@
 
         self.add_required_headers = True
         self.send_body_for_head_request = False
-        self.explicit_flush = False
         self.close_connection = False
 
         self.logger = get_logger()
@@ -665,11 +659,7 @@
     """Object providing an API to write out a HTTP response.
 
     :param handler: The RequestHandler being used.
-    :param response: The Response associated with this writer.
-
-    After each part of the response is written, the output is
-    flushed unless response.explicit_flush is False, in which case
-    the user must call .flush() explicitly."""
+    :param response: The Response associated with this writer."""
     def __init__(self, handler, response):
         self._wfile = handler.wfile
         self._response = response
@@ -707,52 +697,65 @@
 
         :param name: Name of the header field
         :param value: Value of the header field
+        :return: A boolean indicating whether the write succeeds
         """
         if not self._status_written:
             self.write_status(self.default_status)
         self._headers_seen.add(self.encode(name.lower()))
-        self.write(name)
-        self.write(b": ")
+        if not self.write(name):
+            return False
+        if not self.write(b": "):
+            return False
         if isinstance(value, int):
-            self.write(text_type(value))
-        else:
-            self.write(value)
-        self.write(b"\r\n")
-        if not self._response.explicit_flush:
-            self.flush()
+            if not self.write(text_type(value)):
+                return False
+        elif not self.write(value):
+            return False
+        return self.write(b"\r\n")
 
     def write_default_headers(self):
         for name, f in [("Server", self._handler.version_string),
                         ("Date", self._handler.date_time_string)]:
             if not self._seen_header(name):
-                self.write_header(name, f())
+                if not self.write_header(name, f()):
+                    return False
 
         if (isinstance(self._response.content, (binary_type, text_type)) and
             not self._seen_header("content-length")):
             #Would be nice to avoid double-encoding here
-            self.write_header("Content-Length", len(self.encode(self._response.content)))
+            if not self.write_header("Content-Length", len(self.encode(self._response.content))):
+                return False
+
+        return True
 
     def end_headers(self):
         """Finish writing headers and write the separator.
 
         Unless add_required_headers on the response is False,
         this will also add HTTP-mandated headers that have not yet been supplied
-        to the response headers"""
+        to the response headers.
+        :return: A boolean indicating whether the write succeeds
+        """
 
         if self._response.add_required_headers:
-            self.write_default_headers()
+            if not self.write_default_headers():
+                return False
 
-        self.write("\r\n")
+        if not self.write("\r\n"):
+            return False
         if not self._seen_header("content-length"):
             self._response.close_connection = True
-        if not self._response.explicit_flush:
-            self.flush()
         self._headers_complete = True
 
+        return True
+
     def write_content(self, data):
         """Write the body of the response.
 
-        HTTP-mandated headers will be automatically added with status default to 200 if they have not been explicitly set."""
+        HTTP-mandated headers will be automatically added with status default to 200 if they have
+        not been explicitly set.
+        :return: A boolean indicating whether the write succeeds
+        """
         if not self._status_written:
             self.write_status(self.default_status)
         if not self._headers_complete:
@@ -772,7 +775,9 @@
 
     def write(self, data):
         """Write directly to the response, converting unicode to bytes
-        according to response.encoding. Does not flush."""
+        according to response.encoding.
+        :return: A boolean indicating whether the write succeeds
+        """
         self.content_written = True
         try:
             self._wfile.write(self.encode(data))
@@ -782,8 +787,7 @@
             return False
 
     def write_content_file(self, data):
-        """Write a file-like object directly to the response in chunks.
-        Does not flush."""
+        """Write a file-like object directly to the response in chunks."""
         self.content_written = True
         success = True
         while True:
@@ -807,13 +811,3 @@
             return data.encode(self._response.encoding)
         else:
             raise ValueError("data %r should be text or binary, but is %s" % (data, type(data)))
-
-    def flush(self):
-        """Flush the output. Returns False if the flush failed due to
-        the socket being closed by the remote end."""
-        try:
-            self._wfile.flush()
-            return True
-        except socket.error:
-            # This can happen if the socket got closed by the remote end
-            return False
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
index 251b15a..bbf65be 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
@@ -132,11 +132,6 @@
         if self.actual_driver_output.error:
             artifact_filename = self.port.output_filename(
                 self.test_name, FILENAME_SUFFIX_STDERR, '.txt')
-
-            # some ref tests don't produce any text output and also
-            # have a text baseline. They also produce an image mismatch
-            # error. If the test driver produces stderr then an exception
-            # will be raised because we will be writing that stderr twice
             artifacts_abspath = self.filesystem.join(
                 self.result_directory, typ_artifacts.ArtifactsSubDirectory(),
                 artifact_filename)
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache b/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache
index 7909f65..e3823bdd 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache
+++ b/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache
@@ -1,3 +1,23 @@
 # tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ]
 # tags: [ Release Debug ]
 # results: [ Timeout Crash Pass Failure Slow Skip ]
+
+# Tests that are not compatible with same-site back-forward cache. To run these
+# tests, we have to disable same-site back-forward cache.
+crbug.com/1132180 http/tests/history/cross-origin-redirect-on-back.html [ Skip ]
+crbug.com/1132180 http/tests/history/dynamic-frame-creation-order-inline-scripts.html [ Skip ]
+crbug.com/1132180 http/tests/history/dynamic-frame-creation-order-onload-handler.html [ Skip ]
+crbug.com/1132180 http/tests/misc/resource-timing-iframe-restored-from-history.html [ Skip ]
+crbug.com/1132180 http/tests/misc/resource-timing-navigation-in-restored-iframe.html [ Skip ]
+crbug.com/1132180 http/tests/navigation/back-to-dynamic-iframe.html [ Skip ]
+crbug.com/1132180 http/tests/navigation/forward-to-fragment-fires-onload.html [ Skip ]
+
+# TODO(peria): Make these tests work with same-site back-forward cache.
+crbug.com/1150297 http/tests/navigation/back-during-child-frame-reload.html [ Timeout ]
+crbug.com/1150297 http/tests/navigation/post-frames-goback1.html [ Timeout ]
+crbug.com/1150297 http/tests/navigation/postredirect-frames-goback1.html [ Timeout ]
+
+# TODO(peria): Make these tests work with same-site browsing instance swap.
+crbug.com/1136383 http/tests/inspector-protocol/network/interception-download.js [ Failure ]
+crbug.com/1136383 virtual/sxg-subresource-disabled/http/tests/loading/sxg/sxg-subresource-origin-trial.https.html [ Failure ]
+crbug.com/1136383 virtual/synchronous_html_parser/http/tests/inspector-protocol/network/interception-download.js [ Failure ]
diff --git a/third_party/blink/web_tests/android/ChromiumWPTExpectations b/third_party/blink/web_tests/android/ChromiumWPTExpectations
index c984827d..b96d70e 100644
--- a/third_party/blink/web_tests/android/ChromiumWPTExpectations
+++ b/third_party/blink/web_tests/android/ChromiumWPTExpectations
@@ -1524,7 +1524,6 @@
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-disallow-import.tentative.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-duplicate.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable.html [ Failure Pass ]
-crbug.com/1050754 external/wpt/css/cssom/border-shorthand-serialization.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-002.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-003.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-004.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WeblayerWPTExpectations b/third_party/blink/web_tests/android/WeblayerWPTExpectations
index eb6c7c9..59454e16 100644
--- a/third_party/blink/web_tests/android/WeblayerWPTExpectations
+++ b/third_party/blink/web_tests/android/WeblayerWPTExpectations
@@ -1431,7 +1431,6 @@
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-disallow-import.tentative.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-duplicate.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable.html [ Failure Pass ]
-crbug.com/1050754 external/wpt/css/cssom/border-shorthand-serialization.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-002.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-003.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-004.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WebviewWPTExpectations b/third_party/blink/web_tests/android/WebviewWPTExpectations
index 63c0d95..b09d9d4 100644
--- a/third_party/blink/web_tests/android/WebviewWPTExpectations
+++ b/third_party/blink/web_tests/android/WebviewWPTExpectations
@@ -1568,7 +1568,6 @@
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-disallow-import.tentative.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable-duplicate.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/CSSStyleSheet-constructable.html [ Failure Pass ]
-crbug.com/1050754 external/wpt/css/cssom/border-shorthand-serialization.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-002.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-003.html [ Failure ]
 crbug.com/1050754 external/wpt/css/cssom/computed-style-004.html [ Failure ]
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 0ab8189..191280b7 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
@@ -169034,7 +169034,7 @@
     "file": {
      "resources": {
       "echo-content-escaped.py": [
-       "2cbaf45c20efdfcba17a27d3aecb3e5c9bee4bfb",
+       "f35d069acac9c5cfe4d15fcf9a83288a72c375db",
        []
       ]
      }
@@ -209630,7 +209630,7 @@
      ]
     },
     "requirements.txt": [
-     "a008e3e72e88c9605b4b01cdc26d68fd4d13d710",
+     "725ddd9e85ee202cf7fc9d3072a770a6351cdb71",
      []
     ],
     "selectors": {
@@ -212056,7 +212056,7 @@
      []
     ],
     "conf.py": [
-     "44d3c2f76bbcd6364e6bd81015ee9d0caaca21b9",
+     "96e8290455e20cec5088b7f1f7036ac39a8cf6c3",
      []
     ],
     "frontend.py": [
@@ -212076,12 +212076,12 @@
      []
     ],
     "requirements.txt": [
-     "a9ddeecfe573825febb48afcd16ce4bc02b696ff",
+     "03ce983831da5d30ad423f9030cb612b30a9fb91",
      []
     ],
     "reviewing-tests": {
      "checklist.md": [
-      "0e50843f289bfad232723065f41442ba0b241713",
+      "be0f4d134e4d3d9ad06e994d96937640ee53246b",
       []
      ],
      "email.md": [
@@ -212152,7 +212152,7 @@
      []
     ],
     "wpt_lint_rules.py": [
-     "a5eed507b5e774c37d5081046173ca5629bb7c16",
+     "b9997372520f3670a1047d3020ed2475f3f09098",
      []
     ],
     "writing-tests": {
@@ -245474,7 +245474,7 @@
      ],
      "documentation": {
       "Dockerfile": [
-       "e01f98e4d4df0e7f7501bb5d7057d1d528221bde",
+       "01ea0bd95bf6d1468d4a38afa121f9fca01f3e95",
        []
       ]
      },
@@ -250445,7 +250445,7 @@
         []
        ],
        "stream.py": [
-        "fc399f2a85b9fe6c52ec5690f580d06b222e4748",
+        "82d1ea619c074f1183bc08ae55a8ce0bb7704106",
         []
        ],
        "util.py": [
@@ -251379,7 +251379,7 @@
       []
      ],
      "requirements.txt": [
-      "90d0cb6cdc8795c9b39e7644fd330283653b48e4",
+      "d83f5eb89fab1eb9734a90d262e21c33fa162a1f",
       []
      ],
      "revlist.py": [
@@ -251425,7 +251425,7 @@
       []
      ],
      "requirements.txt": [
-      "77c1ea50e90bc2ccff510173fbc892190b616b1d",
+      "a266c322e2cf453221e4a11e4302879e413baa94",
       []
      ],
      "requirements_android_webview.txt": [
@@ -251473,7 +251473,7 @@
       []
      ],
      "requirements_sauce.txt": [
-      "d363945f54fc1b84fdc9ddc58560637ee050881c",
+      "47e268df17307a701bd966a9dbe89c3d542d8d3b",
       []
      ],
      "requirements_servo.txt": [
@@ -379661,6 +379661,13 @@
       {}
      ]
     ],
+    "placeholder-image.html": [
+     "6a2ce5c7c6df636e7003e7c69a58e65eb444f454",
+     [
+      null,
+      {}
+     ]
+    ],
     "redirects-tao-star.html": [
      "f01c2496c0673feb4d4ee4821e4ad51b5a79cd49",
      [
diff --git a/third_party/blink/web_tests/external/wpt/FileAPI/file/resources/echo-content-escaped.py b/third_party/blink/web_tests/external/wpt/FileAPI/file/resources/echo-content-escaped.py
index 2cbaf45..f35d069a 100644
--- a/third_party/blink/web_tests/external/wpt/FileAPI/file/resources/echo-content-escaped.py
+++ b/third_party/blink/web_tests/external/wpt/FileAPI/file/resources/echo-content-escaped.py
@@ -1,3 +1,4 @@
+from six import PY3
 from wptserve.utils import isomorphic_encode
 
 # Outputs the request body, with controls and non-ASCII bytes escaped
@@ -5,13 +6,13 @@
 # As a convenience, CRLF newlines are left as is.
 
 def escape_byte(byte):
-    # Iterating over a binary string gives different types in Py2 & Py3.
-    # Py3: bytes -> int
-    # Py2: str -> str (of length 1), so we convert it to int
-    code = byte if type(byte) is int else ord(byte)
-    if 0 <= code <= 0x1F or code >= 0x7F:
-        return b"\\x%02x" % code
-    if code == ord(b"\\"):
+    # We want a single-char binary string, but in Python 3 we may get an int
+    # from iterating over bytes.
+    if PY3:
+        byte = bytes([byte])
+    if b"\0" <= byte <= b"\x1F" or byte >= b"\x7F":
+        return b"\\x%02x" % ord(byte)
+    if byte == b"\\":
         return b"\\\\"
     return byte
 
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/border-shorthand-serialization-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/border-shorthand-serialization-expected.txt
index 11e3cba..e69de29 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/border-shorthand-serialization-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/border-shorthand-serialization-expected.txt
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-PASS Declaration with border longhands is not serialized to a border shorthand declaration.
-FAIL Declaration with border longhands and border-image is not serialized to a border shorthand declaration. assert_equals: border shorthand isn't serialized if border-image longhands are not initial expected "" but got "1px solid black"
-PASS Border shorthand is serialized correctly if all border-image-* are set to their initial specified values.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/requirements.txt b/third_party/blink/web_tests/external/wpt/css/requirements.txt
index a008e3e..725ddd9 100644
--- a/third_party/blink/web_tests/external/wpt/css/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/css/requirements.txt
@@ -1,6 +1,6 @@
 Template-Python==0.1.post1
 html5lib==1.1
-lxml==4.1.1
+lxml==4.5.2
 mercurial==4.5
 six==1.15.0
 webencodings==0.5.1
diff --git a/third_party/blink/web_tests/external/wpt/docs/conf.py b/third_party/blink/web_tests/external/wpt/docs/conf.py
index 44d3c2f..96e82904 100644
--- a/third_party/blink/web_tests/external/wpt/docs/conf.py
+++ b/third_party/blink/web_tests/external/wpt/docs/conf.py
@@ -78,6 +78,7 @@
     ('py:exc', 'BadOperationException'),
     ('py:exc', 'Exception'),
     ('py:exc', 'ValueError'),
+    ('py:class', 'http.client.HTTPMessage')
 ]
 
 # The language for content autogenerated by Sphinx. Refer to documentation
@@ -211,5 +212,5 @@
 # A list of files that should not be packed into the epub file.
 epub_exclude_files = ['search.html']
 
-intersphinx_mapping = {'python': ('https://docs.python.org/2/', None),
+intersphinx_mapping = {'python': ('https://docs.python.org/3/', None),
                        'mozilla': ('https://firefox-source-docs.mozilla.org/', None)}
diff --git a/third_party/blink/web_tests/external/wpt/docs/requirements.txt b/third_party/blink/web_tests/external/wpt/docs/requirements.txt
index a9ddeecf..03ce983 100644
--- a/third_party/blink/web_tests/external/wpt/docs/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/docs/requirements.txt
@@ -1,4 +1,4 @@
 recommonmark==0.6.0
-# pin this to the last Py2 release
-Sphinx==1.8.5  # pyup: <2.0
+# Pin this to the same major version as https://docs.python.org/3/
+Sphinx==2.4.4  # pyup: <3.0
 sphinx-argparse==0.2.5
diff --git a/third_party/blink/web_tests/external/wpt/docs/reviewing-tests/checklist.md b/third_party/blink/web_tests/external/wpt/docs/reviewing-tests/checklist.md
index 0e50843f..be0f4d1 100644
--- a/third_party/blink/web_tests/external/wpt/docs/reviewing-tests/checklist.md
+++ b/third_party/blink/web_tests/external/wpt/docs/reviewing-tests/checklist.md
@@ -5,7 +5,7 @@
 documentation it should be ignored
 (please [file a bug](https://github.com/web-platform-tests/wpt/issues/new)!).
 
-As noted on the [reviewing tests](index) page, nits need not block PRs
+As noted on the [reviewing tests](./index.md) page, nits need not block PRs
 from landing.
 
 
diff --git a/third_party/blink/web_tests/external/wpt/docs/wpt_lint_rules.py b/third_party/blink/web_tests/external/wpt/docs/wpt_lint_rules.py
index a5eed50..b999737 100644
--- a/third_party/blink/web_tests/external/wpt/docs/wpt_lint_rules.py
+++ b/third_party/blink/web_tests/external/wpt/docs/wpt_lint_rules.py
@@ -3,6 +3,7 @@
 from recommonmark.parser import CommonMarkParser
 import importlib
 import textwrap
+from six import iteritems
 
 class WPTLintRules(Directive):
     """A docutils directive to generate documentation for the
@@ -31,7 +32,7 @@
                 """wpt-lint-rules: unable to resolve the module at "{}".""".format(self.module_specifier)
             )
 
-        for binding_name, value in module.__dict__.iteritems():
+        for binding_name, value in iteritems(module.__dict__):
             if hasattr(value, "__abstractmethods__") and len(value.__abstractmethods__):
                 continue
 
diff --git a/third_party/blink/web_tests/external/wpt/tools/docker/documentation/Dockerfile b/third_party/blink/web_tests/external/wpt/tools/docker/documentation/Dockerfile
index e01f98e4..01ea0bd9 100644
--- a/third_party/blink/web_tests/external/wpt/tools/docker/documentation/Dockerfile
+++ b/third_party/blink/web_tests/external/wpt/tools/docker/documentation/Dockerfile
@@ -1,3 +1,3 @@
-FROM python:2-stretch
+FROM python:3.8-buster
 
-RUN apt-get update && apt-get install --yes git
+RUN apt-get update && apt-get install --yes git virtualenv
diff --git a/third_party/blink/web_tests/external/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/stream.py b/third_party/blink/web_tests/external/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/stream.py
index fc399f2a..82d1ea61 100644
--- a/third_party/blink/web_tests/external/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/stream.py
+++ b/third_party/blink/web_tests/external/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/stream.py
@@ -875,7 +875,7 @@
             wait_response: True when caller want to wait the response.
         Raises:
             BadOperationException: when reason is specified with code None
-            or reason is not an instance of both str and unicode.
+                or reason is not an instance of both str and unicode.
         """
 
         if self._request.server_terminated:
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wpt/requirements.txt
index 90d0cb6c..d83f5eb8 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/requirements.txt
@@ -1,2 +1,2 @@
-requests==2.24.0
+requests==2.25.0
 mozinfo==1.2.1  # https://bugzilla.mozilla.org/show_bug.cgi?id=1621226
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
index 77c1ea5..a266c32 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
@@ -6,5 +6,5 @@
 pillow==6.2.2; python_version <= '2.7'  # pyup: <7.0
 pillow==8.0.1; python_version >= '3.0'
 urllib3[secure]==1.26.2
-requests==2.24.0
+requests==2.25.0
 six==1.15.0
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_sauce.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_sauce.txt
index d363945f..47e268d 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_sauce.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_sauce.txt
@@ -1,3 +1,3 @@
 mozprocess==1.2.1
 selenium==3.141.0
-requests==2.24.0
+requests==2.25.0
diff --git a/third_party/blink/web_tests/fast/multicol/outline/outline-inline-across-columns.html b/third_party/blink/web_tests/fast/multicol/outline/outline-inline-across-columns.html
new file mode 100644
index 0000000..4c53a15
--- /dev/null
+++ b/third_party/blink/web_tests/fast/multicol/outline/outline-inline-across-columns.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<style>
+.columns {
+  column-fill: auto;
+  column-width: 10ch;
+  font-size: 20px;
+  line-height: 22px;
+  height: 90px;
+  margin-bottom: 1em;
+}
+.loose {
+  line-height: 24px;
+  height: 100px;
+}
+</style>
+<body>
+  <div class="columns">
+    123456789
+    12345
+    <span style="outline: auto">
+      789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+
+  <div class="columns loose">
+    123456789
+    12345
+    <span style="outline: auto">
+      789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+
+  <div class="columns">
+    123456789
+    12345
+    <span style="outline: 5px solid blue">
+      789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/fast/multicol/outline/outline-inline-continuation-across-columns.html b/third_party/blink/web_tests/fast/multicol/outline/outline-inline-continuation-across-columns.html
new file mode 100644
index 0000000..23fc376
--- /dev/null
+++ b/third_party/blink/web_tests/fast/multicol/outline/outline-inline-continuation-across-columns.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<style>
+.columns {
+  column-fill: auto;
+  column-width: 10ch;
+  orphans: 1;
+  widows: 1;
+  font-size: 20px;
+  line-height: 22px;
+  height: 90px;
+  margin-bottom: 1em;
+}
+.loose {
+  line-height: 24px;
+  height: 100px;
+}
+</style>
+<body>
+  <div class="columns">
+    123456789
+    12345
+    <span style="outline: auto">
+      789
+      123456789
+      <div>
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+      </div>
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+
+  <div class="columns loose">
+    123456789
+    12345
+    <span style="outline: auto">
+      789
+      123456789
+      <div>
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+      </div>
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+
+  <div class="columns">
+    123456789
+    12345
+    <span style="outline: 5px solid blue">
+      789
+      123456789
+      <div>
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+        123456789
+      </div>
+      123456789
+      123</span>
+    56789
+    123456789
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back-expected.txt b/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back-expected.txt
index 78e39708c..8f2f7fc 100644
--- a/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back-expected.txt
+++ b/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back-expected.txt
@@ -1 +1,3 @@
+This test expects a HTTP fetch resulting in a redirect for the first history navigation. This doesn't happen if the page is restored from back-forward cache, so back-fowrad cache has to be disabled to test this behaviour.
+
 We pass if we don't crash.
diff --git a/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back.html b/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back.html
index 30da4e4b..3eb8fb53 100644
--- a/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back.html
+++ b/third_party/blink/web_tests/http/tests/history/cross-origin-redirect-on-back.html
@@ -1,5 +1,10 @@
 <html>
 <body>
+<p>This test expects a HTTP fetch resulting in a redirect for the first history
+navigation. This doesn't happen if the page is restored from back-forward cache,
+so back-fowrad cache has to be disabled to test this behaviour.
+</p>
+
 <script>
 if (window.testRunner) {
     testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt
index 44cfdce..51c8ff8 100644
--- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt
+++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt
@@ -1,4 +1,6 @@
-This is almost the same test as dynamic-frame-creation-order-onload-handler.html except that the dynamic frames are created from an inline script, rather than in response to an onLoad event.
+This is almost the same test as dynamic-frame-creation-order-onload-handler.html except that the dynamic frames are created from an inline script, rather than in response to an onload event.
+
+If we enable back-forward cache, back navigation doesn't run inline script and thus this test fails.
 
 Frame creation order during this page load:
 
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts.html b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts.html
index 6c3a78c..e06f7a5ce 100644
--- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts.html
+++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts.html
@@ -24,7 +24,10 @@
     <p>This is almost the same test as
     dynamic-frame-creation-order-onload-handler.html except that the dynamic
     frames are created from an inline script, rather than in response to an
-    onLoad event.
+    onload event.
+    </p>
+    <p>If we enable back-forward cache, back navigation doesn't run inline
+    script and thus this test fails.
     </p>
     <hr>
     <p>Frame creation order during this page load:</p>
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt
index 7343d777..0d4cd6b7 100644
--- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt
+++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt
@@ -7,6 +7,8 @@
     
 The tricky part is that the order of subframe creation changes at each load (via sessionStorage.pageLoadCount). This can confuse the browser into restoring (after back navigation) green.htm into left frame and red.htm into right frame.
 
+This test expects to reset and reload iframes on main frame's back navigation. Back-forward cache needs to be disabled to run this test.
+
 Frame creation order during this page load:
 
 Created <iframe class="left" src="resources/red.html"></iframe>
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler.html b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler.html
index 99dc4a6..23a665f 100644
--- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler.html
+++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler.html
@@ -99,6 +99,10 @@
     (after back navigation) green.htm into left frame and red.htm into right frame.
     </p>
 
+    <p>This test expects to reset and reload iframes on main frame's back
+    navigation. Back-forward cache needs to be disabled to run this test.
+    </p>
+
     <hr>
     <p>Frame creation order during this page load:</p>
     <ul id="order-description"></ul>
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt
index 396b12ea..abbe0a2 100644
--- a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt
+++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt
@@ -12,3 +12,5 @@
 
 TEST COMPLETE
 
+
+Back-forward cache keeps and restores the resource timing of the iframe on back navigation. Back-forward cache needs to be disabled to run this test.
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history.html b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history.html
index a3a14d2..995f6de 100644
--- a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history.html
+++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history.html
@@ -28,4 +28,8 @@
 }
 
 </script>
+
+<p>Back-forward cache keeps and restores the resource timing of the iframe on
+back navigation. Back-forward cache needs to be disabled to run this test.
+</p>
 <iframe></iframe>
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt
index 4aebeaff..c787e96 100644
--- a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt
+++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt
@@ -9,3 +9,5 @@
 
 TEST COMPLETE
 
+
+Back-forward cache keeps and restores the resource timing of the iframe on back navigation. Back-forward cache needs to be disabled to run this test.
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe.html b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe.html
index 14a559dc..141b0fd8 100644
--- a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe.html
+++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe.html
@@ -27,4 +27,9 @@
 window.onload = runTest;
 
 </script>
+
+<p>Back-forward cache keeps and restores the resource timing of the iframe on
+back navigation. Back-forward cache needs to be disabled to run this test.
+</p>
+
 <iframe id="target-iframe" src="http://localhost:8080/misc/resources/navigate-on-message.html"></iframe>
diff --git a/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe-expected.txt b/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe-expected.txt
index ef6edca..5f671e0 100644
--- a/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe-expected.txt
+++ b/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe-expected.txt
@@ -1,4 +1,4 @@
-
+ This test expects the iframe to be reset on backward navigation. Back-foward cache needs to be disabled to run this test successfully.
 
 ============== Back Forward List ==============
 curr->  http://127.0.0.1:8000/navigation/back-to-dynamic-iframe.html
diff --git a/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe.html b/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe.html
index 5511fe565..38f5d7a1 100644
--- a/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe.html
+++ b/third_party/blink/web_tests/http/tests/navigation/back-to-dynamic-iframe.html
@@ -31,4 +31,7 @@
     i.src = "resources/back-to-dynamic-iframe-iframe.html#PASS";
 }
 </script>
+
+This test expects the iframe to be reset on backward navigation. Back-foward
+cache needs to be disabled to run this test successfully.
 </body>
diff --git a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt
index 694a7d0..35c4629 100644
--- a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt
@@ -1,13 +1,15 @@
-CONSOLE MESSAGE: line 26: Starting test.
+CONSOLE MESSAGE: line 31: Starting test.
 CONSOLE MESSAGE: line 6: 1. Got to page 2.  Going to #foo.
 CONSOLE MESSAGE: line 22: 2. Got to page 2 #foo.  Going back to start.
-CONSOLE MESSAGE: line 16: 3. Got back to start.  Going forward to page 2.
+CONSOLE MESSAGE: line 21: 3. Got back to start.  Going forward to page 2.
 CONSOLE MESSAGE: line 31: 4. Got back to page 2.  Immediately going forward.
 CONSOLE MESSAGE: line 13: 5. Got to page 2 onload.  Success.
 Tests that loading is not stopped by going forward to a fragment.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
+This test checks the behavior of loading on back navigation. Back-forward cache needs to be disabled to test the behavior, because otherwise we won't trigger a new load on back navigation.
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload.html b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload.html
index 3b8f0cb..8d05289 100644
--- a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload.html
+++ b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload.html
@@ -5,6 +5,11 @@
 </head>
 <body>
 <p id="description"></p>
+<p>This test checks the behavior of loading on back navigation. Back-forward
+cache needs to be disabled to test the behavior, because otherwise we won't
+trigger a new load on back navigation.
+</p>
+
 <div id="console"></div>
 
 <script>
diff --git a/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..6d04e40
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..b34da920
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..41f472c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..ad1f1a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..69baaa0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..f8fb7e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..be30e3a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..9e9a2d49
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..784650b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..95b77d8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png b/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
new file mode 100644
index 0000000..67bc2e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-across-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png b/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
new file mode 100644
index 0000000..215beab3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/fast/multicol/outline/outline-inline-continuation-across-columns-expected.png
Binary files differ
diff --git a/tools/android/modularization/owners/owners_git.py b/tools/android/modularization/owners/owners_git.py
index d448582..d8b1f4c 100644
--- a/tools/android/modularization/owners/owners_git.py
+++ b/tools/android/modularization/owners/owners_git.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 '''Git utility functions.'''
 
+import os
 import subprocess
 import sys
 
@@ -42,7 +43,12 @@
                           git_src: str) -> List[str]:
   command = _build_ls_files_command(subdirectory)
   filepath_str = run_command(command, cwd=git_src)
-  return [filepath for filepath in filepath_str.split('\n') if filepath]
+  result = []
+  for relative_filepath in filepath_str.split('\n'):
+    if relative_filepath:
+      absolute_filepath = os.path.join(git_src, relative_filepath)
+      result.append(absolute_filepath)
+  return result
 
 
 def _build_ls_files_command(subdirectory: Optional[str]) -> List[str]:
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
index 56da24ac..90df7fd 100644
--- a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
+++ b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
@@ -27,6 +27,9 @@
 chrome/chrome_elf/
 chrome/installer/mini_installer/
 
+# Exclude pocdll.dll asnit doesn't depend on //base and only used for testing.
+sandbox/win/sandbox_poc/pocdll
+
 # The folder holds headers that are duplicated in the Android source and need to
 # provide a stable C ABI. Can't depend on //base.
 android_webview/public/
diff --git a/tools/metrics/actions/README.md b/tools/metrics/actions/README.md
index e35f29b..c82a19b 100644
--- a/tools/metrics/actions/README.md
+++ b/tools/metrics/actions/README.md
@@ -34,11 +34,13 @@
 user action needs to be logged in multiple places, consider whether you should
 be using different user action names for these separate call paths.
 
-That said, if you truly need to record the same user action in multiple places,
-that's okay. Use a compile-time constant of appropriate scope that can be
-referenced everywhere. Using inline strings in multiple places can lead to
-errors if you ever need to revise the name and you update one location but
-forget another.
+In rare cases, the same user action can be recorded in multiple places as long
+as only one of the places can be reached. This may be necessary if the user
+action is logged in platform-specific code or if one implementation is being
+replaced with another. When recording an action in multiple places, use a
+compile-time constant of appropriate scope that can be referenced everywhere.
+Using inline strings in multiple places can lead to errors if you ever need to
+revise the name and you update one location but forget another.
 
 ### Efficiency
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5fc617f8..4ca5101 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -12774,6 +12774,14 @@
   <int value="3" label="Peek Promo was not seen, Panel was not opened"/>
 </enum>
 
+<enum name="ContextualSearchPermissions">
+  <summary>The privacy permissions for the current user.</summary>
+  <int value="0" label="None"/>
+  <int value="1" label="Send URL"/>
+  <int value="2" label="Send content"/>
+  <int value="3" label="Send URL and content"/>
+</enum>
+
 <enum name="ContextualSearchPreferenceState">
   <int value="0" label="Uninitialized"/>
   <int value="1" label="Enabled"/>
@@ -31729,6 +31737,7 @@
   <int value="24" label="RECENT_AUDIO"/>
   <int value="25" label="RECENT_IMAGES"/>
   <int value="26" label="RECENT_VIDEOS"/>
+  <int value="27" label="TRASH"/>
 </enum>
 
 <enum name="FileManagerTaskType">
@@ -37907,208 +37916,152 @@
 </enum>
 
 <enum name="InputMethodID2">
-  <int value="-2082426075" label="xkb:cz:qwerty:cze">Czech QWERTY keyboard</int>
-  <int value="-2039513744" label="xkb:ru::rus">Russian keyboard</int>
-  <int value="-2030885731" label="vkd_fa">Persian keyboard</int>
-  <int value="-2004968165" label="xkb:gb:dvorak:eng">UK Dvorak keyboard</int>
-  <int value="-2004834194" label="xkb:ca:multix:fra">
-    Canadian Multilingual keyboard
-  </int>
-  <int value="-1992142310" label="xkb:dk::dan">Danish keyboard</int>
-  <int value="-1989523479" label="pa-t-i0-und">Punjabi transliteration</int>
-  <int value="-1955862460" label="xkb:ro::rum">Romanian keyboard</int>
-  <int value="-1953637256" label="xkb:us:workman-intl:eng">
-    US Workman International Keyboard
-  </int>
-  <int value="-1951732875" label="xkb:be::nld">Belgian keyboard</int>
-  <int value="-1856842164" label="xkb:ge::geo">Georgian keyboard</int>
-  <int value="-1793755122" label="zh-hant-t-i0-cangjie-1987-x-m0-simplified">
-    Quick input method
-  </int>
-  <int value="-1710145174" label="xkb:am:phonetic:arm">
-    Armenian Phonetic keyboard
-  </int>
-  <int value="-1709647399" label="xkb:mn::mon">Mongolian keyboard</int>
-  <int value="-1668610460" label="xkb:us:dvp:eng">
-    US Programmer Dvorak keyboard
-  </int>
-  <int value="-1622129313" label="sr-t-i0-und">Serbian transliteration</int>
-  <int value="-1616253108" label="ta-t-i0-und">Tamil transliteration</int>
-  <int value="-1608984043" label="vkd_my_myansan">Myanmar Myansan keyboard</int>
-  <int value="-1520893793" label="vkd_te_phone">Telugu keyboard (Phonetic)</int>
-  <int value="-1474243589" label="xkb:it::ita">Italian keyboard</int>
-  <int value="-1466408010" label="hi-t-i0-und">Hindi transliteration</int>
-  <int value="-1408581676" label="xkb:gb:extd:eng">UK keyboard</int>
-  <int value="-1402880636" label="xkb:se::swe">Swedish keyboard</int>
-  <int value="-1386518472" label="vkd_ru_phone_aatseel">
-    Russian Phonetic (AATSEEL) keyboard
-  </int>
-  <int value="-1362493117" label="zh-hant-t-i0-dayi-1988">
-    Dayi input method
-  </int>
-  <int value="-1356599825" label="bn-t-i0-und">Bengali transliteration</int>
-  <int value="-1346114248" label="vkd_vi_vni">Vietnamese keyboard (VNI)</int>
-  <int value="-1338032348" label="xkb:de:neo:ger">German NEO 2 keyboard</int>
-  <int value="-1148371254" label="xkb:us:intl:por">
-    US International keyboard
-  </int>
-  <int value="-1093390778" label="vkd_ml_phone">
-    Malayalam keyboard (Phonetic)
-  </int>
-  <int value="-1084450354" label="gu-t-i0-und">Gujarati transliteration</int>
-  <int value="-1053378431" label="xkb:tr::tur">Turkish keyboard</int>
-  <int value="-1044696009" label="ar-t-i0-und">Arabic transliteration</int>
-  <int value="-1032532014" label="xkb:bg:phonetic:bul">
-    Bulgarian Phonetic keyboard
-  </int>
-  <int value="-1024152574" label="xkb:ca:eng:eng">
-    Canadian English keyboard
-  </int>
-  <int value="-1021036210" label="xkb:us::ind">US keyboard</int>
-  <int value="-1011117789" label="vkd_ta_itrans">Tamil keyboard (itrans)</int>
-  <int value="-994915284" label="xkb:ch:fr:fra">Swiss French keyboard</int>
-  <int value="-955047705" label="xkb:sk::slo">Slovakian keyboard</int>
-  <int value="-942739805" label="xkb:tr:f:tur">Turkish-F keyboard</int>
-  <int value="-923332388" label="xkb:ua::ukr">Ukrainian keyboard</int>
-  <int value="-827208209" label="xkb:hu::hun">Hungarian keyboard</int>
-  <int value="-769279084" label="xkb:us:intl_pc:eng">
-    US International (PC) keyboard
-  </int>
-  <int value="-694112343" label="vkd_ne_phone">Nepali keyboard (Phonetic)</int>
-  <int value="-666585286" label="xkb:bg::bul">Bulgarian keyboard</int>
-  <int value="-650362029" label="xkb:ie::ga">Irish keyboard</int>
-  <int value="-607101895" label="zh-t-i0-pinyin">Pinyin input method</int>
-  <int value="-547772150" label="xkb:ro:std:rum">
-    Romanian standard keyboard
-  </int>
-  <int value="-545936253" label="zh-hant-t-i0-array-1992">
-    Array input method
-  </int>
-  <int value="-537214862" label="xkb:us:intl_pc:eng">
-    US International (PC) keyboard
-  </int>
-  <int value="-535089160" label="xkb:us::msa">US keyboard</int>
-  <int value="-512360986" label="xkb:us:altgr-intl:eng">
-    US Extended keyboard
-  </int>
-  <int value="-496003957" label="xkb:de::ger">German keyboard</int>
-  <int value="-489436211" label="xkb:us:intl_pc:nld">
-    US International (PC) keyboard
-  </int>
-  <int value="-456651526" label="kn-t-i0-und">Kannada transliteration</int>
-  <int value="-383640577" label="or-t-i0-und">Oriya transliteration</int>
-  <int value="-366323598" label="fa-t-i0-und">Persian transliteration</int>
-  <int value="-352571373" label="xkb:rs::srp">Serbian keyboard</int>
-  <int value="-329596558" label="te-t-i0-und">Telugu transliteration</int>
-  <int value="-299716106" label="xkb:si::slv">Slovenian keyboard</int>
-  <int value="-292687390" label="xkb:fi::fin">Finnish keyboard</int>
-  <int value="-263932473" label="xkb:ch::ger">Swiss keyboard</int>
-  <int value="-244167850" label="nacl_mozc_jp">
-    Google Japanese Input (for Japanese keyboard)
-  </int>
-  <int value="-202781885" label="xkb:us:intl:eng">
-    US International keyboard
-  </int>
-  <int value="-176093583" label="vkd_bn_phone">Bengali keyboard (Phonetic)</int>
-  <int value="-119597715" label="mr-t-i0-und">Marathi transliteration</int>
-  <int value="-70827301" label="xkb:be::fra">Belgian keyboard</int>
-  <int value="2215666" label="xkb:jp::jpn">Japanese keyboard</int>
-  <int value="23642603" label="yue-hant-t-i0-und">Cantonese input method</int>
-  <int value="28549849" label="xkb:pt::por">Portuguese keyboard</int>
-  <int value="60054916" label="xkb:fo::fao">Faroese keyboard</int>
-  <int value="68243712" label="vkd_si">Sinhala keyboard</int>
-  <int value="87135772" label="xkb:fr::fra">French keyboard</int>
-  <int value="132261074" label="ti-t-i0-und">Tigrinya transliteration</int>
-  <int value="193122406" label="xkb:gr::gre">Greek keyboard</int>
-  <int value="197116831" label="xkb:es::spa">Spanish keyboard</int>
-  <int value="233227876" label="vkd_km">Khmer keyboard</int>
-  <int value="319509360" label="xkb:be::ger">Belgian keyboard</int>
-  <int value="374544129" label="vkd_th_pattajoti">
-    Thai keyboard (Pattachote)
-  </int>
-  <int value="382485416" label="xkb:lv:apostrophe:lav">Latvian keyboard</int>
-  <int value="469000663" label="xkb:es:cat:cat">Catalan keyboard</int>
-  <int value="472995125" label="vkd_ta_phone">Tamil keyboard (Phonetic)</int>
-  <int value="484753645" label="xkb:us:workman:eng">US Workman Keyboard</int>
-  <int value="490329655" label="zh-t-i0-wubi-1986">Wubi input method</int>
-  <int value="520496071" label="vkd_ckb_en">
-    Sorani Kurdish English-based keyboard
-  </int>
-  <int value="535728072" label="ne-t-i0-und">Nepali transliteration</int>
-  <int value="537062379" label="vkd_ru_phone_yazhert">
-    Russian Phonetic (YaZHert) keyboard
-  </int>
-  <int value="602570138" label="xkb:mk::mkd">Macedonian keyboard</int>
-  <int value="612541362" label="vkd_ar">Arabic keyboard</int>
-  <int value="629711326" label="xkb:il::heb">Hebrew keyboard</int>
-  <int value="683071754" label="xkb:hr::scr">Croatian keyboard</int>
-  <int value="774753710" label="vkd_th_tis">Thai keyboard (TIS 820-2531)</int>
-  <int value="787164771" label="vkd_lo">Lao keyboard</int>
-  <int value="789603234" label="xkb:by::bel">Belarusian keyboard</int>
-  <int value="789867412" label="vkd_ethi">Ethiopic keyboard</int>
-  <int value="822222165" label="xkb:ru:phonetic:rus">
-    Russian Phonetic keyboard
-  </int>
-  <int value="825747412" label="xkb:latam::spa">Latin American keyboard</int>
-  <int value="828287201" label="vkd_ta_inscript">Tamil keyboard (InScript)</int>
-  <int value="843503620" label="ur-t-i0-und">Urdu transliteration</int>
-  <int value="871656925" label="xkb:us::fil">US keyboard</int>
-  <int value="1028639984" label="he-t-i0-und">Hebrew transliteration</int>
-  <int value="1091977227" label="vkd_my">Myanmar keyboard</int>
-  <int value="1190741118" label="am-t-i0-und">Amharic transliteration</int>
-  <int value="1203226200" label="vkd_kn_phone">Kannada keyboard (Phonetic)</int>
-  <int value="1275989482" label="xkb:ee::est">Estonian keyboard</int>
-  <int value="1292575742" label="el-t-i0-und">Greek transliteration</int>
-  <int value="1321401457" label="zh-hant-t-i0-pinyin">
-    Traditional Pinyin input method
-  </int>
-  <int value="1346294191" label="vkd_vi_tcvn">Vietnamese keyboard (TCVN)</int>
-  <int value="1364126694" label="vkd_vi_viqr">Vietnamese keyboard (VIQR)</int>
-  <int value="1409029247" label="xkb:ca::fra">Canadian French keyboard</int>
-  <int value="1411091864" label="vkd_th">Thai keyboard (Kedmanee)</int>
-  <int value="1425002521" label="vkd_ckb_ar">
-    Sorani Kurdish Arabic-based keyboard
-  </int>
-  <int value="1530194498" label="vkd_deva_phone">
-    Devanagari keyboard (Phonetic)
-  </int>
-  <int value="1624346366" label="zh-hant-t-i0-und">Zhuyin input method</int>
-  <int value="1643737979" label="xkb:fr:bepo:fra">French Bepo keyboard</int>
-  <int value="1680967466" label="sa-t-i0-und">Sanskrit transliteration</int>
-  <int value="1683010298" label="xkb:is::ice">Icelandic keyboard</int>
-  <int value="1691327142" label="vkd_gu_phone">
-    Gujarati keyboard (Phonetic)
-  </int>
-  <int value="1718072990" label="xkb:us::eng">US keyboard</int>
-  <int value="1763643144" label="xkb:lt::lit">Lithuanian keyboard</int>
-  <int value="1783807851" label="nacl_mozc_us">
-    Google Japanese Input (for US keyboard)
-  </int>
-  <int value="1842376130" label="vkd_ta_typewriter">
-    Tamil keyboard (Typewriter)
-  </int>
-  <int value="1847701260" label="xkb:pl::pol">Polish keyboard</int>
-  <int value="1851658441" label="xkb:hu:qwerty:hun">
-    Hungarian QWERTY keyboard
-  </int>
-  <int value="1882667893" label="xkb:us:colemak:eng">US Colemak keyboard</int>
-  <int value="1925299009" label="xkb:br::por">Brazilian keyboard</int>
-  <int value="1952551273" label="vkd_ta_tamil99">Tamil keyboard (Tamil99)</int>
-  <int value="1960657481" label="vkd_vi_telex">Vietnamese keyboard (Telex)</int>
-  <int value="1970923579" label="xkb:us:intl:nld">Netherlands keyboard</int>
-  <int value="1983264676" label="xkb:no::nob">Norwegian keyboard</int>
-  <int value="2007323478" label="xkb:cz::cze">Czech keyboard</int>
-  <int value="2014669693" label="xkb:kz::kaz">Kazakh keyboard</int>
-  <int value="2018878326" label="zh-hant-t-i0-cangjie-1987">
-    Cangjie input method
-  </int>
-  <int value="2031967946" label="xkb:mt::mlt">Maltese keyboard</int>
-  <int value="2060414855" label="braille">Braille Keyboard</int>
-  <int value="2077260254" label="ko-t-i0-und">Korean input method</int>
-  <int value="2121258069" label="xkb:us:dvorak:eng">US Dvorak keyboard</int>
-  <int value="2143389015" label="vkd_ne_inscript">
-    Nepali keyboard (InScript)
-  </int>
+<!--
+    Mappings for input method IDs of first-party Chrome OS IME extension ONLY
+    (i.e. extension with ID "jkghodnilhceideoidjikpgommlajknk" and defined in
+    google_xkb_manifest.json [1]), although InputMethod.ID2 histogram is
+    recorded for open-source Chromium OS and third-party IME extensions as well.
+    [1] https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json?q=google_xkb_manifest.json
+  -->
+
+  <int value="-2082426075" label="xkb:cz:qwerty:cze"/>
+  <int value="-2039513744" label="xkb:ru::rus"/>
+  <int value="-2030885731" label="vkd_fa"/>
+  <int value="-2004968165" label="xkb:gb:dvorak:eng"/>
+  <int value="-2004834194" label="xkb:ca:multix:fra"/>
+  <int value="-1992142310" label="xkb:dk::dan"/>
+  <int value="-1989523479" label="pa-t-i0-und"/>
+  <int value="-1955862460" label="xkb:ro::rum"/>
+  <int value="-1953637256" label="xkb:us:workman-intl:eng"/>
+  <int value="-1951732875" label="xkb:be::nld"/>
+  <int value="-1856842164" label="xkb:ge::geo"/>
+  <int value="-1793755122" label="zh-hant-t-i0-cangjie-1987-x-m0-simplified"/>
+  <int value="-1710145174" label="xkb:am:phonetic:arm"/>
+  <int value="-1709647399" label="xkb:mn::mon"/>
+  <int value="-1668610460" label="xkb:us:dvp:eng"/>
+  <int value="-1622129313" label="sr-t-i0-und"/>
+  <int value="-1616253108" label="ta-t-i0-und"/>
+  <int value="-1608984043" label="vkd_my_myansan"/>
+  <int value="-1520893793" label="vkd_te_phone"/>
+  <int value="-1474243589" label="xkb:it::ita"/>
+  <int value="-1466408010" label="hi-t-i0-und"/>
+  <int value="-1408581676" label="xkb:gb:extd:eng"/>
+  <int value="-1402880636" label="xkb:se::swe"/>
+  <int value="-1386518472" label="vkd_ru_phone_aatseel"/>
+  <int value="-1362493117" label="zh-hant-t-i0-dayi-1988"/>
+  <int value="-1356599825" label="bn-t-i0-und"/>
+  <int value="-1346114248" label="vkd_vi_vni"/>
+  <int value="-1338032348" label="xkb:de:neo:ger"/>
+  <int value="-1148371254" label="xkb:us:intl:por"/>
+  <int value="-1093390778" label="vkd_ml_phone"/>
+  <int value="-1084450354" label="gu-t-i0-und"/>
+  <int value="-1053378431" label="xkb:tr::tur"/>
+  <int value="-1044696009" label="ar-t-i0-und"/>
+  <int value="-1032532014" label="xkb:bg:phonetic:bul"/>
+  <int value="-1024152574" label="xkb:ca:eng:eng"/>
+  <int value="-1021036210" label="xkb:us::ind"/>
+  <int value="-1011117789" label="vkd_ta_itrans"/>
+  <int value="-994915284" label="xkb:ch:fr:fra"/>
+  <int value="-955047705" label="xkb:sk::slo"/>
+  <int value="-942739805" label="xkb:tr:f:tur"/>
+  <int value="-923332388" label="xkb:ua::ukr"/>
+  <int value="-827208209" label="xkb:hu::hun"/>
+  <int value="-769279084" label="xkb:us:intl_pc:eng"/>
+  <int value="-694112343" label="vkd_ne_phone"/>
+  <int value="-666585286" label="xkb:bg::bul"/>
+  <int value="-650362029" label="xkb:ie::ga"/>
+  <int value="-607101895" label="zh-t-i0-pinyin"/>
+  <int value="-547772150" label="xkb:ro:std:rum"/>
+  <int value="-545936253" label="zh-hant-t-i0-array-1992"/>
+  <int value="-537214862" label="xkb:us:intl_pc:eng"/>
+  <int value="-535089160" label="xkb:us::msa"/>
+  <int value="-512360986" label="xkb:us:altgr-intl:eng"/>
+  <int value="-496003957" label="xkb:de::ger"/>
+  <int value="-489436211" label="xkb:us:intl_pc:nld"/>
+  <int value="-456651526" label="kn-t-i0-und"/>
+  <int value="-383640577" label="or-t-i0-und"/>
+  <int value="-366323598" label="fa-t-i0-und"/>
+  <int value="-352571373" label="xkb:rs::srp"/>
+  <int value="-329596558" label="te-t-i0-und"/>
+  <int value="-299716106" label="xkb:si::slv"/>
+  <int value="-292687390" label="xkb:fi::fin"/>
+  <int value="-263932473" label="xkb:ch::ger"/>
+  <int value="-244167850" label="nacl_mozc_jp"/>
+  <int value="-202781885" label="xkb:us:intl:eng"/>
+  <int value="-176093583" label="vkd_bn_phone"/>
+  <int value="-119597715" label="mr-t-i0-und"/>
+  <int value="-70827301" label="xkb:be::fra"/>
+  <int value="2215666" label="xkb:jp::jpn"/>
+  <int value="23642603" label="yue-hant-t-i0-und"/>
+  <int value="28549849" label="xkb:pt::por"/>
+  <int value="60054916" label="xkb:fo::fao"/>
+  <int value="68243712" label="vkd_si"/>
+  <int value="87135772" label="xkb:fr::fra"/>
+  <int value="132261074" label="ti-t-i0-und"/>
+  <int value="193122406" label="xkb:gr::gre"/>
+  <int value="197116831" label="xkb:es::spa"/>
+  <int value="233227876" label="vkd_km"/>
+  <int value="319509360" label="xkb:be::ger"/>
+  <int value="374544129" label="vkd_th_pattajoti"/>
+  <int value="382485416" label="xkb:lv:apostrophe:lav"/>
+  <int value="469000663" label="xkb:es:cat:cat"/>
+  <int value="472995125" label="vkd_ta_phone"/>
+  <int value="484753645" label="xkb:us:workman:eng"/>
+  <int value="490329655" label="zh-t-i0-wubi-1986"/>
+  <int value="520496071" label="vkd_ckb_en"/>
+  <int value="535728072" label="ne-t-i0-und"/>
+  <int value="537062379" label="vkd_ru_phone_yazhert"/>
+  <int value="602570138" label="xkb:mk::mkd"/>
+  <int value="612541362" label="vkd_ar"/>
+  <int value="629711326" label="xkb:il::heb"/>
+  <int value="683071754" label="xkb:hr::scr"/>
+  <int value="774753710" label="vkd_th_tis"/>
+  <int value="787164771" label="vkd_lo"/>
+  <int value="789603234" label="xkb:by::bel"/>
+  <int value="789867412" label="vkd_ethi"/>
+  <int value="822222165" label="xkb:ru:phonetic:rus"/>
+  <int value="825747412" label="xkb:latam::spa"/>
+  <int value="828287201" label="vkd_ta_inscript"/>
+  <int value="843503620" label="ur-t-i0-und"/>
+  <int value="871656925" label="xkb:us::fil"/>
+  <int value="1028639984" label="he-t-i0-und"/>
+  <int value="1091977227" label="vkd_my"/>
+  <int value="1190741118" label="am-t-i0-und"/>
+  <int value="1203226200" label="vkd_kn_phone"/>
+  <int value="1275989482" label="xkb:ee::est"/>
+  <int value="1292575742" label="el-t-i0-und"/>
+  <int value="1321401457" label="zh-hant-t-i0-pinyin"/>
+  <int value="1346294191" label="vkd_vi_tcvn"/>
+  <int value="1364126694" label="vkd_vi_viqr"/>
+  <int value="1409029247" label="xkb:ca::fra"/>
+  <int value="1411091864" label="vkd_th"/>
+  <int value="1425002521" label="vkd_ckb_ar"/>
+  <int value="1530194498" label="vkd_deva_phone"/>
+  <int value="1624346366" label="zh-hant-t-i0-und"/>
+  <int value="1643737979" label="xkb:fr:bepo:fra"/>
+  <int value="1680967466" label="sa-t-i0-und"/>
+  <int value="1683010298" label="xkb:is::ice"/>
+  <int value="1691327142" label="vkd_gu_phone"/>
+  <int value="1718072990" label="xkb:us::eng"/>
+  <int value="1763643144" label="xkb:lt::lit"/>
+  <int value="1783807851" label="nacl_mozc_us"/>
+  <int value="1842376130" label="vkd_ta_typewriter"/>
+  <int value="1847701260" label="xkb:pl::pol"/>
+  <int value="1851658441" label="xkb:hu:qwerty:hun"/>
+  <int value="1882667893" label="xkb:us:colemak:eng"/>
+  <int value="1925299009" label="xkb:br::por"/>
+  <int value="1952551273" label="vkd_ta_tamil99"/>
+  <int value="1960657481" label="vkd_vi_telex"/>
+  <int value="1970923579" label="xkb:us:intl:nld"/>
+  <int value="1983264676" label="xkb:no::nob"/>
+  <int value="2007323478" label="xkb:cz::cze"/>
+  <int value="2014669693" label="xkb:kz::kaz"/>
+  <int value="2018878326" label="zh-hant-t-i0-cangjie-1987"/>
+  <int value="2031967946" label="xkb:mt::mlt"/>
+  <int value="2060414855" label="braille"/>
+  <int value="2077260254" label="ko-t-i0-und"/>
+  <int value="2121258069" label="xkb:us:dvorak:eng"/>
+  <int value="2143389015" label="vkd_ne_inscript"/>
 </enum>
 
 <enum name="InsecureContentType">
@@ -43052,6 +43005,7 @@
   <int value="-860534647" label="SiteDetails:enabled"/>
   <int value="-858280894" label="DelayCompetingLowPriorityRequests:disabled"/>
   <int value="-856915246" label="enable-new-audio-rendering-mixing-strategy"/>
+  <int value="-856407187" label="OnDeviceGrammarCheck:disabled"/>
   <int value="-856146376"
       label="disable_idle_sockets_close_on_memory_pressure:disabled"/>
   <int value="-856016114" label="NTPOfflinePages:disabled"/>
@@ -43984,6 +43938,7 @@
   <int value="59964519" label="OmniboxEnableClipboardProvider:disabled"/>
   <int value="59992411" label="ChangePasswordAffiliationInfo:enabled"/>
   <int value="60023885" label="AutofillNoLocalSaveOnUnmaskSuccess:disabled"/>
+  <int value="60442188" label="MultilingualTyping:enabled"/>
   <int value="61130490" label="WebViewBrotliSupport:enabled"/>
   <int value="61205887" label="enable-text-input-focus-manager"/>
   <int value="61466986" label="AsyncDns:disabled"/>
@@ -45433,6 +45388,7 @@
   <int value="1489915799" label="disable-permissions-blacklist"/>
   <int value="1490043732" label="enable-fill-on-account-select"/>
   <int value="1490255042" label="enable-overlay-scrollbar"/>
+  <int value="1492255992" label="OnDeviceGrammarCheck:enabled"/>
   <int value="1492541927" label="QuickAnswersTranslationCloudAPI:enabled"/>
   <int value="1495341532" label="disable-mtp-write-support"/>
   <int value="1495748045" label="SignedHTTPExchange:enabled"/>
@@ -45883,6 +45839,7 @@
   <int value="1933376478" label="IsolatePrerenders:enabled"/>
   <int value="1935405622" label="AppServiceInstanceRegistry:disabled"/>
   <int value="1936810062" label="WebVrVsyncAlign:enabled"/>
+  <int value="1937357350" label="MultilingualTyping:disabled"/>
   <int value="1938279796" label="PromosOnLocalNtp:disabled"/>
   <int value="1939413645" label="enable-invalid-cert-collection"/>
   <int value="1939884866" label="web-otp-backend"/>
diff --git a/tools/metrics/histograms/histograms_xml/content/histograms.xml b/tools/metrics/histograms/histograms_xml/content/histograms.xml
index d0403073..bcaec12 100644
--- a/tools/metrics/histograms/histograms_xml/content/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/content/histograms.xml
@@ -90,6 +90,17 @@
 
 <histogram name="ContentCapture.SentContentCount" units="count"
     expires_after="2021-04-04">
+  <obsolete>
+    Replaced by ContentCapture.SentContentCount2 in M89, which uses standard
+    buckets for 10k counts rather than exact linear buckets.
+  </obsolete>
+  <owner>michaelbai@chromium.org</owner>
+  <owner>src/third_party/blink/renderer/core/content_capture/OWNERS</owner>
+  <summary>The total number of content captures sent for a document.</summary>
+</histogram>
+
+<histogram name="ContentCapture.SentContentCount2" units="count"
+    expires_after="2021-04-04">
   <owner>michaelbai@chromium.org</owner>
   <owner>src/third_party/blink/renderer/core/content_capture/OWNERS</owner>
   <summary>The total number of content captures sent for a document.</summary>
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml
index 0add7a6..2f21c8f 100644
--- a/tools/metrics/histograms/histograms_xml/input/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -338,8 +338,11 @@
   <owner>shuchen@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
-    The breakdown of input method usage by input method IDs. Recorded when the
-    user presses keys on physical or on-screen keyboard.
+    Breakdown of input method usage by input method IDs. Recorded for an input
+    method ID when the system's 'active input method' is switched to the input
+    method with that ID. Note: In this context, 'input method ID' refers to the
+    'global' input method IDs, i.e. tuple of the extension ID the input method
+    belongs to and the extension-local ID of the input method.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/histograms_xml/search/histograms.xml b/tools/metrics/histograms/histograms_xml/search/histograms.xml
index 6786336..9f72a493 100644
--- a/tools/metrics/histograms/histograms_xml/search/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/search/histograms.xml
@@ -666,7 +666,8 @@
   <owner>twellington@chromium.org</owner>
   <summary>
     The state of the Contextual Search Preference. Can be logged multiple times.
-    Used to determine the population size (user view). Implemented for Android.
+    Used to determine the population size (user view). Logged whenever the
+    Chrome application is paused. Implemented for Android.
   </summary>
 </histogram>
 
@@ -1402,6 +1403,35 @@
   </summary>
 </histogram>
 
+<histogram name="Search.RelatedSearches.AllUserPermissions"
+    enum="ContextualSearchPermissions" expires_after="M91">
+  <owner>donnd@chromium.org</owner>
+  <owner>related-searches-vteam@google.com</owner>
+  <summary>
+    Enumerates all users by the permissions needed in order to use the Related
+    Searches feature. This tells us the potential user pool if we were to remove
+    one of the current requirements (which are sending page content and sending
+    the URL to Google). Logged whenever the Chrome application is paused. NOTE:
+    Use the Count unique clients option to count users since multiple events are
+    logged for each user. Implemented for Android.
+  </summary>
+</histogram>
+
+<histogram name="Search.RelatedSearches.QualifiedUsers" enum="Boolean"
+    expires_after="M92">
+  <owner>donnd@chromium.org</owner>
+  <owner>related-searches-vteam@google.com</owner>
+  <summary>
+    Records true for every user that is qualified for the Related Searches
+    experiment regardless of whether that feature is enabled or not. Never logs
+    false. Used to validate that population sizes are relatively equal (since
+    only a subset is actually qualified). Logged whenever a user triggers
+    Contextual Search in way that could activate Related Searches (i.e. sends
+    context). NOTE: Use the Count unique clients option to count users since
+    multiple events are logged for each user. Implemented for Android.
+  </summary>
+</histogram>
+
 <histogram name="Search.SearchEngineListedInPromoDialog"
     enum="OmniboxSearchEngineType" expires_after="M81">
 <!-- Name completed by histogram_suffixes name="SearchEnginePromoOrdering" and name="SearchEnginePromoDeviceType" -->
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 9a7a3e7..96d077fa 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": "589c99eb2e8e954600fa441597fc26b6fb46d498",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/8f8e2dc7d50fac8d40137e49c39d1a0c2cc10ed7/trace_processor_shell.exe"
+            "hash": "cb4cdb03766f3c69c381bdf17ce5ac88bc71e30e",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/254ea334b65f8a7d5d4ab087f861df0572fa6af7/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "f5e047022dcbe6fa044a7da9739ac8623d0b1efb",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/8f8e2dc7d50fac8d40137e49c39d1a0c2cc10ed7/trace_processor_shell"
+            "hash": "23c054de3c5738695431f962b9f5e79a888eb135",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/254ea334b65f8a7d5d4ab087f861df0572fa6af7/trace_processor_shell"
         },
         "linux": {
-            "hash": "d62b8d8400fd5124b7e6ead6eae14a6e1dfa58c3",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/8f8e2dc7d50fac8d40137e49c39d1a0c2cc10ed7/trace_processor_shell"
+            "hash": "68451064b202f0b800ab6a86da1cdeb450fe5745",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/254ea334b65f8a7d5d4ab087f861df0572fa6af7/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 4c192cb..bece735 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -74,6 +74,8 @@
     "//ui/gfx/geometry",
     "//ui/strings",
   ]
+
+  deps = [ "//build:chromeos_buildflags" ]
 }
 
 #if (is_win) {
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc
index 3786dfa..396aca9 100644
--- a/ui/accessibility/accessibility_features.cc
+++ b/ui/accessibility/accessibility_features.cc
@@ -6,6 +6,7 @@
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace features {
 
@@ -76,7 +77,7 @@
 }
 #endif  // defined(OS_WIN)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const base::Feature kAccessibilityCursorColor{"AccessibilityCursorColor",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -90,7 +91,7 @@
 bool IsMagnifierNewFocusFollowingEnabled() {
   return base::FeatureList::IsEnabled(::features::kMagnifierNewFocusFollowing);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 const base::Feature kAugmentExistingImageLabels{
     "AugmentExistingImageLabels", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -114,7 +115,7 @@
   return base::FeatureList::IsEnabled(::features::kEnableAriaElementReflection);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const base::Feature kSelectToSpeakNavigationControl{
     "SelectToSpeakNavigationControl", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -122,6 +123,6 @@
   return base::FeatureList::IsEnabled(
       ::features::kSelectToSpeakNavigationControl);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace features
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h
index 8b6ff3c..a954257 100644
--- a/ui/accessibility/accessibility_features.h
+++ b/ui/accessibility/accessibility_features.h
@@ -8,6 +8,7 @@
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/accessibility/ax_base_export.h"
 
 namespace features {
@@ -62,7 +63,7 @@
 
 #endif  // defined(OS_WIN)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 AX_BASE_EXPORT extern const base::Feature kAccessibilityCursorColor;
 
 // Returns true if the accessibility cursor color feature is enabled, letting
@@ -75,7 +76,7 @@
 
 // Returns true if the new magnifier focus following feature is enabled.
 AX_BASE_EXPORT bool IsMagnifierNewFocusFollowingEnabled();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Enables Get Image Descriptions to augment existing images labels,
 // rather than only provide descriptions for completely unlabeled images.
@@ -103,14 +104,14 @@
 // Returns true if ARIA element reflection is enabled.
 AX_BASE_EXPORT bool IsAriaElementReflectionEnabled();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Enables enhanced Select-to-speak features that allow users broader control
 // of TTS (pause, resume, skip between sentences and paragraphs).
 AX_BASE_EXPORT extern const base::Feature kSelectToSpeakNavigationControl;
 
 // Returns true if enhanced Select-to-speak features are enabled.
 AX_BASE_EXPORT bool IsSelectToSpeakNavigationControlEnabled();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace features
 
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index 76fd98c6..ec6f242 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -5,13 +5,14 @@
 #include "ui/accessibility/ax_role_properties.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 
 namespace ui {
 
 namespace {
 
-#if defined(OS_WIN) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH)
 constexpr bool kExposeLayoutTableAsDataTable = true;
 #else
 constexpr bool kExposeLayoutTableAsDataTable = false;
diff --git a/ui/accessibility/extensions/BUILD.gn b/ui/accessibility/extensions/BUILD.gn
index d824a5b..843c030 100644
--- a/ui/accessibility/extensions/BUILD.gn
+++ b/ui/accessibility/extensions/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//tools/grit/grit_rule.gni")
 
 group("extensions") {
@@ -9,14 +10,14 @@
     ":caretbrowsing",
     ":colorenhancer",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "chromevoxclassic:chromevox" ]
   }
 }
 
 group("extension_tests") {
   testonly = true
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps = [ "chromevoxclassic:chromevox_tests" ]
   }
 }
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 193de1bb..94a749246 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -101,6 +101,7 @@
     "//base",
     "//base:i18n",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//cc",
     "//cc/mojo_embedder",
     "//components/discardable_memory/client",
@@ -228,6 +229,7 @@
   deps = [
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//cc:test_support",
     "//components/viz/test:test_support",
     "//skia",
@@ -343,6 +345,7 @@
   deps = [
     ":test_support",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//cc/mojo_embedder",
     "//components/viz/client",
     "//mojo/core/embedder",
diff --git a/ui/aura/client/drag_drop_client_observer.h b/ui/aura/client/drag_drop_client_observer.h
index aca9bda..f668f77c 100644
--- a/ui/aura/client/drag_drop_client_observer.h
+++ b/ui/aura/client/drag_drop_client_observer.h
@@ -5,6 +5,7 @@
 #ifndef UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
 #define UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
 
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/aura_export.h"
 
 namespace aura {
@@ -18,7 +19,7 @@
   // Called when dragging ended.
   virtual void OnDragEnded() = 0;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Called when the set of currently selected drag operation changes during the
   // drag. |action| is a bitmask of the actions selected by the client. This is
   // to provide feedback during the operation, it does not take precedence over
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index eb83ab3..e4edb299 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/input_state_lookup.h"
@@ -67,7 +68,7 @@
   ui::test::EnableTestConfigForPlatformWindows();
 #endif
 
-#if defined(USE_OZONE) && defined(OS_CHROMEOS)
+#if defined(USE_OZONE) && BUILDFLAG(IS_CHROMEOS_ASH)
   ui::DisableNativeUiEventDispatchForTest();
 #endif
 
diff --git a/ui/aura/test/ui_controls_ozone.cc b/ui/aura/test/ui_controls_ozone.cc
index 43a7a07..2572a3c 100644
--- a/ui/aura/test/ui_controls_ozone.cc
+++ b/ui/aura/test/ui_controls_ozone.cc
@@ -5,6 +5,7 @@
 #include "ui/aura/test/ui_controls_ozone.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace aura {
 namespace test {
@@ -203,7 +204,7 @@
                          ui_controls::kNoAccelerator);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 bool UIControlsOzone::SendTouchEvents(int action, int id, int x, int y) {
   return SendTouchEventsNotifyWhenDone(action, id, x, y, base::OnceClosure());
 }
diff --git a/ui/aura/test/ui_controls_ozone.h b/ui/aura/test/ui_controls_ozone.h
index e85844f..3250174 100644
--- a/ui/aura/test/ui_controls_ozone.h
+++ b/ui/aura/test/ui_controls_ozone.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/aura_test_utils.h"
 #include "ui/aura/test/env_test_helper.h"
@@ -60,7 +61,7 @@
                                      base::OnceClosure closure,
                                      int accelerator_state) override;
   bool SendMouseClick(ui_controls::MouseButton type) override;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool SendTouchEvents(int action, int id, int x, int y) override;
   bool SendTouchEventsNotifyWhenDone(int action,
                                      int id,
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc
index d0d68f4..1ded0d6 100644
--- a/ui/aura/window_targeter.cc
+++ b/ui/aura/window_targeter.cc
@@ -4,6 +4,7 @@
 
 #include "ui/aura/window_targeter.h"
 
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/event_client.h"
 #include "ui/aura/client/focus_client.h"
@@ -122,7 +123,7 @@
     if (consumer)
       return static_cast<Window*>(consumer);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // If the initial touch is outside the window's display, target the root.
     // This is used for bezel gesture events (eg. swiping in from screen edge).
     display::Display display =
@@ -223,7 +224,7 @@
     if (target) {
       window->ConvertEventToTarget(target, event);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       if (window->IsRootWindow() && event->HasNativeEvent()) {
         // If window is root, and the target is in a different host, we need to
         // convert the native event to the target's host as well. This happens
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index b2521da..6af7c8dd 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -8,6 +8,7 @@
 #include "base/feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "components/viz/common/features.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/cursor_client.h"
@@ -408,7 +409,7 @@
       context_factory, base::ThreadTaskRunnerHandle::Get(),
       ui::IsPixelCanvasRecordingEnabled(), use_external_begin_frame_control,
       force_software_compositor);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   compositor_->AddObserver(this);
 #endif
   if (!dispatcher()) {
@@ -507,7 +508,7 @@
 // Chrome OS is handled in WindowTreeHostManager::OnDisplayMetricsChanged.
 // Chrome OS requires additional handling for the bounds that we do not need to
 // do for other OSes.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (metrics & DISPLAY_METRIC_DEVICE_SCALE_FACTOR &&
       display.id() == GetDisplayId())
     OnHostResizedInPixels(GetBoundsInPixels().size());
diff --git a/ui/aura/window_tree_host_unittest.cc b/ui/aura/window_tree_host_unittest.cc
index 2bf6cb8..fbbef1cf 100644
--- a/ui/aura/window_tree_host_unittest.cc
+++ b/ui/aura/window_tree_host_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/test_screen.h"
 #include "ui/aura/test/window_event_dispatcher_test_api.h"
@@ -91,7 +92,7 @@
   EXPECT_EQ(gfx::Rect(300, 400), host()->window()->bounds());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(WindowTreeHostTest, HoldPointerMovesOnChildResizing) {
   aura::WindowEventDispatcher* dispatcher = host()->dispatcher();
 
@@ -115,7 +116,7 @@
 }
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests if scale factor changes take effect. Previously a scale factor change
 // wouldn't take effect without a bounds change. For context see
 // https://crbug.com/1087626
diff --git a/ui/aura_extra/BUILD.gn b/ui/aura_extra/BUILD.gn
index cc402e9..70fd26f 100644
--- a/ui/aura_extra/BUILD.gn
+++ b/ui/aura_extra/BUILD.gn
@@ -42,6 +42,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//cc/paint",
     "//third_party/zlib/google:compression_utils",
     "//ui/base",
diff --git a/ui/aura_extra/skia_vector_resource.cc b/ui/aura_extra/skia_vector_resource.cc
index 940a8e0..ffa9596 100644
--- a/ui/aura_extra/skia_vector_resource.cc
+++ b/ui/aura_extra/skia_vector_resource.cc
@@ -10,6 +10,7 @@
 #include "base/no_destructor.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/paint/skottie_wrapper.h"
 #include "third_party/zlib/google/compression_utils.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -40,7 +41,7 @@
     return std::make_unique<gfx::SkiaVectorAnimation>(found->second);
 
   auto& rb = ui::ResourceBundle::GetSharedInstance();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ui::ScaleFactor scale_factor_to_load = rb.GetMaxScaleFactor();
 #elif defined(OS_WIN)
   ui::ScaleFactor scale_factor_to_load = display::win::GetDPIScale() > 1.25
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc
index 77fa7c2..1140e65 100644
--- a/ui/base/clipboard/clipboard_ozone.cc
+++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -311,7 +311,9 @@
 // Uses the factory in the clipboard_linux otherwise.
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
-#if defined(OS_CHROMEOS) || !defined(OS_LINUX)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if !(defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 // Clipboard factory method.
 Clipboard* Clipboard::Create() {
 // linux-chromeos uses non-backed clipboard by default, but supports ozone x11
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc
index d963378..bcff5f9 100644
--- a/ui/base/ime/chromeos/input_method_chromeos.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -409,7 +409,15 @@
 bool InputMethodChromeOS::SetAutocorrectRange(const gfx::Range& range) {
   if (IsTextInputTypeNone())
     return false;
-  return GetTextInputClient()->SetAutocorrectRange(range);
+
+  // If we have pending key events, then delay the operation until
+  // |ProcessKeyEventPostIME|. Otherwise, process it immediately.
+  if (handling_key_event_) {
+    pending_autocorrect_range_ = range;
+    return true;
+  } else {
+    return GetTextInputClient()->SetAutocorrectRange(range);
+  }
 }
 
 bool InputMethodChromeOS::SetSelectionRange(uint32_t start, uint32_t end) {
@@ -595,6 +603,11 @@
     pending_composition_range_.reset();
   }
 
+  if (pending_autocorrect_range_) {
+    client->SetAutocorrectRange(*pending_autocorrect_range_);
+    pending_autocorrect_range_.reset();
+  }
+
   // We should not clear composition text here, as it may belong to the next
   // composition session.
   result_text_.clear();
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h
index 02507ba0..46df5bed 100644
--- a/ui/base/ime/chromeos/input_method_chromeos.h
+++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -170,6 +170,8 @@
   // Indicates whether there is a pending SetCompositionRange operation.
   base::Optional<PendingSetCompositionRange> pending_composition_range_;
 
+  base::Optional<gfx::Range> pending_autocorrect_range_;
+
   // An object to compose a character from a sequence of key presses
   // including dead key etc.
   CharacterComposer character_composer_;
diff --git a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
index 2b90fcb..bef9601 100644
--- a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -319,6 +319,16 @@
     GetTextFromRange(range, &composition_text_.text);
     return true;
   }
+  bool SetAutocorrectRange(const gfx::Range& range) override {
+    // TODO(crbug.com/1148157): This is a workaround to ensure that the range is
+    // valid in the text. Change this class to a proper fake so that the text
+    // contents can be queried accurately.
+    if (!inserted_text_.empty() || inserted_char_ != 0) {
+      DummyTextInputClient::SetAutocorrectRange(range);
+      return true;
+    }
+    return false;
+  }
 
   bool HasNativeEvent() const {
     return dispatched_key_event_.HasNativeEvent();
@@ -421,6 +431,7 @@
        OnWillChangeFocusedClientClearAutocorrectRange) {
   input_type_ = TEXT_INPUT_TYPE_TEXT;
   ime_->SetFocusedTextInputClient(this);
+  ime_->CommitText("hello");
   ime_->SetAutocorrectRange(gfx::Range(0, 5));
   EXPECT_EQ(gfx::Range(0, 5), this->GetAutocorrectRange());
 
@@ -1148,4 +1159,20 @@
   EXPECT_FALSE(input_method_manager_->state()->is_jp_ime());
 }
 
+TEST_F(InputMethodChromeOSKeyEventTest,
+       SetAutocorrectRangeRunsAfterCommitText) {
+  input_type_ = TEXT_INPUT_TYPE_TEXT;
+  ime_->OnTextInputTypeChanged(this);
+  ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
+  ime_->DispatchKeyEvent(&event);
+
+  ime_->CommitText("a");
+  ime_->SetAutocorrectRange(gfx::Range(0, 1));
+  std::move(mock_ime_engine_handler_->last_passed_callback())
+      .Run(/*handled=*/true);
+
+  EXPECT_EQ(L'a', inserted_char_);
+  EXPECT_EQ(gfx::Range(0, 1), GetAutocorrectRange());
+}
+
 }  // namespace ui
diff --git a/ui/chromeos/BUILD.gn b/ui/chromeos/BUILD.gn
index f5bf43b..d0cc829 100644
--- a/ui/chromeos/BUILD.gn
+++ b/ui/chromeos/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 
 component("chromeos") {
   output_name = "ui_chromeos"
diff --git a/ui/chromeos/events/BUILD.gn b/ui/chromeos/events/BUILD.gn
index 3792fdb..b26f637d 100644
--- a/ui/chromeos/events/BUILD.gn
+++ b/ui/chromeos/events/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ozone.gni")
 import("//build/config/ui.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 
 source_set("events") {
   output_name = "ui_chromeos_events"
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
index be15d7b..e13010e 100644
--- a/ui/chromeos/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -83,6 +83,9 @@
   <message name="IDS_FILE_BROWSER_RECENT_ROOT_LABEL" desc="A label for the 'Recent' root which shows files recently modified by the user.">
     Recent
   </message>
+  <message name="IDS_FILE_BROWSER_TRASH_ROOT_LABEL" desc="A label for the 'Trash' root which shows files in the trash / recycle bin.">
+    Trash
+  </message>
   <message name="IDS_FILE_BROWSER_DOCPROVIDER_ROOT_LABEL_WITH_SUMMARY" desc="A label for a documents provider root, which has both title and summary.">
     <ph name="ROOT_TITLE">$1<ex>MyCloudProvider</ex></ph> (<ph name="ROOT_SUMMARY">$2<ex>me@example.com</ex></ph>)
   </message>
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_ROOT_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_ROOT_LABEL.png.sha1
new file mode 100644
index 0000000..b7145ec
--- /dev/null
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_TRASH_ROOT_LABEL.png.sha1
@@ -0,0 +1 @@
+8062e88d91b2b313ecfd088ba03bacfe05c8a043
\ No newline at end of file
diff --git a/ui/color/BUILD.gn b/ui/color/BUILD.gn
index 898dd69..ca2c15e 100644
--- a/ui/color/BUILD.gn
+++ b/ui/color/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//testing/test.gni")
 import("//ui/base/ui_features.gni")
 
@@ -82,7 +83,7 @@
 
   public_deps = [ "//base" ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "cros/native_color_mixers.cc" ]
   } else if (is_fuchsia) {
     sources += [ "fuchsia/native_color_mixers.cc" ]
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index 3fcae95b..9383a56 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -88,6 +88,7 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//cc/animation",
     "//cc/paint",
     "//components/viz/host",
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 31df4855..07c2a39 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -19,6 +19,7 @@
 #include "base/system/sys_info.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/animation/animation_host.h"
 #include "cc/animation/animation_id_provider.h"
 #include "cc/animation/animation_timeline.h"
@@ -737,7 +738,9 @@
   throughput_tracker_map_.erase(tracker_id);
 }
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 void Compositor::OnCompleteSwapWithNewSize(const gfx::Size& size) {
   for (auto& observer : observer_list_)
     observer.OnCompositingCompleteSwapWithNewSize(this, size);
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 9dc5de9..bb08a017 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -18,6 +18,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/metrics/frame_sequence_tracker.h"
 #include "cc/paint/element_id.h"
 #include "cc/trees/layer_tree_host.h"
@@ -367,7 +368,9 @@
   void StopThroughtputTracker(TrackerId tracker_id) override;
   void CancelThroughtputTracker(TrackerId tracker_id) override;
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   void OnCompleteSwapWithNewSize(const gfx::Size& size);
 #endif
 
diff --git a/ui/compositor/compositor_observer.h b/ui/compositor/compositor_observer.h
index 5855c94..32c6e49 100644
--- a/ui/compositor/compositor_observer.h
+++ b/ui/compositor/compositor_observer.h
@@ -7,6 +7,7 @@
 
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/compositor/compositor_export.h"
 
 namespace gfx {
@@ -43,7 +44,9 @@
   // Called when a child of the compositor is resizing.
   virtual void OnCompositingChildResizing(Compositor* compositor) {}
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Called when a swap with new size is completed.
   virtual void OnCompositingCompleteSwapWithNewSize(ui::Compositor* compositor,
                                                     const gfx::Size& size) {}
diff --git a/ui/compositor/compositor_switches.cc b/ui/compositor/compositor_switches.cc
index 7cd81cfa..adf348c 100644
--- a/ui/compositor/compositor_switches.cc
+++ b/ui/compositor/compositor_switches.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace switches {
 
@@ -35,7 +36,7 @@
 // to be done via corner points. See https://crbug.com/720596 for details.
 const base::Feature kEnablePixelCanvasRecording {
   "enable-pixel-canvas-recording",
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       base::FEATURE_ENABLED_BY_DEFAULT
 #else
       base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/ui/content_accelerators/BUILD.gn b/ui/content_accelerators/BUILD.gn
index ce101e7..11977a1 100644
--- a/ui/content_accelerators/BUILD.gn
+++ b/ui/content_accelerators/BUILD.gn
@@ -9,6 +9,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//third_party/blink/public:blink_headers",
     "//ui/base",
     "//ui/events",
diff --git a/ui/content_accelerators/accelerator_util.cc b/ui/content_accelerators/accelerator_util.cc
index 027c6e80..223df25 100644
--- a/ui/content_accelerators/accelerator_util.cc
+++ b/ui/content_accelerators/accelerator_util.cc
@@ -5,6 +5,7 @@
 #include "ui/content_accelerators/accelerator_util.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/events/blink/blink_event_util.h"
@@ -15,7 +16,7 @@
 
 ui::Accelerator GetAcceleratorFromNativeWebKeyboardEvent(
     const content::NativeWebKeyboardEvent& event) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (::features::IsNewShortcutMappingEnabled()) {
     // TODO: This must be the same as below and it's simpler.
     // Cleanup if this change sticks.
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn
index 02e3967..e2923c7 100644
--- a/ui/events/ozone/BUILD.gn
+++ b/ui/events/ozone/BUILD.gn
@@ -32,6 +32,7 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//ui/display",
     "//ui/events",
     "//ui/events/devices",
diff --git a/ui/file_manager/base/js/volume_manager_types.js b/ui/file_manager/base/js/volume_manager_types.js
index 08447c0b..4d0db38 100644
--- a/ui/file_manager/base/js/volume_manager_types.js
+++ b/ui/file_manager/base/js/volume_manager_types.js
@@ -142,6 +142,9 @@
 
   // Root directory of recently-modified video files.
   RECENT_VIDEOS: 'recent_videos',
+
+  // Trash.
+  TRASH: 'trash',
 };
 Object.freeze(VolumeManagerCommon.RootType);
 
@@ -182,6 +185,7 @@
   VolumeManagerCommon.RootType.RECENT_AUDIO,                      // 24
   VolumeManagerCommon.RootType.RECENT_IMAGES,                     // 25
   VolumeManagerCommon.RootType.RECENT_VIDEOS,                     // 26
+  VolumeManagerCommon.RootType.TRASH,                             // 27
 ];
 console.assert(
     Object.keys(VolumeManagerCommon.RootType).length ===
@@ -236,6 +240,7 @@
   ANDROID_FILES: 'android_files',
   MY_FILES: 'my_files',
   SMB: 'smb',
+  TRASH: 'trash',
 };
 
 /**
@@ -309,6 +314,8 @@
       return VolumeManagerCommon.VolumeType.MY_FILES;
     case VolumeManagerCommon.RootType.SMB:
       return VolumeManagerCommon.VolumeType.SMB;
+    case VolumeManagerCommon.RootType.TRASH:
+      return VolumeManagerCommon.VolumeType.TRASH;
   }
 
   assertNotReached('Unknown root type: ' + rootType);
@@ -345,6 +352,8 @@
       return VolumeManagerCommon.RootType.REMOVABLE;
     case VolumeManagerCommon.VolumeType.SMB:
       return VolumeManagerCommon.RootType.SMB;
+    case VolumeManagerCommon.VolumeType.TRASH:
+      return VolumeManagerCommon.RootType.TRASH;
   }
 
   assertNotReached('Unknown volume type: ' + volumeType);
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index d6d767d0..05dc3e1 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -651,6 +651,7 @@
     ":file_operation_util",
     "//ui/file_manager/base/js:volume_manager_types",
     "//ui/file_manager/externs:volume_manager",
+    "//ui/file_manager/file_manager/common/js:trash_config",
   ]
 }
 
diff --git a/ui/file_manager/file_manager/background/js/background_scripts.js b/ui/file_manager/file_manager/background/js/background_scripts.js
index 1e7374b..4f162bc 100644
--- a/ui/file_manager/file_manager/background/js/background_scripts.js
+++ b/ui/file_manager/file_manager/background/js/background_scripts.js
@@ -10,6 +10,7 @@
 // <include src="../../common/js/lru_cache.js">
 // <include src="../../common/js/progress_center_common.js">
 // <include src="../../common/js/importer_common.js">
+// <include src="../../common/js/trash_config.js">
 // <include src="metadata_proxy.js">
 // <include src="crostini.js">
 // <include src="device_handler.js">
diff --git a/ui/file_manager/file_manager/background/js/entry_location_impl.js b/ui/file_manager/file_manager/background/js/entry_location_impl.js
index 1dd3894..ea2e504b 100644
--- a/ui/file_manager/file_manager/background/js/entry_location_impl.js
+++ b/ui/file_manager/file_manager/background/js/entry_location_impl.js
@@ -58,7 +58,8 @@
     this.hasFixedLabel = this.isRootEntry &&
         (rootType !== VolumeManagerCommon.RootType.SHARED_DRIVE &&
          rootType !== VolumeManagerCommon.RootType.COMPUTER &&
-         rootType !== VolumeManagerCommon.RootType.REMOVABLE);
+         rootType !== VolumeManagerCommon.RootType.REMOVABLE &&
+         rootType !== VolumeManagerCommon.RootType.TRASH);
     Object.freeze(this);
   }
 }
diff --git a/ui/file_manager/file_manager/background/js/trash.js b/ui/file_manager/file_manager/background/js/trash.js
index 638a9a3..c338aeda 100644
--- a/ui/file_manager/file_manager/background/js/trash.js
+++ b/ui/file_manager/file_manager/background/js/trash.js
@@ -8,44 +8,6 @@
  */
 
 /**
- * Wrapper for /.Trash/files and /.Trash/info directories.
- */
-class TrashDirs {
-  /**
-   * @param {!DirectoryEntry} files /.Trash/files directory entry.
-   * @param {!DirectoryEntry} info /.Trash/info directory entry.
-   */
-  constructor(files, info) {
-    this.files = files;
-    this.info = info;
-  }
-}
-
-/**
- * Configuration for where Trash is stored in a volume.
- */
-class TrashConfig {
-  /**
-   * @param {VolumeManagerCommon.RootType} rootType
-   * @param {string} topDir Top directory of volume. Must end with a slash to
-   *     make comparisons simpler.
-   * @param {string} trashDir Trash directory. Must end with a slash to make
-   *     comparisons simpler.
-   * @param {boolean=} prefixPathWithRemoteMount Optional, if true, 'Path=' in
-   *     *.trashinfo is prefixed with the volume.remoteMountPath. For crostini,
-   *     this is the user's homedir (/home/<username>).
-   */
-  constructor(rootType, topDir, trashDir, prefixPathWithRemoteMount = false) {
-    this.id = `${rootType}-${topDir}`;
-    this.rootType = rootType;
-    this.topDir = topDir;
-    this.trashDir = trashDir;
-    this.prefixPathWithRemoteMount = prefixPathWithRemoteMount;
-    this.pathPrefix = '';
-  }
-}
-
-/**
  * Result from calling Trash.removeFileOrDirectory().
  */
 class TrashItem {
@@ -102,9 +64,9 @@
       return null;
     }
     const fullPathSlash = entry.fullPath + '/';
-    for (const config of Trash.CONFIG) {
+    for (const config of TrashConfig.CONFIG) {
       const entryInVolume = fullPathSlash.startsWith(config.topDir);
-      if (config.rootType === info.rootType && entryInVolume) {
+      if (config.volumeType === info.volumeInfo.volumeType && entryInVolume) {
         if (config.prefixPathWithRemoteMount) {
           config.pathPrefix = info.volumeInfo.remoteMountPath;
         }
@@ -174,16 +136,8 @@
       return trashDirs;
     }
 
-    let trashRoot = entry.filesystem.root;
-    const parts = config.trashDir.split('/');
-    for (const part of parts) {
-      if (part) {
-        trashRoot = await this.getDirectory_(trashRoot, part);
-      }
-    }
-    const trashFiles = await this.getDirectory_(trashRoot, 'files');
-    const trashInfo = await this.getDirectory_(trashRoot, 'info');
-    trashDirs = new TrashDirs(trashFiles, trashInfo);
+    trashDirs = await TrashDirs.getTrashDirs(entry.filesystem, config);
+
     // Check and remove old items max once per session.
     this.removeOldItems_(trashDirs, Date.now());
     this.trashDirs_[config.id] = trashDirs;
@@ -219,21 +173,6 @@
   }
 
   /**
-   * Promise wrapper for FileSystemDirectoryEntry.getDirectory().
-   *
-   * @param {!DirectoryEntry} dirEntry current directory.
-   * @param {string} path name of directory within dirEntry.
-   * @return {!Promise<!DirectoryEntry>} Promise which resolves with
-   *     <dirEntry>/<path>.
-   * @private
-   */
-  getDirectory_(dirEntry, path) {
-    return new Promise((resolve, reject) => {
-      dirEntry.getDirectory(path, {create: true}, resolve, reject);
-    });
-  }
-
-  /**
    * Promise wrapper for FileSystemEntry.moveTo().
    *
    * @param {!T} srcEntry source entry to move.
@@ -314,7 +253,7 @@
     // Move to last directory in path, making sure dirs are created if needed.
     let dir = trashItem.filesEntry.filesystem.root;
     for (let i = 0; i < parts.length - 1; i++) {
-      dir = await this.getDirectory_(dir, parts[i]);
+      dir = await TrashDirs.getDirectory(dir, parts[i]);
     }
 
     // Restore filesEntry first, then remove its trash infoEntry.
@@ -449,21 +388,3 @@
  */
 Trash.AUTO_DELETE_INTERVAL_MS = 30 * 24 * 60 * 60 * 1000;
 
-/**
- * Volumes supported for Trash, and location of Trash dir. Items will be
- * searched in order.
- *
- * @type {!Array<!TrashConfig>}
- */
-Trash.CONFIG = [
-  // MyFiles/Downloads is a separate volume on a physical device, and doing a
-  // move from MyFiles/Downloads/<path> to MyFiles/.Trash actually does a
-  // copy across volumes, so we have a dedicated MyFiles/Downloads/.Trash.
-  new TrashConfig(
-      VolumeManagerCommon.RootType.DOWNLOADS, '/Downloads/',
-      '/Downloads/.Trash/'),
-  new TrashConfig(VolumeManagerCommon.RootType.DOWNLOADS, '/', '/.Trash/'),
-  new TrashConfig(
-      VolumeManagerCommon.RootType.CROSTINI, '/', '/.local/share/Trash/',
-      /*prefixPathWithRemoteMount=*/ true),
-];
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn
index 25c4c6e..04f983c 100644
--- a/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -33,6 +33,7 @@
     ":metrics_base",
     ":mock_entry",
     ":progress_center_common",
+    ":trash_config",
     ":util",
     "//ui/file_manager/base/js:volume_manager_types",
   ]
@@ -231,6 +232,10 @@
 js_library("progress_center_common") {
 }
 
+js_library("trash_config") {
+  deps = [ "//ui/file_manager/base/js:volume_manager_types" ]
+}
+
 js_library("unittest_util") {
   testonly = true
 
diff --git a/ui/file_manager/file_manager/common/js/trash_config.js b/ui/file_manager/file_manager/common/js/trash_config.js
new file mode 100644
index 0000000..96d7cc9
--- /dev/null
+++ b/ui/file_manager/file_manager/common/js/trash_config.js
@@ -0,0 +1,100 @@
+// 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.
+
+/**
+ * @fileoverview Trash configuration of volumes which have trash, and where it
+ * is located.
+ */
+
+/**
+ * Configuration for where Trash is stored in a volume.
+ */
+class TrashConfig {
+  /**
+   * @param {VolumeManagerCommon.VolumeType} volumeType
+   * @param {string} topDir Top directory of volume. Must end with a slash to
+   *     make comparisons simpler.
+   * @param {string} trashDir Trash directory. Must end with a slash to make
+   *     comparisons simpler.
+   * @param {boolean=} prefixPathWithRemoteMount Optional, if true, 'Path=' in
+   *     *.trashinfo is prefixed with the volume.remoteMountPath. For crostini,
+   *     this is the user's homedir (/home/<username>).
+   */
+  constructor(volumeType, topDir, trashDir, prefixPathWithRemoteMount = false) {
+    this.id = `${volumeType}-${topDir}`;
+    this.volumeType = volumeType;
+    this.topDir = topDir;
+    this.trashDir = trashDir;
+    this.prefixPathWithRemoteMount = prefixPathWithRemoteMount;
+    this.pathPrefix = '';
+  }
+}
+
+/**
+ * Volumes supported for Trash, and location of Trash dir. Items will be
+ * searched in order.
+ *
+ * @type {!Array<!TrashConfig>}
+ */
+TrashConfig.CONFIG = [
+  // MyFiles/Downloads is a separate volume on a physical device, and doing a
+  // move from MyFiles/Downloads/<path> to MyFiles/.Trash actually does a
+  // copy across volumes, so we have a dedicated MyFiles/Downloads/.Trash.
+  new TrashConfig(
+      VolumeManagerCommon.VolumeType.DOWNLOADS, '/Downloads/',
+      '/Downloads/.Trash/'),
+  new TrashConfig(VolumeManagerCommon.VolumeType.DOWNLOADS, '/', '/.Trash/'),
+  new TrashConfig(
+      VolumeManagerCommon.VolumeType.CROSTINI, '/', '/.local/share/Trash/',
+      /*prefixPathWithRemoteMount=*/ true),
+];
+
+/**
+ * Wrapper for /.Trash/files and /.Trash/info directories.
+ */
+class TrashDirs {
+  /**
+   * @param {!DirectoryEntry} files /.Trash/files directory entry.
+   * @param {!DirectoryEntry} info /.Trash/info directory entry.
+   */
+  constructor(files, info) {
+    this.files = files;
+    this.info = info;
+  }
+
+  /**
+   * Promise wrapper for FileSystemDirectoryEntry.getDirectory(). Creates dir if
+   * it does not exist.
+   *
+   * @param {!DirectoryEntry} dirEntry current directory.
+   * @param {string} path name of directory within dirEntry.
+   * @return {!Promise<!DirectoryEntry>} Promise which resolves with
+   *     <dirEntry>/<path>.
+   */
+  static getDirectory(dirEntry, path) {
+    return new Promise((resolve, reject) => {
+      dirEntry.getDirectory(path, {create: true}, resolve, reject);
+    });
+  }
+
+  /**
+   * Get trash dirs from file system as specified in config.
+   *
+   * @param {!FileSystem} fileSystem File system from volume with trash.
+   * @param {!TrashConfig} config Config specifying trash dir location.
+   * @return {!Promise<!TrashDirs>} Promise which resolves with trash dirs.
+   */
+  static async getTrashDirs(fileSystem, config) {
+    let trashRoot = fileSystem.root;
+    const parts = config.trashDir.split('/');
+    for (const part of parts) {
+      if (part) {
+        trashRoot = await TrashDirs.getDirectory(trashRoot, part);
+      }
+    }
+    const trashFiles = await TrashDirs.getDirectory(trashRoot, 'files');
+    const trashInfo = await TrashDirs.getDirectory(trashRoot, 'info');
+    return new TrashDirs(trashFiles, trashInfo);
+  }
+}
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index 7567d0f..42dc085 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1154,6 +1154,8 @@
       return str('LINUX_FILES_ROOT_LABEL');
     case VolumeManagerCommon.RootType.MY_FILES:
       return str('MY_FILES_ROOT_LABEL');
+    case VolumeManagerCommon.RootType.TRASH:
+      return str('TRASH_ROOT_LABEL');
     case VolumeManagerCommon.RootType.MEDIA_VIEW:
       const mediaViewRootType =
           VolumeManagerCommon.getMediaViewRootTypeFromVolumeId(
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css
index 875ba11..ca0b018 100644
--- a/ui/file_manager/file_manager/foreground/css/file_types.css
+++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -917,3 +917,16 @@
 .tree-row > .file-row > [volume-type-icon='smb'] {
   -webkit-mask-image: url(../images/volumes/smb.svg);
 }
+
+body.files-ng [file-type-icon='trash'] {
+  -webkit-mask-image: url(../images/files/ui/delete_ng.svg);
+  background-color: currentColor;
+  background-image: none;
+}
+
+.tree-row > .file-row > [root-type-icon='trash'],
+.tree-row > .file-row > [volume-type-icon='trash'] {
+  -webkit-mask-image: url(../images/files/ui/delete_ng.svg);
+}
+
+
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index a9c52c4..77ca46d2 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -85,6 +85,7 @@
     ":task_history",
     ":thumbnail_loader",
     ":toolbar_controller",
+    ":trash",
     ":web_store_utils",
     ":webui_command_extender",
   ]
@@ -678,6 +679,7 @@
   deps = [
     ":android_app_list_model",
     ":folder_shortcuts_data_model",
+    ":trash",
     "//ui/webui/resources/js/cr:event_target",
     "//ui/webui/resources/js/cr/ui:array_data_model",
   ]
@@ -877,6 +879,19 @@
   ]
 }
 
+js_library("trash") {
+  deps = [
+    "//ui/file_manager/base/js:volume_manager_types",
+    "//ui/file_manager/file_manager/common/js:files_app_entry_types",
+    "//ui/file_manager/file_manager/common/js:trash_config",
+  ]
+  externs_list = [
+    "//ui/file_manager/externs/files_app_entry_interfaces.js",
+    "//ui/file_manager/externs/volume_info.js",
+    "//ui/file_manager/externs/volume_manager.js",
+  ]
+}
+
 js_library("web_store_utils") {
   deps = [ ":constants" ]
 }
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js
index 41dcbf7..4a782d8 100644
--- a/ui/file_manager/file_manager/foreground/js/main_scripts.js
+++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -87,6 +87,7 @@
 // <include src="../../common/js/util.js">
 // <include src="../../common/js/progress_center_common.js">
 // <include src="../../common/js/importer_common.js">
+// <include src="../../common/js/trash_config.js">
 //
 // <include src="constants.js">
 // <include src="crossover_search_utils.js">
@@ -159,6 +160,7 @@
 // <include src="toolbar_controller.js">
 // <include src="thumbnail_loader.js">
 // <include src="list_thumbnail_loader.js">
+// <include src="trash.js">
 // <include src="providers_model.js">
 // <include src="ui/actions_submenu.js">
 // <include src="ui/banners.js">
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
index 95e4feaf..e59e774 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
@@ -13,6 +13,7 @@
   ENTRY_LIST: 'entry-list',
   DRIVE: 'drive',
   ANDROID_APP: 'android-app',
+  TRASH: 'trash',
 };
 
 /**
@@ -217,6 +218,12 @@
     this.linuxFilesItem_ = null;
 
     /**
+     * Root folder for trash.
+     * @private {NavigationModelFakeItem}
+     */
+    this.trashItem_ = null;
+
+    /**
      * NavigationModel for MyFiles, since DirectoryTree expect it to be always
      * the same reference we keep the initial reference for reuse.
      * @private {NavigationModelFakeItem}
@@ -661,6 +668,17 @@
       }
     }
 
+    // Add Trash to My Files.
+    if (loadTimeData.getBoolean('FILES_TRASH_ENABLED')) {
+      if (!this.trashItem_) {
+        this.trashItem_ = new NavigationModelFakeItem(
+            str('TRASH_ROOT_LABEL'), NavigationModelItemType.TRASH,
+            new TrashRootEntry(this.volumeManager_));
+      }
+      myFilesEntry.removeByRootType(VolumeManagerCommon.RootType.TRASH);
+      myFilesEntry.addEntry(this.trashItem_.entry);
+    }
+
     // Add Drive.
     let hasDrive = false;
     for (const driveItem of getVolumes(VolumeManagerCommon.VolumeType.DRIVE)) {
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index 1c2eede..6a1cf89a 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -42,6 +42,7 @@
     MY_FILES_ROOT_LABEL: 'My files',
     DOWNLOADS_DIRECTORY_LABEL: 'Downloads',
     DRIVE_DIRECTORY_LABEL: 'My Drive',
+    FILES_TRASH_ENABLED: false,
   };
   window.loadTimeData.getString = id => {
     return window.loadTimeData.data_[id] || id;
@@ -111,6 +112,13 @@
   const myFilesEntryList = /** @type {!EntryList} */ (myFilesItem.entry);
   assertEquals(1, myFilesEntryList.getUIChildren().length);
   assertEquals('linux-files-label', myFilesEntryList.getUIChildren()[0].name);
+
+  // Trash is displayed within My files when feature is enabled.
+  window.loadTimeData.data_['FILES_TRASH_ENABLED'] = true;
+  model.reorderNavigationItems_();
+  assertEquals(6, model.length);
+  assertEquals(2, myFilesEntryList.getUIChildren().length);
+  assertEquals('Trash', myFilesEntryList.getUIChildren()[1].name);
 }
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/trash.js b/ui/file_manager/file_manager/foreground/js/trash.js
new file mode 100644
index 0000000..7f1dfd6
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/trash.js
@@ -0,0 +1,293 @@
+// 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.
+
+/**
+ * @fileoverview Trash UI entry types based on
+ * https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html.
+ *
+ * When you move /dir/hello.txt to trash, you get:
+ *  .Trash/files/hello.txt
+ *  .Trash/info/hello.trashinfo
+ *
+ * .Trash/files/hello.txt is the original file.  .Trash/files.hello.trashinfo is
+ * a text file which looks like:
+ *  [Trash Info]
+ *  Path=/dir/hello.txt
+ *  DeletionDate=2020-11-02T07:35:38.964Z
+ *
+ * TrashEntry combines both files for display.
+ */
+
+/**
+ * Used to control the display of items in Trash. Combines the info from both
+ * .Trash/info and ./Trash/files.
+ *
+ * @implements {FilesAppEntry}
+ */
+class TrashEntry {
+  /**
+   * @param {string} path Path of deleted file from infoEntry.
+   * @param {!Date} deletionDate DeletionDate of deleted file from infoEntry.
+   * @param {!FileEntry} infoEntry trash info entry.
+   * @param {!Entry} filesEntry trash files entry.
+   * @param {string} rootLabel Root label to prefix display name.
+   */
+  constructor(path, deletionDate, infoEntry, filesEntry, rootLabel) {
+    /** @private */
+    this.deletionDate_ = deletionDate;
+
+    /** @private */
+    this.infoEntry_ = infoEntry;
+
+    /** @private */
+    this.filesEntry_ = filesEntry;
+
+    /** @override Entry */
+    this.filesystem = filesEntry.filesystem;
+
+    /** @override Entry */
+    this.fullPath = path;
+
+    /** @override Entry */
+    this.isDirectory = filesEntry.isDirectory;
+
+    /** @override Entry  */
+    this.isFile = filesEntry.isFile;
+
+    /**
+     * Show the root label and the whole Path=<path> from infoEntry as the name.
+     * This allows users to differentiate deleted files such as /a/hello.txt and
+     * /b/hello.txt.
+     * @override Entry
+     */
+    this.name = rootLabel + path.replace(/\//g, ' › ');
+
+    /** @override FileEntry */
+    this.file = filesEntry.file;
+
+    /** @override FilesAppEntry */
+    this.rootType = VolumeManagerCommon.RootType.TRASH;
+
+    /** @override FilesAppEntry */
+    this.type_name = 'TrashEntry';
+  }
+
+  /** @override Entry */
+  toURL() {
+    return 'trash://' + this.infoEntry_.toURL();
+  }
+
+  /**
+   * Pass through to getMetadata() of filesEntry, keep size, but use
+   * DeletionDate from infoEntry for modificationTime.
+   *
+   * @override Entry
+   */
+  getMetadata(success, error) {
+    this.filesEntry_.getMetadata(m => {
+      success({modificationTime: this.deletionDate_, size: m.size});
+    }, error);
+  }
+
+  /** @override Entry */
+  getParent() {
+    return null;
+  }
+
+  /** @override FilesAppEntry */
+  get isNativeType() {
+    return false;
+  }
+
+  /** @override FilesAppEntry */
+  getNativeEntry() {
+    return null;
+  }
+}
+/**
+ * Reads all entries in each of .Trash/info and .Trash/files and produces a
+ * single stream of TrashEntry.
+ *
+ * @extends {DirectoryReader}
+ */
+class TrashDirectoryReader {
+  /**
+   * @param {!FileSystem} fileSystem trash file system.
+   * @param {!TrashConfig} config trash config.
+   * @param {string} rootLabel Label of trash root to prefix entries with.
+   */
+  constructor(fileSystem, config, rootLabel) {
+    this.fileSystem_ = fileSystem;
+    this.config_ = config;
+    this.rootLabel_ = rootLabel;
+
+    /** @private {!Object<!Entry>} all entries in .Trash/files keyed by name. */
+    this.filesEntries_ = {};
+
+    /**
+     * DirectoryReader of .Trash/info which needs to be persisted across calls
+     * to readEntries().
+     *
+     * @private {?DirectoryReader}
+     */
+    this.infoReader_ = null;
+  }
+
+  /**
+   * Create a trash entry if infoEntry and matching files entry are valid, else
+   * return null.
+   *
+   * @param {!FileEntry} infoEntry trash info entry.
+   * @return {!Promise<TrashEntry?>}
+   */
+  async createTrashEntry_(infoEntry) {
+    const error = (msg, text = '') => {
+      console.error(`${msg}: ${infoEntry.toURL()}: ${text}`);
+      return null;
+    };
+
+    // Ignore any directories.
+    if (!infoEntry.isFile) {
+      return error('Ignoring unexpected trash info directory');
+    }
+
+    // Ignore any files not *.trashinfo.
+    if (!infoEntry.name.endsWith('.trashinfo')) {
+      return error('Ignoring unexpected trash info file');
+    }
+
+    const name = infoEntry.name.substring(0, infoEntry.name.length - 10);
+    const filesEntry = this.filesEntries_[name];
+    delete this.filesEntries_[name];
+
+    // Ignore any .trashinfo file with no matching file entry.
+    if (!filesEntry) {
+      return error('Ignoring trash info file with no matching files entry');
+    }
+
+    const file =
+        await new Promise((resolve, reject) => infoEntry.file(resolve, reject));
+    const text = await file.text();
+    let found = text.match(/^Path=(.*)/m);
+    if (!found) {
+      return error('Ignoring trash info file with no Path', text);
+    }
+    const path = found[1];
+
+    found = text.match(/^DeletionDate=(.*)/m);
+    if (!found) {
+      return error('Ignoring trash info file with no DeletionDate', text);
+    }
+
+    const d = Date.parse(found[1]);
+    if (!found) {
+      return error('Ignoring trash info file with invalid DeletionDate', text);
+    }
+
+    return new TrashEntry(
+        path, new Date(d), infoEntry, filesEntry, this.rootLabel_);
+  }
+
+  /**
+   * Async version of readEntries(). This function may be called multiple times
+   * and returns an empty result to indicate end of stream.
+   *
+   * Reads all items in .Trash/files on first call and caches them. Then reads
+   * 1 or more batches of infoReader until we have at least 1 valid result to
+   * send, or reader is exhausted.
+   *
+   * @param {function(!Array<!Entry>)} success
+   * @param {function(!FileError)=} error
+   */
+  async readEntriesAsync_(success, error) {
+    const ls = (reader) => {
+      return new Promise((resolve, reject) => {
+        reader.readEntries(results => resolve(results), error => reject(error));
+      });
+    };
+
+    // Read all of .Trash/files on first call.
+    if (!this.infoReader_) {
+      const trashDirs =
+          await TrashDirs.getTrashDirs(this.fileSystem_, this.config_);
+
+      // Get all entries in trash/files.
+      const filesReader = trashDirs.files.createReader();
+      try {
+        while (true) {
+          const entries = await ls(filesReader);
+          if (!entries.length) {
+            break;
+          }
+          entries.forEach(entry => this.filesEntries_[entry.name] = entry);
+        }
+      } catch (e) {
+        console.error('Error reading trash files entries', e);
+        error(e);
+        return;
+      }
+
+      this.infoReader_ = trashDirs.info.createReader();
+    }
+
+    // Consume infoReader which is initialized in the first call. Read from
+    // .Trash/info until we have at least 1 result, or end of stream.
+    const result = [];
+    while (true) {
+      let entries = [];
+      try {
+        entries = await ls(this.infoReader_);
+      } catch (e) {
+        console.error('Error reading trash info entries', e);
+        error(e);
+        return;
+      }
+      for (const e of entries) {
+        const trashEntry = await this.createTrashEntry_(e);
+        if (trashEntry) {
+          result.push(trashEntry);
+        }
+      }
+      if (!entries.length || result.length) {
+        break;
+      }
+    }
+    success(result);
+  }
+
+  /** @override */
+  readEntries(success, error) {
+    this.readEntriesAsync_(success, error);
+  }
+}
+
+/**
+ * Root Trash entry sits inside "My files". It shows the combined entries of
+ * trashes defined in TrashConfig.
+ */
+class TrashRootEntry extends FakeEntryImpl {
+  /**
+   * @param {!VolumeManager} volumeManager
+   */
+  constructor(volumeManager) {
+    super('Trash', VolumeManagerCommon.RootType.TRASH);
+    this.volumeManager_ = volumeManager;
+  }
+
+  /** @override */
+  createReader() {
+    const readers = [];
+    TrashConfig.CONFIG.forEach(c => {
+      const info =
+          this.volumeManager_.getCurrentProfileVolumeInfo(c.volumeType);
+      if (info && info.fileSystem) {
+        const locationInfo =
+            this.volumeManager_.getLocationInfo(info.fileSystem.root);
+        const rootLabel = util.getRootTypeLabel(assert(locationInfo));
+        readers.push(new TrashDirectoryReader(info.fileSystem, c, rootLabel));
+      }
+    });
+    return new CombinedReaders(readers);
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
index eaac535..c37fc9c8 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -2563,6 +2563,11 @@
       return new AndroidAppItem(
           /** @type {!NavigationModelAndroidAppItem} */ (modelItem), tree);
       break;
+    case NavigationModelItemType.TRASH:
+      return new FakeItem(
+          VolumeManagerCommon.RootType.TRASH,
+          /** @type {!NavigationModelFakeItem} */ (modelItem), tree);
+      break;
   }
   assertNotReached(`No DirectoryItem model: "${modelItem.type}"`);
 };
diff --git a/ui/file_manager/file_manager/test/check_select.js b/ui/file_manager/file_manager/test/check_select.js
index de358342..f5cb6b3 100644
--- a/ui/file_manager/file_manager/test/check_select.js
+++ b/ui/file_manager/file_manager/test/check_select.js
@@ -9,13 +9,15 @@
 
   // Click 2nd last file on checkmark to start check-select-mode.
   assertTrue(test.fakeMouseClick(
-      '#file-list li.table-row:nth-of-type(4) .detail-checkmark'));
-  await test.waitForElement('#file-list li[selected].table-row:nth-of-type(4)');
+      '#file-list li.table-row:nth-last-of-type(2) .detail-checkmark'));
+  await test.waitForElement(
+      '#file-list li[selected].table-row:nth-last-of-type(2)');
 
   // Click last file on checkmark, adds to selection.
   assertTrue(test.fakeMouseClick(
-      '#file-list li.table-row:nth-of-type(5) .detail-checkmark'));
-  await test.waitForElement('#file-list li[selected].table-row:nth-of-type(5)');
+      '#file-list li.table-row:nth-last-of-type(1) .detail-checkmark'));
+  await test.waitForElement(
+      '#file-list li[selected].table-row:nth-last-of-type(1)');
   assertEquals(2, document.querySelectorAll('#file-list li[selected]').length);
 
   // Click selection menu (3-dots).
diff --git a/ui/file_manager/file_manager/test/crostini_mount.js b/ui/file_manager/file_manager/test/crostini_mount.js
index 2749819..24b03141 100644
--- a/ui/file_manager/file_manager/test/crostini_mount.js
+++ b/ui/file_manager/file_manager/test/crostini_mount.js
@@ -59,7 +59,7 @@
 
   // MyFiles folder should be shown when crostini goes away.
   await test.waitForFiles(test.TestEntryInfo.getExpectedRows(
-      test.BASIC_MY_FILES_ENTRY_SET_WITH_LINUX_FILES));
+      test.BASIC_MY_FILES_ENTRY_SET_WITH_FAKES));
 
   done();
 };
diff --git a/ui/file_manager/file_manager/test/crostini_share.js b/ui/file_manager/file_manager/test/crostini_share.js
index 2a95f306..1ce3282 100644
--- a/ui/file_manager/file_manager/test/crostini_share.js
+++ b/ui/file_manager/file_manager/test/crostini_share.js
@@ -145,7 +145,7 @@
   // Go back to 'My files' and ensure message is not shown.
   assertTrue(test.fakeMouseDoubleClick(myFilesDirTree), 'click My files');
   await test.waitForFiles(test.TestEntryInfo.getExpectedRows(
-      test.BASIC_MY_FILES_ENTRY_SET_WITH_LINUX_FILES));
+      test.BASIC_MY_FILES_ENTRY_SET_WITH_FAKES));
   await test.waitForElement(shareMessageHidden);
 
   // Dispatch unshare event which is normally initiated when the user
diff --git a/ui/file_manager/file_manager/test/js/test_util.js b/ui/file_manager/file_manager/test/js/test_util.js
index cf539c1d..da969c5 100644
--- a/ui/file_manager/file_manager/test/js/test_util.js
+++ b/ui/file_manager/file_manager/test/js/test_util.js
@@ -257,6 +257,10 @@
   tiniFile: new test.TestEntryInfo(
       test.EntryType.FILE, 'text.txt', 'test.tini', '', test.SharedOption.NONE,
       'Jan 1, 1980, 11:59 PM', 'test.tini', '51 bytes', 'Crostini image file'),
+
+  trash: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, '', 'Trash', '', test.SharedOption.NONE, '...',
+      'Trash', '--', 'Folder'),
 };
 
 /**
@@ -274,12 +278,12 @@
 ];
 
 /**
- * MyFiles plus the fake item 'Linux files'.
+ * MyFiles plus the fake items 'Linux files' and 'Trash'.
  * @type {!Array<!test.TestEntryInfo>}
  * @const
  */
-test.BASIC_MY_FILES_ENTRY_SET_WITH_LINUX_FILES =
-    test.BASIC_MY_FILES_ENTRY_SET.concat([test.ENTRIES.linuxFiles]);
+test.BASIC_MY_FILES_ENTRY_SET_WITH_FAKES = test.BASIC_MY_FILES_ENTRY_SET.concat(
+    [test.ENTRIES.linuxFiles, test.ENTRIES.trash]);
 
 /**
  * Basic entry set for the drive volume.
@@ -604,7 +608,8 @@
     assertTrue(test.fakeMouseClick(myFilesElement), 'click MyFiles');
   }
   test.refreshFileList();
-  const filesShown = entriesMyFiles.concat([test.ENTRIES.linuxFiles]);
+  const filesShown =
+      entriesMyFiles.concat([test.ENTRIES.linuxFiles, test.ENTRIES.trash]);
   return test.waitForFiles(test.TestEntryInfo.getExpectedRows(filesShown));
 };
 
diff --git a/ui/file_manager/file_manager/test/plugin_vm.js b/ui/file_manager/file_manager/test/plugin_vm.js
index f1c595a7..42938a15 100644
--- a/ui/file_manager/file_manager/test/plugin_vm.js
+++ b/ui/file_manager/file_manager/test/plugin_vm.js
@@ -59,7 +59,7 @@
       [test.ENTRIES.pluginVm, test.ENTRIES.photosInPluginVm], [], []);
   test.refreshFileList();
   await test.waitForFiles(test.TestEntryInfo.getExpectedRows(
-      [test.ENTRIES.pluginVm, test.ENTRIES.linuxFiles]));
+      [test.ENTRIES.pluginVm, test.ENTRIES.linuxFiles, test.ENTRIES.trash]));
 
   // Verify folder icon.
   await test.waitForElement(iconFolder);
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js
index 2d50079..e9a3fe8 100644
--- a/ui/file_manager/integration_tests/file_manager/quick_view.js
+++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -1359,9 +1359,8 @@
   };
 
   /**
-   * Tests opening Quick View on an JPEG image that has EXIF
-   * displays the EXIF information in the QuickView Metadata
-   * Box.
+   * Tests that opening Quick View on a JPEG image with EXIF displays the EXIF
+   * information in the QuickView Metadata Box.
    */
   testcase.openQuickViewImageExif = async () => {
     const caller = getCaller();
diff --git a/ui/file_manager/integration_tests/file_manager/trash.js b/ui/file_manager/integration_tests/file_manager/trash.js
index 2f29293b..374412a 100644
--- a/ui/file_manager/integration_tests/file_manager/trash.js
+++ b/ui/file_manager/integration_tests/file_manager/trash.js
@@ -21,6 +21,11 @@
   await remoteCall.waitForElementLost(
       appId, '#file-list [file-name="hello.txt"]');
 
+  // Navigate to /Trash and ensure the file is shown.
+  await navigateWithDirectoryTree(appId, '/Trash');
+  await remoteCall.waitForElement(
+      appId, '#file-list [file-name="My files › Downloads › hello.txt"]');
+
   // Open the gear menu by clicking the gear button.
   chrome.test.assertTrue(await remoteCall.callRemoteTestUtil(
       'fakeMouseClick', appId, ['#gear-button']));
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 4ea779d..aa3feff 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -299,6 +299,7 @@
     "//base:base_static",
     "//base:i18n",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//device/vr/buildflags",
     "//skia",
     "//third_party/zlib",
@@ -430,6 +431,7 @@
     ]
   }
   deps = [
+    "//build:chromeos_buildflags",
     "//skia:skcms",
     "//ui/gfx:buffer_types",
   ]
@@ -467,6 +469,8 @@
     ":gfx_export",
     "//base",
   ]
+
+  deps = [ "//build:chromeos_buildflags" ]
 }
 
 group("selection_bound") {
@@ -564,6 +568,7 @@
     ":native_widget_types",
     "//base",
     "//build:chromecast_buildflags",
+    "//build:chromeos_buildflags",
     "//ui/gfx/geometry",
   ]
 
@@ -794,6 +799,7 @@
     ":test_support",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//skia",
     "//skia:skcms",
     "//testing/gtest",
@@ -939,6 +945,7 @@
     ":gfx",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
   ]
 
   dict = "test/data/render_text/unicode_text_fuzzer.dict"
diff --git a/ui/gfx/animation/BUILD.gn b/ui/gfx/animation/BUILD.gn
index 34625ed2..e544b09 100644
--- a/ui/gfx/animation/BUILD.gn
+++ b/ui/gfx/animation/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 
 if (is_android) {
@@ -44,7 +45,7 @@
     sources += [ "animation_win.cc" ]
   }
 
-  if (is_linux) {
+  if (is_linux || is_chromeos_lacros) {
     sources += [
       "animation_linux.cc",
       "animation_settings_provider_linux.cc",
@@ -71,6 +72,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//skia",
     "//ui/gfx:geometry_skia",
     "//ui/gfx:gfx_export",
diff --git a/ui/gfx/animation/animation.cc b/ui/gfx/animation/animation.cc
index 0b1d4f2..1056018 100644
--- a/ui/gfx/animation/animation.cc
+++ b/ui/gfx/animation/animation.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/animation/animation_container.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/tween.h"
@@ -111,7 +112,7 @@
          RichAnimationRenderMode::FORCE_ENABLED;
 }
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_IOS) || \
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_IOS) || \
     defined(OS_FUCHSIA)
 // static
 bool Animation::ShouldRenderRichAnimationImpl() {
@@ -136,8 +137,8 @@
   prefers_reduced_motion_ = false;
 }
 #endif  // !defined(OS_ANDROID)
-#endif  // defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_IOS) ||
-        // defined(OS_FUCHSIA)
+#endif  // defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_IOS)
+        // || defined(OS_FUCHSIA)
 
 // static
 bool Animation::PrefersReducedMotion() {
diff --git a/ui/gfx/display_color_spaces.cc b/ui/gfx/display_color_spaces.cc
index 08c30ede..6016876 100644
--- a/ui/gfx/display_color_spaces.cc
+++ b/ui/gfx/display_color_spaces.cc
@@ -5,6 +5,7 @@
 #include "ui/gfx/display_color_spaces.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace gfx {
 
@@ -19,7 +20,7 @@
 gfx::BufferFormat DefaultBufferFormat() {
   // ChromeOS expects the default buffer format be BGRA_8888 in several places.
   // https://crbug.com/1057501, https://crbug.com/1073237
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return gfx::BufferFormat::BGRA_8888;
 #else
   return gfx::BufferFormat::RGBA_8888;
diff --git a/ui/gfx/font_render_params_linux.cc b/ui/gfx/font_render_params_linux.cc
index 838626ea..3ab8b2e 100644
--- a/ui/gfx/font_render_params_linux.cc
+++ b/ui/gfx/font_render_params_linux.cc
@@ -21,6 +21,7 @@
 #include "base/synchronization/lock.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/linux/fontconfig_util.h"
 #include "ui/gfx/skia_font_delegate.h"
@@ -227,7 +228,7 @@
     params.subpixel_positioning = false;
   } else if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
                  switches::kDisableFontSubpixelPositioning)) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     params.subpixel_positioning = actual_query.device_scale_factor > 1.0f;
 #else
     // We want to enable subpixel positioning for fractional dsf.
@@ -235,7 +236,7 @@
         std::abs(std::round(actual_query.device_scale_factor) -
                  actual_query.device_scale_factor) >
         std::numeric_limits<float>::epsilon();
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
     // To enable subpixel positioning, we need to disable hinting.
     if (params.subpixel_positioning)
diff --git a/ui/gfx/font_render_params_linux_unittest.cc b/ui/gfx/font_render_params_linux_unittest.cc
index b3236a32..770708d 100644
--- a/ui/gfx/font_render_params_linux_unittest.cc
+++ b/ui/gfx/font_render_params_linux_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/fontconfig_util_linux.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/linux/fontconfig_util.h"
@@ -363,12 +364,12 @@
     FontRenderParams params =
         GetFontRenderParams(FontRenderParamsQuery(), nullptr);
     EXPECT_TRUE(params.antialiasing);
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     EXPECT_TRUE(params.subpixel_positioning);
 #else
     // Integral scale factor does not require subpixel positioning.
     EXPECT_FALSE(params.subpixel_positioning);
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
     SetFontRenderParamsDeviceScaleFactor(1.0f);
   }
 }
diff --git a/ui/gfx/linux/client_native_pixmap_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_dmabuf.cc
index 8c94f8b..ca5440a3 100644
--- a/ui/gfx/linux/client_native_pixmap_dmabuf.cc
+++ b/ui/gfx/linux/client_native_pixmap_dmabuf.cc
@@ -24,6 +24,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "build/chromecast_buildflags.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/switches.h"
 
@@ -104,7 +105,7 @@
 #endif
 
   bool disable_yuv_biplanar = true;
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMECAST)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMECAST)
   // IsConfigurationSupported(SCANOUT_CPU_READ_WRITE) is used by the renderer
   // to tell whether the platform supports sampling a given format. Zero-copy
   // video capture and encoding requires gfx::BufferFormat::YUV_420_BIPLANAR to
diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h
index f823bb3..334d61f 100644
--- a/ui/gfx/native_widget_types.h
+++ b/ui/gfx/native_widget_types.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/gfx_export.h"
 
 #if defined(OS_ANDROID)
@@ -103,7 +104,9 @@
 #endif
 class SkBitmap;
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 extern "C" {
 struct _AtkObject;
 typedef struct _AtkObject AtkObject;
@@ -204,7 +207,9 @@
 #elif defined(OS_MAC)
 typedef NSFont* NativeFont;
 typedef id NativeViewAccessible;
-#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#elif defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 // Linux doesn't have a native font type.
 typedef AtkObject* NativeViewAccessible;
 #else
diff --git a/ui/gfx/platform_font_skia.cc b/ui/gfx/platform_font_skia.cc
index 0e49019..cc4ea36 100644
--- a/ui/gfx/platform_font_skia.cc
+++ b/ui/gfx/platform_font_skia.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "third_party/skia/include/core/SkFont.h"
 #include "third_party/skia/include/core/SkFontMetrics.h"
 #include "third_party/skia/include/core/SkFontStyle.h"
@@ -171,7 +172,7 @@
     delegate->GetDefaultFontDescription(&family, &size_pixels, &style, &weight,
                                         &params);
   } else if (default_font_description_) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // On ChromeOS, a FontList font description string is stored as a
     // translatable resource and passed in via SetDefaultFontDescription().
     FontRenderParamsQuery query;
diff --git a/ui/gfx/render_text_api_fuzzer.cc b/ui/gfx/render_text_api_fuzzer.cc
index 821cd5c2..aea6d52 100644
--- a/ui/gfx/render_text_api_fuzzer.cc
+++ b/ui/gfx/render_text_api_fuzzer.cc
@@ -14,10 +14,13 @@
 #include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/render_text.h"
 
-#if defined(OS_ANDROID) || defined(OS_LINUX)
+// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
+// complete.
+#if defined(OS_ANDROID) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 #include "base/test/test_discardable_memory_allocator.h"
 #endif
 
@@ -37,7 +40,9 @@
                           TestTimeouts::Initialize(),
                           base::test::TaskEnvironment::MainThreadType::UI)) {
     logging::SetMinLogLevel(logging::LOG_FATAL);
-#if defined(OS_ANDROID) || defined(OS_LINUX)
+// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
+// complete.
+#if defined(OS_ANDROID) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
     // Some platforms require discardable memory to use bitmap fonts.
     base::DiscardableMemoryAllocator::SetInstance(
         &discardable_memory_allocator);
@@ -46,7 +51,9 @@
     gfx::FontList::SetDefaultFontDescription(kFontDescription);
   }
 
-#if defined(OS_ANDROID) || defined(OS_LINUX)
+// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
+// complete.
+#if defined(OS_ANDROID) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   base::TestDiscardableMemoryAllocator discardable_memory_allocator;
 #endif
 
diff --git a/ui/gfx/text_elider_unittest.cc b/ui/gfx/text_elider_unittest.cc
index 71483ea..e940844 100644
--- a/ui/gfx/text_elider_unittest.cc
+++ b/ui/gfx/text_elider_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/font_list.h"
@@ -989,7 +990,7 @@
   EXPECT_LE(GetStringWidthF(lines[1], font_list), kAvailableWidth);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // This test was created specifically to test a message from crbug.com/415213.
 // It tests that width of concatenation of words equals sum of widths of the
 // words.
@@ -1004,7 +1005,7 @@
 #undef WIDTH
   SetFontRenderParamsDeviceScaleFactor(1.0f);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST(TextEliderTest, ElideRectangleString) {
   struct TestData {
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index a3bc537..3b99a1d 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/chrome_build.gni")
 import("//build/config/chromecast_build.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/ozone.gni")
 import("//build/config/ui.gni")
@@ -165,6 +166,7 @@
   deps = [
     ":buildflags",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
 
     # ANGLE includes are used cross-platform.
     "//third_party/angle:includes",
@@ -579,7 +581,7 @@
     sources += [ "gl_image_ahardwarebuffer_unittest.cc" ]
   }
 
-  if (is_linux) {
+  if (is_linux || is_chromeos_lacros) {
     sources += [ "gl_image_native_pixmap_unittest.cc" ]
   }
 
diff --git a/ui/gl/features.gni b/ui/gl/features.gni
index cd26c17..817aa6f 100644
--- a/ui/gl/features.gni
+++ b/ui/gl/features.gni
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
+
 declare_args() {
   # Should ANGLE be linked statically?
   # False by default, enabling currently supported only on Android
@@ -23,7 +25,7 @@
 
 declare_args() {
   enable_swiftshader = (is_win || is_linux || is_chromeos ||
-                        (is_mac && use_egl) || is_chromeos || is_fuchsia) &&
+                        (is_mac && use_egl) || is_chromeos_ash || is_fuchsia) &&
                        (target_cpu == "x86" || target_cpu == "x64" ||
                         target_cpu == "arm" || target_cpu == "arm64" ||
                         target_cpu == "mipsel" || target_cpu == "mips64el")
diff --git a/ui/gl/gl_features.cc b/ui/gl/gl_features.cc
index 56ef4a3..cbae797 100644
--- a/ui/gl/gl_features.cc
+++ b/ui/gl/gl_features.cc
@@ -4,6 +4,8 @@
 
 #include "ui/gl/gl_features.h"
 
+#include "build/chromeos_buildflags.h"
+
 namespace features {
 
 // Use the passthrough command decoder by default.  This can be overridden with
@@ -13,8 +15,9 @@
 // Launched on Windows, still experimental on other platforms.
 const base::Feature kDefaultPassthroughCommandDecoder{
   "DefaultPassthroughCommandDecoder",
-#if defined(OS_WIN) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(CHROMECAST_BUILD))
+#if defined(OS_WIN) ||                                       \
+    ((defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     !defined(CHROMECAST_BUILD))
       base::FEATURE_ENABLED_BY_DEFAULT
 #else
       base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/ui/gtk/BUILD.gn b/ui/gtk/BUILD.gn
index e1106392..bf6b7ee 100644
--- a/ui/gtk/BUILD.gn
+++ b/ui/gtk/BUILD.gn
@@ -2,8 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-assert(is_linux || is_chromeos, "This file should only be referenced on Linux")
+assert(is_linux || is_chromeos_lacros || is_chromeos,
+       "This file should only be referenced on Linux")
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/linux/gtk/gtk.gni")
 import("//build/config/ozone.gni")
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index dcc2ee5c..e04e764 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -26,6 +26,7 @@
 component("message_center") {
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//ui/base",
     "//ui/strings",
     "//url",
@@ -172,6 +173,7 @@
       ":test_support",
       "//base",
       "//base/test:test_support",
+      "//build:chromeos_buildflags",
       "//mojo/core/embedder",
       "//skia",
       "//testing/gmock",
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc
index 16523bb3..39a383a 100644
--- a/ui/message_center/message_center_impl_unittest.cc
+++ b/ui/message_center/message_center_impl_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/size.h"
@@ -483,7 +484,7 @@
   popup_timers_controller->OnNotificationDisplayed("id1", DISPLAY_SOURCE_POPUP);
   ASSERT_EQ(popup_timers_controller->timer_finished(), 0);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const int dismiss_time =
       popup_timers_controller->GetNotificationTimeoutDefault();
 #else
@@ -842,7 +843,7 @@
   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(MessageCenterImplTest, RemoveAllNotificationsWithPinned) {
   NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
   NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
diff --git a/ui/message_center/notification_list.cc b/ui/message_center/notification_list.cc
index 1796054b..1f357c6 100644
--- a/ui/message_center/notification_list.cc
+++ b/ui/message_center/notification_list.cc
@@ -10,6 +10,7 @@
 #include "base/check.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/image/image.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/notification_blocker.h"
@@ -341,7 +342,7 @@
     // For critical ChromeOS system notifications, we ignore the standard quiet
     // mode behaviour and show the notification anyways.
     bool effective_quiet_mode = quiet_mode_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     effective_quiet_mode &= notification->system_notification_warning_level() !=
                             SystemNotificationWarningLevel::CRITICAL_WARNING;
 #endif
diff --git a/ui/message_center/popup_timers_controller.cc b/ui/message_center/popup_timers_controller.cc
index 213de8e2..a6682c29 100644
--- a/ui/message_center/popup_timers_controller.cc
+++ b/ui/message_center/popup_timers_controller.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/stl_util.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/message_center/public/cpp/message_center_constants.h"
 
 namespace message_center {
@@ -16,7 +17,7 @@
 bool UseHighPriorityDelay(Notification* notification) {
 // Web Notifications are given a longer on-screen time on non-Chrome OS
 // platforms as there is no notification center to dismiss them to.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const bool use_high_priority_delay =
       notification->priority() > DEFAULT_PRIORITY;
 #else
diff --git a/ui/message_center/public/cpp/BUILD.gn b/ui/message_center/public/cpp/BUILD.gn
index 59337d8..54fd58f 100644
--- a/ui/message_center/public/cpp/BUILD.gn
+++ b/ui/message_center/public/cpp/BUILD.gn
@@ -22,6 +22,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//skia",
     "//ui/gfx",
     "//ui/strings",
diff --git a/ui/message_center/public/cpp/notification.cc b/ui/message_center/public/cpp/notification.cc
index a32ee61..2e390fc 100644
--- a/ui/message_center/public/cpp/notification.cc
+++ b/ui/message_center/public/cpp/notification.cc
@@ -7,6 +7,7 @@
 #include <map>
 #include <memory>
 
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -146,12 +147,12 @@
   // masking and resizing.
   gfx::ImageSkia image = small_image().AsImageSkia();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool create_masked_image =
       !optional_fields_.ignore_accent_color_for_small_image;
 #else
   bool create_masked_image = false;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   if (create_masked_image) {
     image = gfx::ImageSkiaOperations::CreateMaskedImage(
diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h
index 94d0c2a9..6ef34b6 100644
--- a/ui/message_center/public/cpp/notification.h
+++ b/ui/message_center/public/cpp/notification.h
@@ -15,6 +15,7 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image.h"
@@ -106,11 +107,11 @@
   // notification. Optional.
   gfx::Image small_image;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // If true, we simply use the raw |small_image| icon, ignoring accent color
   // styling. For example, this is used with raw icons received from Android.
   bool ignore_accent_color_for_small_image = false;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Vector version of |small_image|.
   // Used by Notification::GenerateMaskedSmallIcon.
@@ -148,11 +149,11 @@
   // depending on visual assistance systems.
   bool should_make_spoken_feedback_for_popup_updates = true;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Flag if the notification is pinned. If true, the notification is pinned
   // and the user can't remove it.
   bool pinned = false;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Vibration pattern to play when displaying the notification. There must be
   // an odd number of entries in this pattern when it's set: numbers of
@@ -384,15 +385,15 @@
   }
 
   bool pinned() const {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     return optional_fields_.pinned;
 #else
     return false;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void set_pinned(bool pinned) { optional_fields_.pinned = pinned; }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Gets a text for spoken feedback.
   const base::string16& accessible_name() const {
@@ -441,7 +442,7 @@
   // method explicitly, to avoid setting it accidentally.
   void SetSystemPriority();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void set_system_notification_warning_level(
       SystemNotificationWarningLevel warning_level) {
     system_notification_warning_level_ = warning_level;
@@ -450,7 +451,7 @@
   SystemNotificationWarningLevel system_notification_warning_level() const {
     return system_notification_warning_level_;
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   const std::string& custom_view_type() const { return custom_view_type_; }
   void set_custom_view_type(const std::string& custom_view_type) {
@@ -495,11 +496,11 @@
   // used to register the factory in MessageViewFactory.
   std::string custom_view_type_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // The warning level of a system notification.
   SystemNotificationWarningLevel system_notification_warning_level_ =
       SystemNotificationWarningLevel::NORMAL;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 }  // namespace message_center
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc
index 19b670c..7b40bb5f 100644
--- a/ui/message_center/views/message_popup_view.cc
+++ b/ui/message_center/views/message_popup_view.cc
@@ -5,6 +5,7 @@
 #include "ui/message_center/views/message_popup_view.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/display/display.h"
@@ -20,7 +21,7 @@
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/aura/window.h"
 #include "ui/aura/window_targeter.h"
 #endif
@@ -110,7 +111,9 @@
 void MessagePopupView::Show() {
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
   params.z_order = ui::ZOrderLevel::kFloatingWindow;
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Make the widget explicitly activatable as TYPE_POPUP is not activatable by
   // default but we need focus for the inline reply textarea.
   params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
@@ -134,7 +137,7 @@
 
   widget->Init(std::move(params));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS, this widget is shown in the shelf container. It means this
   // widget would inherit the parent's window targeter (ShelfWindowTarget) by
   // default. But it is not good for popup. So we override it with the normal
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index 4de15aad..2fb950e 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -454,7 +455,7 @@
 }
 
 bool MessageView::ShouldShowControlButtons() const {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Users on ChromeOS are used to the Settings and Close buttons not being
   // visible at all times, but users on other platforms expect them to be
   // visible.
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc
index f58d075a..796a71c 100644
--- a/ui/message_center/views/notification_control_buttons_view.cc
+++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "build/chromeos_buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/events/event.h"
@@ -149,7 +150,7 @@
   return kViewClassName;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void NotificationControlButtonsView::OnThemeChanged() {
   View::OnThemeChanged();
   SetBackground(views::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
diff --git a/ui/message_center/views/notification_control_buttons_view.h b/ui/message_center/views/notification_control_buttons_view.h
index 035b632..97822be6 100644
--- a/ui/message_center/views/notification_control_buttons_view.h
+++ b/ui/message_center/views/notification_control_buttons_view.h
@@ -7,6 +7,7 @@
 #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_CONTROL_BUTTONS_VIEW_H_
 
 #include "base/macros.h"
+#include "build/chromeos_buildflags.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/message_center/message_center_export.h"
 #include "ui/message_center/views/padded_button.h"
@@ -52,7 +53,7 @@
 
   // views::View
   const char* GetClassName() const override;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnThemeChanged() override;
 #endif
 
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc
index 80afef5..25d5ecf6 100644
--- a/ui/message_center/views/notification_view_md_unittest.cc
+++ b/ui/message_center/views/notification_view_md_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/events/event_processor.h"
@@ -857,7 +858,7 @@
 }
 
 // Pinning notification is ChromeOS only feature.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(NotificationViewMDTest, SlideOutPinned) {
   notification_view()->SetIsNested();
@@ -940,7 +941,7 @@
             notification_view()->GetControlButtonsView()->snooze_button());
 }
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(NotificationViewMDTest, ExpandLongMessage) {
   std::unique_ptr<Notification> notification = CreateSimpleNotification();
@@ -1197,7 +1198,7 @@
   generator.ClickLeftButton();
   EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // By clicking settings button again, it will toggle. Skip this on ChromeOS as
   // the control_buttons_view gets hidden when the inline settings are shown.
   generator.ClickLeftButton();
diff --git a/ui/message_center/views/padded_button.cc b/ui/message_center/views/padded_button.cc
index 24409c2..720e947f 100644
--- a/ui/message_center/views/padded_button.cc
+++ b/ui/message_center/views/padded_button.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "build/chromeos_buildflags.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/message_center/public/cpp/message_center_constants.h"
@@ -38,7 +39,7 @@
 void PaddedButton::OnThemeChanged() {
   ImageButton::OnThemeChanged();
   auto* theme = GetNativeTheme();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   SetBackground(views::CreateSolidBackground(theme->GetSystemColor(
       ui::NativeTheme::kColorId_NotificationButtonBackground)));
 #endif
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index 5d675682..763b98c 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -8,6 +8,7 @@
 #include "base/notreached.h"
 #include "base/optional.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
@@ -451,7 +452,7 @@
       return SkColorSetA(SK_ColorWHITE, gfx::kDisabledControlAlpha);
     case NativeTheme::kColorId_NotificationInkDropBase:
       return gfx::kGoogleBlue600;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     case NativeTheme::kColorId_NotificationButtonBackground:
       return SkColorSetA(SK_ColorWHITE, 0.9 * 0xff);
 #endif
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index 726f588a..4181c8d 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/paint/paint_canvas.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/models/menu_separator_types.h"
@@ -51,7 +52,9 @@
   // The part to be painted / sized.
   enum Part {
     kCheckbox,
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
     kFrameTopArea,
 #endif
     kInnerSpinButton,
diff --git a/ui/native_theme/native_theme_aura.cc b/ui/native_theme/native_theme_aura.cc
index fb2297a..120112d 100644
--- a/ui/native_theme/native_theme_aura.cc
+++ b/ui/native_theme/native_theme_aura.cc
@@ -76,7 +76,7 @@
     : NativeThemeBase(should_only_use_dark_colors),
       use_overlay_scrollbars_(use_overlay_scrollbars) {
 // We don't draw scrollbar buttons.
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   set_scrollbar_button_length(0);
 #endif
 
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc
index dc879e3..0632c37 100644
--- a/ui/native_theme/native_theme_base.cc
+++ b/ui/native_theme/native_theme_base.cc
@@ -12,6 +12,7 @@
 #include "base/notreached.h"
 #include "base/numerics/ranges.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkPath.h"
@@ -255,7 +256,9 @@
     case kCheckbox:
       PaintCheckbox(canvas, state, rect, extra.button, color_scheme);
       break;
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
     case kFrameTopArea:
       PaintFrameTopArea(canvas, state, rect, extra.frame_top_area,
                         color_scheme);
diff --git a/ui/native_theme/native_theme_color_id.h b/ui/native_theme/native_theme_color_id.h
index 52ac7e6..d08b6a2 100644
--- a/ui/native_theme/native_theme_color_id.h
+++ b/ui/native_theme/native_theme_color_id.h
@@ -5,6 +5,8 @@
 #ifndef UI_NATIVE_THEME_NATIVE_THEME_COLOR_ID_H_
 #define UI_NATIVE_THEME_NATIVE_THEME_COLOR_ID_H_
 
+#include "build/chromeos_buildflags.h"
+
 // Clang format mangles sectioned lists like the below badly.
 // clang-format off
 #define NATIVE_THEME_CROSS_PLATFORM_COLOR_IDS                                  \
@@ -165,13 +167,13 @@
   OP(kColorId_DefaultIconColor),                                               \
   OP(kColorId_DisabledIconColor)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define NATIVE_THEME_CHROMEOS_COLOR_IDS                                        \
   /* Notification view */                                                      \
   OP(kColorId_NotificationButtonBackground)
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define NATIVE_THEME_COLOR_IDS                                                 \
   NATIVE_THEME_CROSS_PLATFORM_COLOR_IDS,                                       \
   NATIVE_THEME_CHROMEOS_COLOR_IDS
diff --git a/ui/native_theme/native_theme_features.cc b/ui/native_theme/native_theme_features.cc
index 09575183..d08594d 100644
--- a/ui/native_theme/native_theme_features.cc
+++ b/ui/native_theme/native_theme_features.cc
@@ -9,8 +9,8 @@
 
 namespace features {
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) || \
-    BUILDFLAG(IS_LACROS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || \
+    defined(OS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS_LACROS)
 constexpr base::FeatureState kOverlayScrollbarFeatureState =
     base::FEATURE_ENABLED_BY_DEFAULT;
 #else
diff --git a/ui/ozone/common/features.cc b/ui/ozone/common/features.cc
index e8f68097..02f03c4 100644
--- a/ui/ozone/common/features.cc
+++ b/ui/ozone/common/features.cc
@@ -10,7 +10,7 @@
 
 const base::Feature kWaylandOverlayDelegation {
   "WaylandOverlayDelegation",
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
       base::FEATURE_ENABLED_BY_DEFAULT
 #else
       base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index 37a412b..0bd8a7f6 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/chromecast_build.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/ozone.gni")
 import("//gpu/vulkan/features.gni")
@@ -119,6 +120,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//build/config/linux/libdrm",
     "//gpu/vulkan:buildflags",
     "//ipc",
@@ -158,7 +160,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//ui/base/ime/chromeos" ]
   }
 
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc
index 4f84ef4..b1ccd606 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/display/display_features.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/gamma_ramp_rgb_entry.h"
@@ -156,7 +157,7 @@
   modes_ = GetDrmModeVector(info->connector());
   is_hdr_capable_ =
       params->bits_per_channel() > 8 && params->color_space().IsHDR();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   is_hdr_capable_ =
       is_hdr_capable_ &&
       base::FeatureList::IsEnabled(display::features::kUseHDRTransferFunction);
diff --git a/ui/ozone/platform/drm/host/drm_cursor.cc b/ui/ozone/platform/drm/host/drm_cursor.cc
index afed5c2..5b433602 100644
--- a/ui/ozone/platform/drm/host/drm_cursor.cc
+++ b/ui/ozone/platform/drm/host/drm_cursor.cc
@@ -8,11 +8,12 @@
 #include <utility>
 
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/ozone/platform/drm/host/drm_window_host.h"
 #include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/events/ozone/chromeos/cursor_controller.h"
 #endif
 
@@ -192,7 +193,7 @@
   if (window_ == gfx::kNullAcceleratedWidget)
     return;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   gfx::Vector2dF transformed_delta = delta;
   ui::CursorController::GetInstance()->ApplyCursorConfigForWindow(
       window_, &transformed_delta);
@@ -232,7 +233,7 @@
       gfx::PointF(confined_bounds_.right() - 1, confined_bounds_.bottom() - 1));
 
   location_ = clamped_location;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ui::CursorController::GetInstance()->SetCursorLocation(location_);
 #endif
 }
diff --git a/ui/ozone/platform/drm/ozone_platform_drm.cc b/ui/ozone/platform/drm/ozone_platform_drm.cc
index ee9b289..aceccb8 100644
--- a/ui/ozone/platform/drm/ozone_platform_drm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_drm.cc
@@ -18,6 +18,7 @@
 #include "base/notreached.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "ui/base/buildflags.h"
@@ -58,7 +59,7 @@
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/base/ime/chromeos/input_method_chromeos.h"
 #else
 #include "ui/base/ime/input_method_minimal.h"
@@ -174,7 +175,7 @@
   std::unique_ptr<InputMethod> CreateInputMethod(
       internal::InputMethodDelegate* delegate,
       gfx::AcceleratedWidget) override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     return std::make_unique<InputMethodChromeOS>(delegate);
 #else
     return std::make_unique<InputMethodMinimal>(delegate);
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 46447f33..5af2930 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -202,7 +202,7 @@
     "//ui/platform_window/wm",
   ]
 
-  if (is_linux && !is_chromeos) {
+  if (is_linux || is_chromeos_lacros) {
     deps += [ "//ui/base/ime/linux" ]
   }
 
@@ -217,8 +217,8 @@
     ]
   }
 
-  # TODO(crbug.com/1052397): Rename chromeos_is_browser_only to is_lacros.
-  if (chromeos_is_browser_only) {
+  # TODO(crbug.com/1052397): Rename is_chromeos_lacros to is_chromeos_lacros.
+  if (is_chromeos_lacros) {
     deps += [ "//chromeos/crosapi/cpp" ]
   }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc
index 07e4c286..f171b264 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.cc
+++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -40,7 +40,7 @@
     auto format = buffer_format.first;
 
     // TODO(crbug.com/1127822): Investigate a better fix for this.
-#if !BUILDFLAG(IS_LACROS)
+#if !BUILDFLAG(IS_CHROMEOS_LACROS)
     // RGBA_8888 is the preferred format, except when running on ChromiumOS. See
     // crbug.com/1127558.
     if (format == gfx::BufferFormat::RGBA_8888)
@@ -50,7 +50,7 @@
       // available, but for some reason Chromium gets broken when it's used.
       // Though,  we can import RGBX_8888 dma buffer to EGLImage successfully.
       // Enable that back when the issue is resolved.
-#endif  // !BUILDFLAG(IS_LACROS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_LACROS)
 
     if (!image_format_alpha_ && format == gfx::BufferFormat::BGRA_8888)
       image_format_alpha_ = gfx::BufferFormat::BGRA_8888;
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
index 3aaca26c..7d32d96 100644
--- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -25,7 +25,7 @@
 #include "ui/platform_window/extensions/wayland_extension.h"
 #include "ui/platform_window/wm/wm_drop_handler.h"
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 // TODO(jamescook): The nogncheck is to work around false-positive failures on
 // the code search bot. Remove after https://crrev.com/c/2432137 lands.
 #include "chromeos/crosapi/cpp/crosapi_constants.h"  // nogncheck
@@ -61,7 +61,7 @@
     return false;
   }
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   shell_surface_->SetAppId(window_unique_id_);
 #else
   shell_surface_->SetAppId(wm_class_class_);
@@ -235,7 +235,7 @@
 }
 
 std::string WaylandToplevelWindow::GetWindowUniqueId() const {
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   return window_unique_id_;
 #else
   return std::string();
@@ -377,7 +377,7 @@
 
 bool WaylandToplevelWindow::OnInitialize(
     PlatformWindowInitProperties properties) {
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   auto token = base::UnguessableToken::Create();
   window_unique_id_ =
       std::string(crosapi::kLacrosAppIdPrefix) + token.ToString();
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
index 5de398a..f377c87 100644
--- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -127,7 +127,7 @@
 
   bool is_active_ = false;
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   // Unique ID for this window. May be shared over non-Wayland IPC transports
   // (e.g. mojo) to identify the window.
   std::string window_unique_id_;
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn
index 64295d9..7cf0bfdf 100644
--- a/ui/ozone/platform/x11/BUILD.gn
+++ b/ui/ozone/platform/x11/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/gtk/gtk.gni")
 import("//gpu/vulkan/features.gni")
 import("//ui/base/ui_features.gni")
@@ -37,6 +38,7 @@
   deps = [
     "//base",
     "//build:chromecast_buildflags",
+    "//build:chromeos_buildflags",
     "//gpu/vulkan:buildflags",
     "//skia",
     "//ui/base:base",
@@ -68,7 +70,7 @@
     "//ui/platform_window/x11",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//ui/base/ime/chromeos" ]
   } else {
     sources += [
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index c793d62..7ed5142 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
@@ -44,7 +45,7 @@
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/platform_window/x11/x11_window.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h"
 #include "ui/base/ime/chromeos/input_method_chromeos.h"
 #else
@@ -132,7 +133,7 @@
   std::unique_ptr<InputMethod> CreateInputMethod(
       internal::InputMethodDelegate* delegate,
       gfx::AcceleratedWidget) override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     return std::make_unique<InputMethodChromeOS>(delegate);
 #else
     // This method is used by upper layer components (e.g: GtkUi) to determine
@@ -150,7 +151,7 @@
   }
 
   std::unique_ptr<OSExchangeDataProvider> CreateProvider() override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     return std::make_unique<OSExchangeDataProviderNonBacked>();
 #else
     return std::make_unique<X11OSExchangeDataProviderOzone>();
diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn
index 1e1e9cf..5b47c90 100644
--- a/ui/platform_window/x11/BUILD.gn
+++ b/ui/platform_window/x11/BUILD.gn
@@ -13,6 +13,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//skia",
     "//ui/base",
     "//ui/base/x",
@@ -62,6 +63,7 @@
     ":x11",
     "//base/test:run_all_unittests",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/ui/platform_window/x11/test/events_x_unittest.cc b/ui/platform_window/x11/test/events_x_unittest.cc
index 143f55a..817c3e8 100644
--- a/ui/platform_window/x11/test/events_x_unittest.cc
+++ b/ui/platform_window/x11/test/events_x_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/devices/x11/device_data_manager_x11.h"
 #include "ui/events/devices/x11/touch_factory_x11.h"
@@ -53,7 +54,7 @@
   });
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Initializes the passed-in x11::Event.
 void InitKeyEvent(x11::Event* event,
                   bool is_press,
@@ -458,7 +459,7 @@
   EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(*xev));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(EventsXTest, ImeFabricatedKeyEvents) {
   x11::KeyButMask state_to_be_fabricated[] = {
       {},
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index 022864f2..63a44b1 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/ui_base_features.h"
@@ -944,7 +945,7 @@
 
 gfx::Size X11Window::AdjustSizeForDisplay(
     const gfx::Size& requested_size_in_pixels) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // We do not need to apply the workaround for the ChromeOS.
   return requested_size_in_pixels;
 #else
diff --git a/ui/resources/BUILD.gn b/ui/resources/BUILD.gn
index b976294..1182b83 100644
--- a/ui/resources/BUILD.gn
+++ b/ui/resources/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/repack.gni")
 import("//ui/webui/webui_features.gni")
@@ -40,7 +41,7 @@
   source = "../webui/resources/webui_resources.grd"
 
   deps = [ "//ui/webui/resources:modulize" ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//ui/chromeos/colors:cros_colors_css" ]
   }
 
@@ -153,7 +154,7 @@
     "$root_gen_dir/ui/strings/ui_strings_en-US.pak",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "$root_gen_dir/ui/chromeos/resources/ui_chromeos_resources_100_percent.pak",
       "$root_gen_dir/ui/chromeos/strings/ui_chromeos_strings_en-US.pak",
@@ -176,7 +177,7 @@
     deps += [ ":copy_ui_resources_100_percent" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "//ui/chromeos/resources",
       "//ui/chromeos/strings",
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn
index 24a925dd..a7ef636 100644
--- a/ui/shell_dialogs/BUILD.gn
+++ b/ui/shell_dialogs/BUILD.gn
@@ -57,6 +57,7 @@
   deps = [
     "//base",
     "//base:i18n",
+    "//build:chromeos_buildflags",
     "//skia",
     "//ui/base",
     "//ui/strings",
@@ -101,8 +102,8 @@
     sources += [ "select_file_dialog_fuchsia.cc" ]
   }
 
-  # TODO(crbug.com/1052397): Rename chromeos_is_browser_only.
-  if (chromeos_is_browser_only) {
+  # TODO(crbug.com/1052397): Rename is_chromeos_lacros.
+  if (is_chromeos_lacros) {
     sources += [
       "select_file_dialog_lacros.cc",
       "select_file_dialog_lacros.h",
diff --git a/ui/shell_dialogs/shell_dialog_linux.cc b/ui/shell_dialogs/shell_dialog_linux.cc
index f5999fb..f97dc0ed 100644
--- a/ui/shell_dialogs/shell_dialog_linux.cc
+++ b/ui/shell_dialogs/shell_dialog_linux.cc
@@ -5,6 +5,7 @@
 #include "ui/shell_dialogs/shell_dialog_linux.h"
 
 #include "base/notreached.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 
 namespace {
@@ -26,7 +27,7 @@
 SelectFileDialog* CreateSelectFileDialog(
     SelectFileDialog::Listener* listener,
     std::unique_ptr<SelectFilePolicy> policy) {
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if defined(USE_AURA) && !BUILDFLAG(IS_CHROMEOS_ASH)
   const ui::ShellDialogLinux* shell_dialogs = ui::ShellDialogLinux::instance();
   if (shell_dialogs)
     return shell_dialogs->CreateSelectFileDialog(listener, std::move(policy));
diff --git a/ui/views/views_delegate.cc b/ui/views/views_delegate.cc
index f856122..e9e7458 100644
--- a/ui/views/views_delegate.cc
+++ b/ui/views/views_delegate.cc
@@ -86,7 +86,7 @@
   return false;
 }
 #elif BUILDFLAG(ENABLE_DESKTOP_AURA) && \
-  (defined(OS_LINUX) || defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || defined(OS_CHROMEOS))
 gfx::ImageSkia* ViewsDelegate::GetDefaultWindowIcon() const {
   return nullptr;
 }
diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h
index 177271c..a28f8caf 100644
--- a/ui/views/views_delegate.h
+++ b/ui/views/views_delegate.h
@@ -134,7 +134,7 @@
   // environment.
   virtual bool IsWindowInMetro(gfx::NativeWindow window) const;
 #elif BUILDFLAG(ENABLE_DESKTOP_AURA) && \
-  (defined(OS_LINUX) || defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || defined(OS_CHROMEOS))
   virtual gfx::ImageSkia* GetDefaultWindowIcon() const;
 #endif
 
diff --git a/ui/views_content_client/BUILD.gn b/ui/views_content_client/BUILD.gn
index 57ca84c0..bee5a73 100644
--- a/ui/views_content_client/BUILD.gn
+++ b/ui/views_content_client/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 
 component("views_content_client") {
@@ -18,7 +19,7 @@
     "views_content_main_delegate.h",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "views_content_client_main_parts_chromeos.cc" ]
   }
 
@@ -31,6 +32,7 @@
   deps = [
     "//base",
     "//base:i18n",
+    "//build:chromeos_buildflags",
     "//content",
     "//content/shell:content_shell_lib",
     "//third_party/icu",
@@ -53,7 +55,7 @@
       "views_content_client_main_parts_aura.h",
     ]
 
-    if (!is_chromeos) {
+    if (!is_chromeos_ash) {
       sources += [ "views_content_client_main_parts_desktop_aura.cc" ]
     }
 
@@ -63,7 +65,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "//ui/aura:test_support",
       "//ui/wm:test_support",
diff --git a/ui/views_content_client/views_content_client_main_parts_aura.cc b/ui/views_content_client/views_content_client_main_parts_aura.cc
index bbda2594..2c057cc 100644
--- a/ui/views_content_client/views_content_client_main_parts_aura.cc
+++ b/ui/views_content_client/views_content_client_main_parts_aura.cc
@@ -4,6 +4,7 @@
 
 #include "ui/views_content_client/views_content_client_main_parts_aura.h"
 
+#include "build/chromeos_buildflags.h"
 #include "ui/wm/core/wm_state.h"
 
 namespace ui {
@@ -20,7 +21,7 @@
 void ViewsContentClientMainPartsAura::ToolkitInitialized() {
   ViewsContentClientMainParts::ToolkitInitialized();
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   wm_state_ = std::make_unique<::wm::WMState>();
 #endif
 }
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 98887897..dfba3b68 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 
@@ -39,7 +40,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//third_party/web-animations-js:build_grdp" ]
     grdp_files += [ "$root_gen_dir/third_party/web-animations-js/web_animations_resources.grdp" ]
   }
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn
index 2e8559c6..ee2a9666 100644
--- a/ui/webui/resources/cr_components/BUILD.gn
+++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/preprocess_grit.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
@@ -90,7 +91,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "chromeos/bluetooth/bluetooth_dialog.m.js",
       "chromeos/cellular_setup/activation_code_page.m.js",
@@ -157,7 +158,7 @@
     "managed_footnote/managed_footnote.html",
     "managed_footnote/managed_footnote.js",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     if (!optimize_webui) {
       in_files += [
         "chromeos/bluetooth/bluetooth_dialog.html",
@@ -305,7 +306,7 @@
     "omnibox:closure_compile",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "chromeos:closure_compile" ]
   }
 }
@@ -317,7 +318,7 @@
     "managed_footnote:managed_footnote_module",
     "omnibox:web_components",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     public_deps += [ "chromeos:polymer3_elements" ]
   }
 }
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 708349f..e3c8c8c 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/preprocess_grit.gni")
 import("//tools/polymer/html_to_js.gni")
@@ -134,7 +135,7 @@
     "shared_vars_css.html",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "chromeos/cros_color_overrides.html",
       "chromeos/cr_picture/cr_camera.html",
@@ -216,7 +217,7 @@
     "shared_vars_css.m.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "chromeos/cros_color_overrides.m.js",
       "chromeos/cr_picture/cr_camera.m.js",
@@ -285,7 +286,7 @@
     "policy:closure_compile_module",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "chromeos:closure_compile",
 
@@ -426,7 +427,7 @@
     "policy:polymer3_elements",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     public_deps += [
       "chromeos:polymer3_elements",
 
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn b/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
index fb06449..0fed7f9 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/polymer.gni")
 import("//ui/webui/resources/tools/js_modulizer.gni")
@@ -74,7 +75,7 @@
 # platforms.
 js_library("cr_picture_types.m") {
   sources = []
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.m.js" ]
   }
   extra_deps = [ ":modulize" ]
@@ -95,7 +96,7 @@
 # platforms.
 js_library("cr_picture_pane.m") {
   sources = []
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.m.js" ]
   }
   deps = [
@@ -111,7 +112,7 @@
 # platforms.
 js_library("cr_camera.m") {
   sources = []
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.m.js" ]
   }
   deps = [ ":png.m" ]
@@ -123,7 +124,7 @@
 # platforms.
 js_library("cr_picture_list.m") {
   sources = []
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.m.js" ]
   }
   deps = [
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn
index 597d8f7..43a84f0 100644
--- a/ui/webui/resources/js/BUILD.gn
+++ b/ui/webui/resources/js/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/preprocess_grit.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
@@ -56,7 +57,7 @@
     "webui_resource_test.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [ "i18n_template_process.js" ]
   }
 
@@ -124,7 +125,7 @@
     ":web_ui_listener_behavior",
     ":webui_resource_test",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ ":i18n_template_process" ]
   }
   if (is_ios) {
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn
index 0e10c8d..f0d46fdf 100644
--- a/ui/webui/resources/js/cr/ui/BUILD.gn
+++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/preprocess_grit.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
@@ -74,7 +75,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [ "grid.js" ]
   }
 }
@@ -103,7 +104,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "array_data_model.m.js",
       "command.m.js",
@@ -162,7 +163,7 @@
     ":tree",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ ":grid" ]
   }
 }
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index bec18064..f92f962 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
@@ -65,6 +66,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//skia",
     "//ui/aura",
     "//ui/base",
@@ -85,7 +87,7 @@
     "//ui/wm/public",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "core/ime_util_chromeos.cc",
       "core/ime_util_chromeos.h",
@@ -140,6 +142,7 @@
     ":wm",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//mojo/core/embedder",
     "//skia",
     "//testing/gtest",
@@ -163,7 +166,7 @@
 
   data_deps = [ "//ui/resources:ui_test_pak_data" ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "core/ime_util_chromeos_unittest.cc" ]
   }
 }
diff --git a/ui/wm/core/compound_event_filter.cc b/ui/wm/core/compound_event_filter.cc
index 12bba29..16643954 100644
--- a/ui/wm/core/compound_event_filter.cc
+++ b/ui/wm/core/compound_event_filter.cc
@@ -7,6 +7,7 @@
 #include "base/check.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/env.h"
@@ -25,7 +26,7 @@
 // Returns true if the cursor should be hidden on touch events.
 // TODO(tdanderson|rsadam): Move this function into CursorClient.
 bool ShouldHideCursorOnTouch(const ui::TouchEvent& event) {
-#if defined(OS_WIN) || defined(OS_CHROMEOS)
+#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH)
   return true;
 #else
   // Linux Aura does not hide the cursor on touch by default.
diff --git a/ui/wm/core/compound_event_filter_unittest.cc b/ui/wm/core/compound_event_filter_unittest.cc
index 51fcf0e..75a2d07 100644
--- a/ui/wm/core/compound_event_filter_unittest.cc
+++ b/ui/wm/core/compound_event_filter_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/aura_test_base.h"
@@ -21,12 +22,11 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
 base::TimeTicks GetTime() {
   return ui::EventTimeForNow();
 }
-#endif  // defined(OS_CHROMEOS) || defined(OS_WIN)
-
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
 }
 
 namespace wm {
@@ -50,7 +50,7 @@
 
 typedef aura::test::AuraTestBase CompoundEventFilterTest;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // A keypress only hides the cursor on ChromeOS (crbug.com/304296).
 TEST_F(CompoundEventFilterTest, CursorVisibilityChange) {
   std::unique_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
@@ -108,9 +108,9 @@
 
   aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
 // Touch visually hides the cursor on ChromeOS and Windows.
 TEST_F(CompoundEventFilterTest, TouchHidesCursor) {
   std::unique_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
@@ -165,7 +165,7 @@
   EXPECT_FALSE(cursor_client.IsCursorVisible());
   aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
 }
-#endif  // defined(OS_CHROMEOS) || defined(OS_WIN)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
 
 // Tests that if an event filter consumes a gesture, then it doesn't focus the
 // window.
diff --git a/weblayer/app/content_main_delegate_impl.cc b/weblayer/app/content_main_delegate_impl.cc
index 11bfb119..6bbc7b6 100644
--- a/weblayer/app/content_main_delegate_impl.cc
+++ b/weblayer/app/content_main_delegate_impl.cc
@@ -220,8 +220,7 @@
 }
 
 void ContentMainDelegateImpl::PreSandboxStartup() {
-#if defined(ARCH_CPU_ARM_FAMILY) && \
-    (defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS))
+#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
   // Create an instance of the CPU class to parse /proc/cpuinfo and cache
   // cpu_brand info.
   base::CPU cpu_info;
diff --git a/weblayer/browser/browser_main_parts_impl.cc b/weblayer/browser/browser_main_parts_impl.cc
index c65e868..1a4376c0 100644
--- a/weblayer/browser/browser_main_parts_impl.cc
+++ b/weblayer/browser/browser_main_parts_impl.cc
@@ -65,7 +65,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
-#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX)
+#if defined(USE_AURA) && defined(OS_LINUX)
 #include "ui/base/ime/init/input_method_initializer.h"
 #endif
 
@@ -176,7 +176,7 @@
 int BrowserMainPartsImpl::PreEarlyInitialization() {
   browser_process_ = std::make_unique<BrowserProcess>(std::move(local_state_));
 
-#if defined(USE_AURA) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
+#if defined(USE_AURA) && defined(OS_LINUX)
   ui::InitializeInputMethodForTesting();
 #endif
 #if defined(OS_ANDROID)
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc
index 88b6164..0b20b2c 100644
--- a/weblayer/browser/content_browser_client_impl.cc
+++ b/weblayer/browser/content_browser_client_impl.cc
@@ -136,7 +136,7 @@
 #include "weblayer/browser/weblayer_factory_impl_android.h"
 #endif
 
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
 #include "content/public/common/content_descriptors.h"
 #endif
 
@@ -383,7 +383,7 @@
 
 void ContentBrowserClientImpl::OnNetworkServiceCreated(
     network::mojom::NetworkService* network_service) {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if defined(OS_LINUX)
   network::mojom::CryptConfigPtr config = network::mojom::CryptConfig::New();
   content::GetNetworkService()->SetCryptConfig(std::move(config));
 #endif
@@ -830,7 +830,7 @@
 }
 #endif
 
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
 void ContentBrowserClientImpl::GetAdditionalMappedFilesForChildProcess(
     const base::CommandLine& command_line,
     int child_process_id,
@@ -864,7 +864,7 @@
     mappings->Share(kCrashDumpSignal, crash_signal_fd);
 #endif  // defined(OS_ANDROID)
 }
-#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#endif  // defined(OS_LINUX)|| defined(OS_ANDROID)
 
 void ContentBrowserClientImpl::AppendExtraCommandLineSwitches(
     base::CommandLine* command_line,
diff --git a/weblayer/browser/content_browser_client_impl.h b/weblayer/browser/content_browser_client_impl.h
index fa350fa..f7518dc 100644
--- a/weblayer/browser/content_browser_client_impl.h
+++ b/weblayer/browser/content_browser_client_impl.h
@@ -116,12 +116,12 @@
   void RenderProcessWillLaunch(content::RenderProcessHost* host) override;
   scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext()
       override;
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
   void GetAdditionalMappedFilesForChildProcess(
       const base::CommandLine& command_line,
       int child_process_id,
       content::PosixFileDescriptorInfo* mappings) override;
-#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) override;
 #if defined(OS_ANDROID)
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestFactory.java b/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestFactory.java
index 3221b6e..d4aa67a 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestFactory.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestFactory.java
@@ -113,8 +113,7 @@
         WebContents webContents = WebContentsStatics.fromRenderFrameHost(mRenderFrameHost);
         if (webContents == null || webContents.isDestroyed()) return new InvalidPaymentRequest();
 
-        return PaymentRequestService.createPaymentRequest(mRenderFrameHost,
-                /*isOffTheRecord=*/delegate.isOffTheRecord(), delegate,
+        return PaymentRequestService.createPaymentRequest(mRenderFrameHost, delegate,
                 (paymentRequestService)
                         -> new WebLayerPaymentRequestService(paymentRequestService, delegate));
     }
diff --git a/weblayer/browser/permissions/permission_manager_factory.cc b/weblayer/browser/permissions/permission_manager_factory.cc
index f743eb29..b2467eb 100644
--- a/weblayer/browser/permissions/permission_manager_factory.cc
+++ b/weblayer/browser/permissions/permission_manager_factory.cc
@@ -71,7 +71,7 @@
       std::make_unique<payments::PaymentHandlerPermissionContext>(
           browser_context);
 
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
   permission_contexts[ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER] =
       std::make_unique<SafePermissionContext>(
           browser_context, ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
@@ -92,7 +92,7 @@
   // For now, all requests are denied. As features are added, their permission
   // contexts can be added here instead of DeniedPermissionContext.
   for (content::PermissionType type : content::GetAllPermissionTypes()) {
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !defined(OS_ANDROID)
     // PROTECTED_MEDIA_IDENTIFIER is only supported on Android/ChromeOS.
     if (type == content::PermissionType::PROTECTED_MEDIA_IDENTIFIER)
       continue;
diff --git a/weblayer/browser/system_network_context_manager.cc b/weblayer/browser/system_network_context_manager.cc
index 75605b8e..90cb4b7 100644
--- a/weblayer/browser/system_network_context_manager.cc
+++ b/weblayer/browser/system_network_context_manager.cc
@@ -64,10 +64,10 @@
     network::mojom::NetworkContextParams* network_context_params,
     const std::string& user_agent) {
   network_context_params->user_agent = user_agent;
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_WIN)
   // We're not configuring the cookie encryption on these platforms yet.
   network_context_params->enable_encrypted_cookies = false;
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
+#endif  // defined(OS_LINUX) || defined(OS_WIN)
 }
 
 SystemNetworkContextManager::SystemNetworkContextManager(
diff --git a/weblayer/common/weblayer_paths.cc b/weblayer/common/weblayer_paths.cc
index 018a3891..327a7fd 100644
--- a/weblayer/common/weblayer_paths.cc
+++ b/weblayer/common/weblayer_paths.cc
@@ -17,7 +17,7 @@
 
 #if defined(OS_WIN)
 #include "base/base_paths_win.h"
-#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
+#elif defined(OS_LINUX)
 #include "base/nix/xdg_util.h"
 #endif
 
@@ -35,7 +35,7 @@
     return false;
   *result = result->AppendASCII("weblayer");
   return true;
-#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
+#elif defined(OS_LINUX)
   std::unique_ptr<base::Environment> env(base::Environment::Create());
   base::FilePath config_dir(base::nix::GetXDGDirectory(
       env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir));
diff --git a/weblayer/shell/browser/shell_views.cc b/weblayer/shell/browser/shell_views.cc
index d40ed88..41d08b1 100644
--- a/weblayer/shell/browser/shell_views.cc
+++ b/weblayer/shell/browser/shell_views.cc
@@ -310,7 +310,7 @@
   views_delegate_ = nullptr;
   // delete platform_;
   // platform_ = nullptr;
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if defined(USE_AURA)
   delete wm_state_;
   wm_state_ = nullptr;
 #endif