Automated commit: libchrome r1297392 uprev

Merge with upstream commit db41af4bab810cbaa4e6ab2a64aaaa9ccf2ac16b

BUG=None
TEST=sudo emerge libchrome

Cq-Depend: chromium:5528177
Change-Id: Ieae5a8e1ce89d8a1e2b3c060e5ebd1bafc8d08c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/5521313
Commit-Queue: Grace Cham <hscham@chromium.org>
Reviewed-by: Grace Cham <hscham@chromium.org>
Tested-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Jae Hoon Kim <kimjae@chromium.org>
diff --git a/BASE_VER b/BASE_VER
index 7ca3f11..d24b0d3 100644
--- a/BASE_VER
+++ b/BASE_VER
@@ -1 +1 @@
-1296734
+1297392
diff --git a/base/android/java/src/org/chromium/base/cached_flags/CachedFlagUtils.java b/base/android/java/src/org/chromium/base/cached_flags/CachedFlagUtils.java
index 7ee79a5..453dbd4 100644
--- a/base/android/java/src/org/chromium/base/cached_flags/CachedFlagUtils.java
+++ b/base/android/java/src/org/chromium/base/cached_flags/CachedFlagUtils.java
@@ -15,25 +15,30 @@
  */
 public class CachedFlagUtils {
     /** Caches flags that must take effect on startup but are set via native code. */
-    public static void cacheNativeFlags(List<CachedFlag> featuresToCache) {
+    public static void cacheNativeFlags(List<CachedFlag>... listsOfFeaturesToCache) {
         // Batch the updates into a single apply() call to avoid calling the expensive
         // SharedPreferencesImpl$EditorImpl.commitToMemory() method many times unnecessarily.
         final SharedPreferences.Editor editor =
                 CachedFlagsSharedPreferences.getInstance().getEditor();
-        for (CachedFlag feature : featuresToCache) {
-            feature.writeCacheValueToEditor(editor);
+        for (final List<CachedFlag> featuresToCache : listsOfFeaturesToCache) {
+            for (CachedFlag feature : featuresToCache) {
+                feature.writeCacheValueToEditor(editor);
+            }
         }
         editor.apply();
     }
 
     /** Caches flags that must take effect on startup but are set via native code. */
-    public static void cacheFieldTrialParameters(List<CachedFieldTrialParameter> parameters) {
+    public static void cacheFieldTrialParameters(
+            List<CachedFieldTrialParameter>... listsOfParameters) {
         // Batch the updates into a single apply() call to avoid calling the expensive
         // SharedPreferencesImpl$EditorImpl.commitToMemory() method many times unnecessarily.
         final SharedPreferences.Editor editor =
                 CachedFlagsSharedPreferences.getInstance().getEditor();
-        for (final CachedFieldTrialParameter parameter : parameters) {
-            parameter.writeCacheValueToEditor(editor);
+        for (final List<CachedFieldTrialParameter> parameters : listsOfParameters) {
+            for (final CachedFieldTrialParameter parameter : parameters) {
+                parameter.writeCacheValueToEditor(editor);
+            }
         }
         editor.apply();
     }
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 42617c8..f5d96a5 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -2,11 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "base/memory/discardable_shared_memory.h"
 
 #include <stdint.h>
@@ -145,15 +140,11 @@
 
 }  // namespace
 
-DiscardableSharedMemory::DiscardableSharedMemory()
-    : mapped_size_(0), locked_page_count_(0) {
-}
+DiscardableSharedMemory::DiscardableSharedMemory() = default;
 
 DiscardableSharedMemory::DiscardableSharedMemory(
     UnsafeSharedMemoryRegion shared_memory_region)
-    : shared_memory_region_(std::move(shared_memory_region)),
-      mapped_size_(0),
-      locked_page_count_(0) {}
+    : shared_memory_region_(std::move(shared_memory_region)) {}
 
 DiscardableSharedMemory::~DiscardableSharedMemory() = default;
 
@@ -173,10 +164,8 @@
   if (!shared_memory_mapping_.IsValid())
     return false;
 
-  mapped_size_ = shared_memory_mapping_.mapped_size() -
-                 AlignToPageSize(sizeof(SharedState));
-
-  locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
+  locked_page_count_ =
+      AlignToPageSize(mapped_memory().size()) / base::GetPageSize();
 #if DCHECK_IS_ON()
   for (size_t page = 0; page < locked_page_count_; ++page)
     locked_pages_.insert(page);
@@ -200,10 +189,8 @@
   if (!shared_memory_mapping_.IsValid())
     return false;
 
-  mapped_size_ = shared_memory_mapping_.mapped_size() -
-                 AlignToPageSize(sizeof(SharedState));
-
-  locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
+  locked_page_count_ =
+      AlignToPageSize(mapped_memory().size()) / base::GetPageSize();
 #if DCHECK_IS_ON()
   for (size_t page = 0; page < locked_page_count_; ++page)
     locked_pages_.insert(page);
@@ -221,7 +208,6 @@
 #if DCHECK_IS_ON()
   locked_pages_.clear();
 #endif
-  mapped_size_ = 0;
   return true;
 }
 
@@ -258,12 +244,12 @@
 
   // Zero for length means "everything onward".
   if (!length)
-    length = AlignToPageSize(mapped_size_) - offset;
+    length = AlignToPageSize(mapped_memory().size()) - offset;
 
   size_t start = offset / base::GetPageSize();
   size_t end = start + length / base::GetPageSize();
   DCHECK_LE(start, end);
-  DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize());
+  DCHECK_LE(end, AlignToPageSize(mapped_memory().size()) / base::GetPageSize());
 
   // Add pages to |locked_page_count_|.
   // Note: Locking a page that is already locked is an error.
@@ -299,9 +285,8 @@
   //
   // For more information, see
   // https://bugs.chromium.org/p/chromium/issues/detail?id=823915.
-  madvise(static_cast<char*>(shared_memory_mapping_.memory()) +
-              AlignToPageSize(sizeof(SharedState)),
-          AlignToPageSize(mapped_size_), MADV_FREE_REUSE);
+  base::span<uint8_t> mapped = mapped_memory();
+  madvise(mapped.data(), AlignToPageSize(mapped.size()), MADV_FREE_REUSE);
   return DiscardableSharedMemory::SUCCESS;
 #else
   return DiscardableSharedMemory::SUCCESS;
@@ -316,9 +301,9 @@
   DFAKE_SCOPED_LOCK(thread_collision_warner_);
 
   // Passing zero for |length| means "everything onward". Note that |length| may
-  // still be zero after this calculation, e.g. if |mapped_size_| is zero.
+  // still be zero after this calculation, e.g. if the mapped size is zero.
   if (!length)
-    length = AlignToPageSize(mapped_size_) - offset;
+    length = AlignToPageSize(mapped_memory().size()) - offset;
 
   DCHECK(shared_memory_mapping_.IsValid());
 
@@ -329,7 +314,7 @@
   size_t start = offset / base::GetPageSize();
   size_t end = start + length / base::GetPageSize();
   DCHECK_LE(start, end);
-  DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize());
+  DCHECK_LE(end, AlignToPageSize(mapped_memory().size()) / base::GetPageSize());
 
   // Remove pages from |locked_page_count_|.
   // Note: Unlocking a page that is not locked is an error.
@@ -369,9 +354,14 @@
   last_known_usage_ = current_time;
 }
 
-void* DiscardableSharedMemory::memory() const {
-  return static_cast<uint8_t*>(shared_memory_mapping_.memory()) +
-         AlignToPageSize(sizeof(SharedState));
+span<uint8_t> DiscardableSharedMemory::memory() const {
+  return shared_memory_mapping_.GetMemoryAsSpan<uint8_t>().subspan(
+      AlignToPageSize(sizeof(SharedState)));
+}
+
+span<uint8_t> DiscardableSharedMemory::mapped_memory() const {
+  return shared_memory_mapping_.mapped_memory().subspan(
+      AlignToPageSize(sizeof(SharedState)));
 }
 
 bool DiscardableSharedMemory::Purge(Time current_time) {
@@ -420,17 +410,16 @@
   // Advise the kernel to remove resources associated with purged pages.
   // Subsequent accesses of memory pages will succeed, but might result in
   // zero-fill-on-demand pages.
-  if (madvise(static_cast<char*>(shared_memory_mapping_.memory()) +
-                  AlignToPageSize(sizeof(SharedState)),
-              AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) {
+  base::span<uint8_t> map = mapped_memory();
+  if (madvise(map.data(), AlignToPageSize(map.size()), MADV_PURGE_ARGUMENT)) {
     DPLOG(ERROR) << "madvise() failed";
   }
 #elif BUILDFLAG(IS_WIN)
   // On Windows, discarded pages are not returned to the system immediately and
   // not guaranteed to be zeroed when returned to the application.
-  char* address = static_cast<char*>(shared_memory_mapping_.memory()) +
-                  AlignToPageSize(sizeof(SharedState));
-  size_t length = AlignToPageSize(mapped_size_);
+  base::span<uint8_t> mapped = mapped_memory();
+  uint8_t* address = mapped.data();
+  size_t length = AlignToPageSize(mapped.size());
 
   DWORD ret = DiscardVirtualMemory(address, length);
   // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
@@ -442,11 +431,10 @@
 #elif BUILDFLAG(IS_FUCHSIA)
   // De-commit via our VMAR, rather than relying on the VMO handle, since the
   // handle may have been closed after the memory was mapped into this process.
-  uint64_t address_int = reinterpret_cast<uint64_t>(
-      static_cast<char*>(shared_memory_mapping_.memory()) +
-      AlignToPageSize(sizeof(SharedState)));
+  base::span<uint8_t> mapped = mapped_memory();
+  uint64_t address_int = reinterpret_cast<uint64_t>(mapped.data());
   zx_status_t status = zx::vmar::root_self()->op_range(
-      ZX_VMO_OP_DECOMMIT, address_int, AlignToPageSize(mapped_size_), nullptr,
+      ZX_VMO_OP_DECOMMIT, address_int, AlignToPageSize(mapped.size()), nullptr,
       0);
   ZX_DCHECK(status == ZX_OK, status) << "zx_vmo_op_range(ZX_VMO_OP_DECOMMIT)";
 #endif  // BUILDFLAG(IS_FUCHSIA)
@@ -455,36 +443,6 @@
   return true;
 }
 
-void DiscardableSharedMemory::ReleaseMemoryIfPossible(size_t offset,
-                                                      size_t length) {
-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
-// Linux and Android provide MADV_REMOVE which is preferred as it has a
-// behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs),
-// provide MADV_FREE which has the same result but memory is purged lazily.
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
-#define MADV_PURGE_ARGUMENT MADV_REMOVE
-#elif BUILDFLAG(IS_APPLE)
-// MADV_FREE_REUSABLE is similar to MADV_FREE, but also marks the pages with the
-// reusable bit, which allows both Activity Monitor and memory-infra to
-// correctly track the pages.
-#define MADV_PURGE_ARGUMENT MADV_FREE_REUSABLE
-#else  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
-#define MADV_PURGE_ARGUMENT MADV_FREE
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
-        // BUILDFLAG(IS_ANDROID)
-  // Advise the kernel to remove resources associated with purged pages.
-  // Subsequent accesses of memory pages will succeed, but might result in
-  // zero-fill-on-demand pages.
-  if (madvise(static_cast<char*>(shared_memory_mapping_.memory()) + offset,
-              length, MADV_PURGE_ARGUMENT)) {
-    DPLOG(ERROR) << "madvise() failed";
-  }
-#else   // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
-  partition_alloc::DiscardSystemPages(
-      static_cast<char*>(shared_memory_mapping_.memory()) + offset, length);
-#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
-}
-
 bool DiscardableSharedMemory::IsMemoryResident() const {
   DCHECK(shared_memory_mapping_.IsValid());
 
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
index 73ae10b..8006deb 100644
--- a/base/memory/discardable_shared_memory.h
+++ b/base/memory/discardable_shared_memory.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "base/base_export.h"
+#include "base/containers/span.h"
 #include "base/dcheck_is_on.h"
 #include "base/memory/shared_memory_mapping.h"
 #include "base/memory/unsafe_shared_memory_region.h"
@@ -71,8 +72,15 @@
   // not mapped.
   bool Unmap();
 
-  // The actual size of the mapped memory (may be larger than requested).
-  size_t mapped_size() const { return mapped_size_; }
+  // The actual size of the mapped memory (may be larger than requested). It is
+  // 0 when the memory has not been mapped via `Map()`.
+  size_t mapped_size() const {
+    if (shared_memory_mapping_.IsValid()) {
+      return mapped_memory().size();
+    } else {
+      return 0u;
+    }
+  }
 
   // Returns a duplicated shared memory region for this DiscardableSharedMemory
   // object.
@@ -109,22 +117,20 @@
   // Passing 0 for |length| means "everything onward".
   void Unlock(size_t offset, size_t length);
 
-  // Gets a pointer to the opened discardable memory space. Discardable memory
+  // Gets a span over the opened discardable memory space. Discardable memory
   // must have been mapped via Map().
-  void* memory() const;
+  //
+  // This gives the logical memory region, matching the size of what was
+  // requested. The actual mapped memory may be larger due to system alignment
+  // requirements. See `SharedMemoryMapping::size()` vs
+  // `SharedMemoryMapping::mapped_size()`.
+  span<uint8_t> memory() const;
 
   // Returns the last known usage time for DiscardableSharedMemory object. This
   // may be earlier than the "true" usage time when memory has been used by a
   // different process. Returns NULL time if purged.
   Time last_known_usage() const { return last_known_usage_; }
 
-  // Releases any allocated pages in the specified range, if supported by the
-  // platform. Address space in the specified range continues to be reserved.
-  // The memory is not guaranteed to be released immediately.
-  // |offset| and |length| are both in bytes. |offset| and |length| must both be
-  // page aligned.
-  void ReleaseMemoryIfPossible(size_t offset, size_t length);
-
   // This returns true and sets |last_known_usage_| to 0 if
   // DiscardableSharedMemory object was successfully purged. Purging can fail
   // for two reasons; object might be locked or our last known usage timestamp
@@ -166,6 +172,12 @@
 #endif
 
  private:
+  // Returns the full mapped memory region after the internal bookkeeping
+  // header. This may be larger than the region exposed through `memory()` due
+  // to platform alignment requirements. Discardable memory must have been
+  // mapped via Map().
+  span<uint8_t> mapped_memory() const;
+
   // LockPages/UnlockPages are platform-native discardable page management
   // helper functions. Both expect |offset| to be specified relative to the
   // base address at which |memory| is mapped, and that |offset| and |length|
@@ -184,8 +196,7 @@
 
   UnsafeSharedMemoryRegion shared_memory_region_;
   WritableSharedMemoryMapping shared_memory_mapping_;
-  size_t mapped_size_;
-  size_t locked_page_count_;
+  size_t locked_page_count_ = 0u;
 #if DCHECK_IS_ON()
   std::set<size_t> locked_pages_;
 #endif
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
index 9c7d495..0853cf8 100644
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/memory/discardable_shared_memory.h"
+
 #include <fcntl.h>
 #include <stdint.h>
 
+#include <algorithm>
+
 #include "base/files/scoped_file.h"
-#include "base/memory/discardable_shared_memory.h"
 #include "base/memory/page_size.h"
 #include "base/memory/shared_memory_tracker.h"
 #include "base/tracing_buildflags.h"
@@ -434,7 +437,7 @@
   ASSERT_TRUE(rv);
 
   // Initialize all memory to '0xaa'.
-  memset(memory2.memory(), 0xaa, kDataSize);
+  std::ranges::fill(memory2.memory(), 0xaa);
 
   // Unlock memory.
   memory2.SetNow(Time::FromSecondsSinceUnixEpoch(1));
@@ -450,7 +453,7 @@
   // Check that reading memory after it has been purged is returning
   // zero-filled pages.
   uint8_t expected_data[kDataSize] = {};
-  EXPECT_EQ(memcmp(memory2.memory(), expected_data, kDataSize), 0);
+  EXPECT_EQ(base::span(expected_data), memory2.memory());
 }
 #endif
 
diff --git a/base/memory/shared_memory_mapping.h b/base/memory/shared_memory_mapping.h
index d546deb..42d53a1 100644
--- a/base/memory/shared_memory_mapping.h
+++ b/base/memory/shared_memory_mapping.h
@@ -242,6 +242,18 @@
                               size_t size,
                               const UnguessableToken& guid,
                               SharedMemoryMapper* mapper);
+
+  friend class DiscardableSharedMemory;
+  // Returns a span over the entire mapped memory, which may be more than the
+  // logical requested memory. Bytes outside of the logical size should not be
+  // used.
+  span<uint8_t> mapped_memory() const {
+    if (!IsValid()) {
+      return span<uint8_t>();
+    }
+    return UNSAFE_BUFFERS(
+        span(static_cast<uint8_t*>(raw_memory_ptr()), mapped_size()));
+  }
 };
 
 }  // namespace base
diff --git a/base/os_compat_android.cc b/base/os_compat_android.cc
index d0f920b..8bdd84a 100644
--- a/base/os_compat_android.cc
+++ b/base/os_compat_android.cc
@@ -35,7 +35,8 @@
   ts[0].tv_nsec = tv[0].tv_usec * 1000;
   ts[1].tv_sec = tv[1].tv_sec;
   ts[1].tv_nsec = tv[1].tv_usec * 1000;
-  return base::checked_cast<int>(syscall(__NR_utimensat, fd, NULL, ts, 0));
+  return base::checked_cast<int>(
+      syscall(__NR_utimensat, fd, NULL, ts.data(), 0));
 }
 #endif
 
diff --git a/base/task/sequence_manager/thread_controller.cc b/base/task/sequence_manager/thread_controller.cc
index 5bf8ce7..dd2cc55 100644
--- a/base/task/sequence_manager/thread_controller.cc
+++ b/base/task/sequence_manager/thread_controller.cc
@@ -331,8 +331,8 @@
 void ThreadController::RunLevelTracker::RunLevel::LogPercentageMetric(
     const char* name,
     int percentage) {
-  UmaHistogramPercentage(
-      base::StrCat({name, base::StrCat({".", GetThreadName()})}), percentage);
+  UmaHistogramPercentage(base::StrCat({name, ".", GetThreadName()}),
+                         percentage);
 }
 
 void ThreadController::RunLevelTracker::RunLevel::LogPercentageMetric(
diff --git a/base/task/sequence_manager/thread_controller.h b/base/task/sequence_manager/thread_controller.h
index 6ee818e..47bb7b9 100644
--- a/base/task/sequence_manager/thread_controller.h
+++ b/base/task/sequence_manager/thread_controller.h
@@ -279,7 +279,7 @@
 
     void EnableTimeKeeperMetrics(
         const char* thread_name,
-        bool wall_time_based_metrics_for_testing_enabled);
+        bool wall_time_based_metrics_enabled_for_testing);
 
     // Observes changes of state sent as trace-events so they can be tested.
     class TraceObserverForTesting {
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java
new file mode 100644
index 0000000..f21f33e
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java
@@ -0,0 +1,113 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.test.transit;
+
+import android.app.Activity;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.supplier.Supplier;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Represents an {@link Activity} that needs to exist to consider the Station active.
+ *
+ * <p>Subclasses are treated as a different type.
+ *
+ * @param <ActivityT> exact type of Activity expected
+ */
+public class ActivityElement<ActivityT extends Activity>
+        implements ElementInState, Supplier<ActivityT> {
+    private final Class<ActivityT> mActivityClass;
+    private final String mId;
+    private final ActivityExistsCondition mEnterCondition;
+
+    ActivityElement(Class<ActivityT> activityClass) {
+        mActivityClass = activityClass;
+        mId = "AE/" + activityClass.getCanonicalName();
+        mEnterCondition = new ActivityExistsCondition();
+    }
+
+    @Override
+    public String getId() {
+        return mId;
+    }
+
+    @Override
+    public Condition getEnterCondition() {
+        return mEnterCondition;
+    }
+
+    @Override
+    public @Nullable Condition getExitCondition(Set<String> destinationElementIds) {
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return mId;
+    }
+
+    @Override
+    public ActivityT get() {
+        return mEnterCondition.mMatchedActivity;
+    }
+
+    @Override
+    public boolean hasValue() {
+        return mEnterCondition.mMatchedActivity != null;
+    }
+
+    private class ActivityExistsCondition extends InstrumentationThreadCondition {
+        private ActivityT mMatchedActivity;
+
+        @Override
+        public ConditionStatus check() {
+            ActivityT candidate = null;
+            List<Activity> allActivities = ApplicationStatus.getRunningActivities();
+            for (Activity activity : allActivities) {
+                if (mActivityClass.equals(activity.getClass())) {
+                    ActivityT matched = mActivityClass.cast(activity);
+                    if (candidate != null) {
+                        return error("%s matched two Activities: %s, %s", this, candidate, matched);
+                    }
+                    candidate = matched;
+                }
+            }
+            mMatchedActivity = candidate;
+            if (mMatchedActivity == null) {
+                return notFulfilled("No Activity with expected class");
+            }
+
+            @ActivityState int state = ApplicationStatus.getStateForActivity(mMatchedActivity);
+            return whether(
+                    state == ActivityState.RESUMED,
+                    "matched: %s (state=%s)",
+                    mMatchedActivity,
+                    activityStateDescription(state));
+        }
+
+        @Override
+        public String buildDescription() {
+            return "Activity exists and is RESUMED: " + mActivityClass.getSimpleName();
+        }
+    }
+
+    private static String activityStateDescription(@ActivityState int state) {
+        return switch (state) {
+            case ActivityState.CREATED -> "CREATED";
+            case ActivityState.STARTED -> "STARTED";
+            case ActivityState.RESUMED -> "RESUMED";
+            case ActivityState.PAUSED -> "PAUSED";
+            case ActivityState.STOPPED -> "STOPPED";
+            case ActivityState.DESTROYED -> "DESTROYED";
+            default -> throw new IllegalStateException("Unexpected value: " + state);
+        };
+    }
+}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
index d5436ce..1a590a4 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
@@ -4,6 +4,7 @@
 
 package org.chromium.base.test.transit;
 
+import android.app.Activity;
 import android.view.View;
 
 import org.hamcrest.Matcher;
@@ -64,6 +65,13 @@
             mElements = elements;
         }
 
+        /** Declare as an element an Android Activity of type |activityClass|. */
+        public <T extends Activity> ActivityElement<T> declareActivity(Class<T> activityClass) {
+            ActivityElement<T> element = new ActivityElement<>(activityClass);
+            mElements.mElementsInState.add(element);
+            return element;
+        }
+
         /** Declare as an element a View that matches |viewMatcher|. */
         public ViewElementInState declareView(ViewElement viewElement) {
             ViewElementInState inState = new ViewElementInState(viewElement, /* gate= */ null);
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/LogicalElement.java b/base/test/android/javatests/src/org/chromium/base/test/transit/LogicalElement.java
index b71b48d..652cb07 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/LogicalElement.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/LogicalElement.java
@@ -14,7 +14,7 @@
  *
  * <p>LogicalElements should be declared by calling {@link
  * Elements.Builder#declareLogicalElement(LogicalElement)} passing in an instance created by one of
- * the factory methods here such as {@link #sharedUiThreadLogicalElement(String, Callable)}.
+ * the factory methods here such as {@link #uiThreadLogicalElement(String, Callable)}.
  *
  * <p>Generates ENTER and EXIT Conditions for the ConditionalState to ensure the LogicalElement is
  * in the right state.
@@ -29,9 +29,27 @@
     @Nullable private Condition mExitCondition;
 
     /**
+     * Alias for {@link #unscopedUiThreadLogicalElement(String, Callable)} as the default way to
+     * declare LogicalElements.
+     */
+    public static LogicalElement uiThreadLogicalElement(
+            String description, Callable<Boolean> checkFunction) {
+        return unscopedUiThreadLogicalElement(description, checkFunction);
+    }
+
+    /**
+     * Alias for {@link #unscopedInstrumentationThreadLogicalElement(String, Callable)} as the
+     * default way to declare LogicalElements.
+     */
+    public static LogicalElement instrumentationThreadLogicalElement(
+            String description, Callable<Boolean> checkFunction) {
+        return unscopedInstrumentationThreadLogicalElement(description, checkFunction);
+    }
+
+    /**
      * Create a shared-scope LogicalElement that runs the check on the UI Thread.
      *
-     * <p>Unscoped LogicalElements wait for the function to be true as an ENTER Condition. It also
+     * <p>Shared LogicalElements wait for the function to be true as an ENTER Condition. It also
      * waits for the function to be false as an EXIT Condition when transitioning to a
      * ConditionalState that does not declare the LogicalElement too.
      */
diff --git a/base/trace_event/memory_infra_background_allowlist.cc b/base/trace_event/memory_infra_background_allowlist.cc
index 84088f2..524bc70 100644
--- a/base/trace_event/memory_infra_background_allowlist.cc
+++ b/base/trace_event/memory_infra_background_allowlist.cc
@@ -268,6 +268,8 @@
         "v8/main/heap/read_only_space",
         "v8/main/heap/shared_large_object_space",
         "v8/main/heap/shared_space",
+        "v8/main/heap/shared_trusted_large_object_space",
+        "v8/main/heap/shared_trusted_space",
         "v8/main/heap/trusted_space",
         "v8/main/heap/trusted_large_object_space",
         "v8/main/malloc",
@@ -286,6 +288,8 @@
         "v8/utility/heap/read_only_space",
         "v8/utility/heap/shared_large_object_space",
         "v8/utility/heap/shared_space",
+        "v8/utility/heap/shared_trusted_large_object_space",
+        "v8/utility/heap/shared_trusted_space",
         "v8/utility/heap/trusted_space",
         "v8/utility/heap/trusted_large_object_space",
         "v8/utility/malloc",
@@ -304,6 +308,8 @@
         "v8/workers/heap/read_only_space/isolate_0x?",
         "v8/workers/heap/shared_large_object_space/isolate_0x?",
         "v8/workers/heap/shared_space/isolate_0x?",
+        "v8/workers/heap/shared_trusted_large_object_space/isolate_0x?",
+        "v8/workers/heap/shared_trusted_space/isolate_0x?",
         "v8/workers/heap/trusted_space/isolate_0x?",
         "v8/workers/heap/trusted_large_object_space/isolate_0x?",
         "v8/workers/malloc/isolate_0x?",
diff --git a/base/values.cc b/base/values.cc
index d66a2e1..2ac910b 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -217,8 +217,9 @@
 
 Value::DoubleStorage::DoubleStorage(double v) : v_(bit_cast<decltype(v_)>(v)) {
   if (!std::isfinite(v)) {
-    NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
-                 << "values cannot be represented in JSON";
+    DUMP_WILL_BE_NOTREACHED_NORETURN()
+        << "Non-finite (i.e. NaN or positive/negative infinity) "
+        << "values cannot be represented in JSON";
     v_ = bit_cast<decltype(v_)>(0.0);
   }
 }
diff --git a/build/install-build-deps.py b/build/install-build-deps.py
index b321fff..3f0c4ef 100755
--- a/build/install-build-deps.py
+++ b/build/install-build-deps.py
@@ -233,7 +233,6 @@
       "libsctp-dev",
       "libspeechd-dev",
       "libsqlite3-dev",
-      "libssl-dev",
       "libsystemd-dev",
       "libudev-dev",
       "libva-dev",
@@ -326,6 +325,17 @@
     elif package_exists("lib32gcc1"):
       packages.append("lib32gcc1")
 
+  # TODO(b/339091434): Remove this workaround once this bug is fixed.  This
+  # workaround ensures the newer libssl-dev is used to prevent package conficts.
+  apt_cache_cmd = ["apt-cache", "show", "libssl-dev"]
+  output = subprocess.check_output(apt_cache_cmd).decode()
+  pattern = re.compile(r'^Version: (.+?)$', re.M)
+  versions = re.findall(pattern, output)
+  if set(versions) == {"3.2.1-3", "3.0.10-1"}:
+    packages.append("libssl-dev=3.2.1-3")
+  else:
+    packages.append("libssl-dev")
+
   return packages
 
 
diff --git a/components/policy/core/common/default_chrome_apps_migrator.cc b/components/policy/core/common/default_chrome_apps_migrator.cc
index 199636a..7d95058 100644
--- a/components/policy/core/common/default_chrome_apps_migrator.cc
+++ b/components/policy/core/common/default_chrome_apps_migrator.cc
@@ -120,7 +120,8 @@
         policies->Get(key::kExtensionInstallForcelist);
     PolicyMap::Entry policy_entry(
         forcelist_entry->level, forcelist_entry->scope, forcelist_entry->source,
-        base::Value(base::Value::Type::LIST), nullptr);
+        base::Value(base::Value::Type::LIST), /*external_data_fetcher=*/nullptr,
+        policies->GetPolicyDetails(policy_name));
     // If `policy_value` has wrong type, add message before overriding value.
     if (policy_value) {
       policy_entry.AddMessage(PolicyMap::MessageType::kError,
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
index b7d37e0..5a1962a 100644
--- a/components/policy/core/common/policy_map.cc
+++ b/components/policy/core/common/policy_map.cc
@@ -68,7 +68,8 @@
     PolicyScope scope,
     bool cloud_policy_overrides_platform_policy,
     bool cloud_user_policy_overrides_cloud_machine_policy,
-    bool is_user_affiliated) {
+    bool is_user_affiliated,
+    const PolicyDetails* details) {
   switch (source) {
     case POLICY_SOURCE_ENTERPRISE_DEFAULT:
       return POLICY_PRIORITY_BROWSER_ENTERPRISE_DEFAULT;
@@ -82,6 +83,11 @@
                    ? POLICY_PRIORITY_BROWSER_CLOUD_MACHINE_RAISED
                    : POLICY_PRIORITY_BROWSER_CLOUD_MACHINE;
       }
+      // For policies that can only be set with managed account, raise the
+      // priority of correct source to highest.
+      if (details && details->scope == kSingleProfile) {
+        return POLICY_PRIORITY_BROWSER_CLOUD_USER_DOUBLE_RAISED;
+      }
       if (cloud_user_policy_overrides_cloud_machine_policy &&
           is_user_affiliated) {
         // Raise the priority of cloud user policies only when the metapolicy
@@ -120,11 +126,13 @@
     PolicyScope scope,
     PolicySource source,
     std::optional<base::Value> value,
-    std::unique_ptr<ExternalDataFetcher> external_data_fetcher)
+    std::unique_ptr<ExternalDataFetcher> external_data_fetcher,
+    const PolicyDetails* details)
     : level(level),
       scope(scope),
       source(source),
       external_data_fetcher(std::move(external_data_fetcher)),
+      details(details),
       value_(std::move(value)) {}
 
 PolicyMap::Entry::~Entry() = default;
@@ -138,7 +146,8 @@
       value_ ? std::make_optional<base::Value>(value_->Clone()) : std::nullopt,
       external_data_fetcher
           ? std::make_unique<ExternalDataFetcher>(*external_data_fetcher)
-          : nullptr);
+          : nullptr,
+      details);
   copy.ignored_ = ignored_;
   copy.message_ids_ = message_ids_;
   copy.is_default_value_ = is_default_value_;
@@ -378,7 +387,7 @@
     std::optional<base::Value> value,
     std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
   Entry entry(level, scope, source, std::move(value),
-              std::move(external_data_fetcher));
+              std::move(external_data_fetcher), GetPolicyDetails(policy));
   Set(policy, std::move(entry));
 }
 
@@ -541,12 +550,17 @@
 }
 
 bool PolicyMap::IsPolicyExternal(const std::string& policy) {
-  const PolicyDetails* policy_details = details_callback_.Run(policy);
+  const PolicyDetails* policy_details = GetPolicyDetails(policy);
   if (policy_details && policy_details->max_external_data_size > 0)
     return true;
   return false;
 }
 
+const PolicyDetails* PolicyMap::GetPolicyDetails(
+    const std::string& policy) const {
+  return details_callback_.Run(policy);
+}
+
 void PolicyMap::LoadFrom(const base::Value::Dict& policies,
                          PolicyLevel level,
                          PolicyScope scope,
@@ -611,20 +625,21 @@
   return std::tie(lhs.level, lhs.scope, lhs.source) >
          std::tie(rhs.level, rhs.scope, rhs.source);
 #else   // BUILDFLAG(IS_CHROMEOS)
+  const PolicyDetails* details = lhs.details ? lhs.details : rhs.details;
   PolicyPriorityBrowser lhs_priority =
       using_default_precedence
-          ? GetPriority(lhs.source, lhs.scope, false, false, false)
+          ? GetPriority(lhs.source, lhs.scope, false, false, false, details)
           : GetPriority(lhs.source, lhs.scope,
                         cloud_policy_overrides_platform_policy_,
                         cloud_user_policy_overrides_cloud_machine_policy_,
-                        IsUserAffiliated());
+                        IsUserAffiliated(), details);
   PolicyPriorityBrowser rhs_priority =
       using_default_precedence
-          ? GetPriority(rhs.source, rhs.scope, false, false, false)
+          ? GetPriority(rhs.source, rhs.scope, false, false, false, details)
           : GetPriority(rhs.source, rhs.scope,
                         cloud_policy_overrides_platform_policy_,
                         cloud_user_policy_overrides_cloud_machine_policy_,
-                        IsUserAffiliated());
+                        IsUserAffiliated(), details);
   return std::tie(lhs.level, lhs_priority) > std::tie(rhs.level, rhs_priority);
 #endif  // BUILDFLAG(IS_CHROMEOS)
 }
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h
index 683ab5b..22d6fbb 100644
--- a/components/policy/core/common/policy_map.h
+++ b/components/policy/core/common/policy_map.h
@@ -16,6 +16,7 @@
 #include "base/containers/flat_set.h"
 #include "base/functional/callback.h"
 #include "base/gtest_prod_util.h"
+#include "base/memory/raw_ptr.h"
 #include "base/values.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_details.h"
@@ -55,13 +56,18 @@
     PolicySource source = POLICY_SOURCE_ENTERPRISE_DEFAULT;
     std::unique_ptr<ExternalDataFetcher> external_data_fetcher;
     std::vector<EntryConflict> conflicts;
+    // Unsupported raw_ptr: Pointer fields in classes/structs that are used as
+    // global.
+    // PolicyDetails is defined in gen/components/policy/policy_constants.cc
+    RAW_PTR_EXCLUSION const PolicyDetails* details = nullptr;
 
     Entry();
     Entry(PolicyLevel level,
           PolicyScope scope,
           PolicySource source,
           std::optional<base::Value> value,
-          std::unique_ptr<ExternalDataFetcher> external_data_fetcher);
+          std::unique_ptr<ExternalDataFetcher> external_data_fetcher,
+          const PolicyDetails* details = nullptr);
     ~Entry();
 
     Entry(Entry&&) noexcept;
@@ -323,8 +329,12 @@
   // Returns the set containing device affiliation ID strings.
   const base::flat_set<std::string>& GetDeviceAffiliationIds() const;
 
-  // Sets the ChromePolicyDetailsCallback, which is used in IsPolicyExternal(),
-  // in test environments
+  // Returns the PolicyDetails which is generated with the yaml definition of
+  // the `policy`.
+  const PolicyDetails* GetPolicyDetails(const std::string& policy) const;
+
+  // Sets the ChromePolicyDetailsCallback, which is used in
+  // IsPolicyExternal(), in test environments
   void set_chrome_policy_details_callback_for_test(
       const GetChromePolicyDetailsCallback& details_callback);
 
diff --git a/components/policy/core/common/policy_map_unittest.cc b/components/policy/core/common/policy_map_unittest.cc
index 6f77196..d40c3f5 100644
--- a/components/policy/core/common/policy_map_unittest.cc
+++ b/components/policy/core/common/policy_map_unittest.cc
@@ -42,6 +42,13 @@
 // Dummy error message.
 const char16_t kTestError[] = u"Test error message";
 
+const PolicyDetails kExternalDetails_ = {false, false, kProfile, 0, 10, {}};
+const PolicyDetails kNonExternalDetails_ = {false, false, kProfile, 0, 0, {}};
+#if !BUILDFLAG(IS_CHROMEOS)
+const PolicyDetails kUserCloudDetails = {false, false, kSingleProfile,
+                                         0,     0,     {}};
+#endif
+
 // Utility functions for the tests.
 void SetPolicy(PolicyMap* map, const char* name, base::Value value) {
   map->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
@@ -81,16 +88,13 @@
  public:
   const PolicyDetails* GetPolicyDetailsExternalCallback(
       const std::string& policy_name) {
-    return &externalDetails_;
+    return &kExternalDetails_;
   }
 
   const PolicyDetails* GetPolicyDetailsNonExternalCallback(
       const std::string& policy_name) {
-    return &nonExternalDetails_;
+    return &kNonExternalDetails_;
   }
-
-  PolicyDetails externalDetails_ = {false, false, kProfile, 0, 10, {}};
-  PolicyDetails nonExternalDetails_ = {false, false, kProfile, 0, 0, {}};
 };
 
 TEST_F(PolicyMapTest, SetAndGet) {
@@ -1719,7 +1723,29 @@
 
   bool IsUserAffiliated() { return std::get<2>(GetParam()); }
 
-  void CheckPriorityConditions(PolicyMap& policy_map) {
+  void SetUp() override {
+    // Update the metapolicy values.
+    policy_map_.Set(key::kCloudPolicyOverridesPlatformPolicy,
+                    POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                    POLICY_SOURCE_PLATFORM,
+                    base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
+    policy_map_.Set(
+        key::kCloudUserPolicyOverridesCloudMachinePolicy,
+        POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
+        base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
+    // Causes the stored metapolicy values to be updated.
+    PolicyMap policy_map_empty;
+    policy_map_.MergeFrom(policy_map_empty);
+
+    if (IsUserAffiliated()) {
+      base::flat_set<std::string> affiliation_ids;
+      affiliation_ids.insert("a");
+      policy_map_.SetUserAffiliationIds(affiliation_ids);
+      policy_map_.SetDeviceAffiliationIds(affiliation_ids);
+    }
+  }
+
+  void CheckPriorityConditions() {
     PolicyMap::Entry platform_machine(
         POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
         base::Value(), nullptr);
@@ -1742,101 +1768,119 @@
     if (CloudPolicyOverridesPlatformPolicy() &&
         CloudUserPolicyOverridesCloudMachinePolicy() && IsUserAffiliated()) {
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, platform_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_machine));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(cloud_machine, platform_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(cloud_machine, cloud_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(platform_user, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
+          policy_map_.EntryHasHigherPriority(platform_user, cloud_user));
+      EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, command_line));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
+          policy_map_.EntryHasHigherPriority(cloud_user, enterprise_default));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(command_line, enterprise_default));
+          policy_map_.EntryHasHigherPriority(command_line, enterprise_default));
     } else if (CloudUserPolicyOverridesCloudMachinePolicy() &&
                IsUserAffiliated()) {
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, platform_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_machine));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(cloud_machine, platform_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(cloud_machine, cloud_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(platform_user, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
+          policy_map_.EntryHasHigherPriority(platform_user, cloud_user));
+      EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, command_line));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
+          policy_map_.EntryHasHigherPriority(cloud_user, enterprise_default));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(command_line, enterprise_default));
+          policy_map_.EntryHasHigherPriority(command_line, enterprise_default));
     } else if (CloudPolicyOverridesPlatformPolicy()) {
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, platform_user));
       EXPECT_FALSE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_machine));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(platform_user, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
+          policy_map_.EntryHasHigherPriority(cloud_machine, platform_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
+          policy_map_.EntryHasHigherPriority(cloud_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(command_line, enterprise_default));
+          policy_map_.EntryHasHigherPriority(platform_user, cloud_user));
+      EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, command_line));
+      EXPECT_TRUE(
+          policy_map_.EntryHasHigherPriority(cloud_user, enterprise_default));
+      EXPECT_TRUE(
+          policy_map_.EntryHasHigherPriority(command_line, enterprise_default));
     } else {
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, platform_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, platform_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_machine));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
+          policy_map_.EntryHasHigherPriority(platform_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(platform_user, cloud_user));
-      EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
+          policy_map_.EntryHasHigherPriority(cloud_machine, platform_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
+          policy_map_.EntryHasHigherPriority(cloud_machine, cloud_user));
       EXPECT_TRUE(
-          policy_map.EntryHasHigherPriority(command_line, enterprise_default));
+          policy_map_.EntryHasHigherPriority(platform_user, cloud_user));
+      EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, command_line));
+      EXPECT_TRUE(
+          policy_map_.EntryHasHigherPriority(cloud_user, enterprise_default));
+      EXPECT_TRUE(
+          policy_map_.EntryHasHigherPriority(command_line, enterprise_default));
     }
   }
+
+  PolicyMap policy_map_;
 };
 
 TEST_P(PolicyMapPriorityTest, PriorityCheck) {
-  PolicyMap policy_map;
+  CheckPriorityConditions();
+}
 
-  // Update the metapolicy values.
-  policy_map.Set(key::kCloudPolicyOverridesPlatformPolicy,
-                 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
-                 POLICY_SOURCE_PLATFORM,
-                 base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
-  policy_map.Set(
-      key::kCloudUserPolicyOverridesCloudMachinePolicy, POLICY_LEVEL_MANDATORY,
-      POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
-      base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
-  // Causes the stored metapolicy values to be updated.
-  PolicyMap policy_map_empty;
-  policy_map.MergeFrom(policy_map_empty);
+TEST_P(PolicyMapPriorityTest, SingleProfilePolicy) {
+  PolicyMap::Entry platform_machine(
+      POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
+      base::Value(), nullptr, &kUserCloudDetails);
+  PolicyMap::Entry platform_user(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+                                 POLICY_SOURCE_PLATFORM, base::Value(), nullptr,
+                                 &kUserCloudDetails);
+  PolicyMap::Entry cloud_machine(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                                 POLICY_SOURCE_CLOUD, base::Value(), nullptr,
+                                 &kUserCloudDetails);
+  PolicyMap::Entry cloud_user(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+                              POLICY_SOURCE_CLOUD, base::Value(), nullptr,
+                              &kUserCloudDetails);
+  PolicyMap::Entry command_line(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                                POLICY_SOURCE_COMMAND_LINE, base::Value(),
+                                nullptr, &kUserCloudDetails);
 
-  if (IsUserAffiliated()) {
-    base::flat_set<std::string> affiliation_ids;
-    affiliation_ids.insert("a");
-    policy_map.SetUserAffiliationIds(affiliation_ids);
-    policy_map.SetDeviceAffiliationIds(affiliation_ids);
-  }
+  EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, cloud_machine));
+  EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, platform_user));
+  EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, platform_machine));
+  EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, platform_machine));
+}
 
-  CheckPriorityConditions(policy_map);
+TEST_P(PolicyMapPriorityTest, SingleProfilePolicyWithMissingDetails) {
+  PolicyMap::Entry cloud_machine(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                                 POLICY_SOURCE_CLOUD, base::Value(), nullptr,
+                                 &kUserCloudDetails);
+  PolicyMap::Entry cloud_user(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+                              POLICY_SOURCE_CLOUD, base::Value(), nullptr,
+                              nullptr);
+  EXPECT_TRUE(policy_map_.EntryHasHigherPriority(cloud_user, cloud_machine));
+  EXPECT_FALSE(policy_map_.EntryHasHigherPriority(cloud_machine, cloud_user));
 }
 
 INSTANTIATE_TEST_SUITE_P(PolicyMapPriorityTestInstance,
diff --git a/mojo/public/interfaces/bindings/tests/data/README.md b/mojo/public/interfaces/bindings/tests/data/README.md
new file mode 100644
index 0000000..13d964b
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/README.md
@@ -0,0 +1,27 @@
+# Mojo conformance test data
+The files in [validations](validations) are test data for mojo conformance
+tests, which validate the memory layout of mojo messages.
+
+Run validation tests using the following command:
+
+```
+autoninja -C out/Default mojo_unittests
+out/Default/bin/run_mojo_unittests --gtest_filter=ValidationTest.*
+```
+
+Note that you do not need to rebuild after changing the test data.
+
+## Adding test data
+
+1. Add a test method if necessary in
+   [validation test interfaces](../validation_test_interfaces.mojom).
+1. Add a .data and .expected file in [validations](validations).
+   * The syntax for the .data file can be found in the
+     [validation test input parser](/mojo/public/cpp/bindings/tests/validation_test_input_parser.h).
+1. Run `ValidationTest.*` to ensure that tests work as expected.
+1. Update [validation_data_files.gni](../validation_data_files.gni) with your
+   test files.
+1. Use [python script](/build/ios/update_bundle_filelist.py) to update
+   [validation_unittest_bundle_data.filelist](../validation_unittest_bundle_data.filelist).
+   * The presubmit will give you a copy pastable command, so there is no need to
+     to figure out how to invoke the script.