Automated commit: libchrome r1329366 uprev

Merge with upstream commit 753f3e772ef130fcb67d86ecb8d08a75aa1f5f08

BUG=None
TEST=sudo emerge libchrome

Change-Id: I35702b6a31840ca53ee0820b11491cd481fbf550
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/5721468
Commit-Queue: Brett Brotherton <bbrotherton@google.com>
Tested-by: ChromeOS Prod (Robot) <chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com>
Bot-Commit: ChromeOS Prod (Robot) <chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com>
diff --git a/BASE_VER b/BASE_VER
index 17cc58e..0161e97 100644
--- a/BASE_VER
+++ b/BASE_VER
@@ -1 +1 @@
-1328677
+1329366
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index 031e8ad..46728b2 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -168,30 +168,16 @@
      * Run the supplied Runnable on the main thread. The method will block until the Runnable
      * completes.
      *
-     * Note that non-test usage of this function is heavily discouraged. For non-tests, use
+     * <p>Note that non-test usage of this function is heavily discouraged. For non-tests, use
      * callbacks rather than blocking threads.
      *
      * @param r The Runnable to run.
      */
-    public static void runOnUiThreadBlocking(final Runnable r) {
+    public static void runOnUiThreadBlocking(Runnable r) {
         PostTask.runSynchronously(TaskTraits.UI_DEFAULT, r);
     }
 
     /**
-     * Run the supplied Callable on the main thread, wrapping any exceptions in a RuntimeException.
-     * The method will block until the Callable completes.
-     *
-     * <p>Note that non-test usage of this function is heavily discouraged. For non-tests, use
-     * callbacks rather than blocking threads.
-     *
-     * @param c The Callable to run
-     * @return The result of the callable
-     */
-    public static <T> T runOnUiThreadBlockingNoException(Callable<T> c) {
-        return runOnUiThreadBlocking(c);
-    }
-
-    /**
      * Run the supplied Callable on the main thread, The method will block until the Callable
      * completes.
      *
@@ -218,17 +204,6 @@
     }
 
     /**
-     * Run the supplied Callable on the main thread. The method will block only if the current
-     * thread is the main thread.
-     *
-     * @param c The Callable to run
-     * @return A FutureTask wrapping the callable to retrieve results
-     */
-    public static <T> FutureTask<T> runOnUiThread(Callable<T> c) {
-        return runOnUiThread(new FutureTask<T>(c));
-    }
-
-    /**
      * Run the supplied Runnable on the main thread. The method will block only if the current
      * thread is the main thread.
      *
diff --git a/base/containers/span.h b/base/containers/span.h
index 356851e..6fc6e8a 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -314,6 +314,11 @@
         data_(base::to_address(first)) {
     // Guarantees that the N in the type signature is correct.
     CHECK(N == count);
+
+    // `count != 0` implies non-null `data_`.  Consider using
+    // `base::SpanOrSize<T>` to represent a size that may or may not be
+    // accompanied by the actual data.
+    DCHECK(count == 0 || !!data_);
   }
 
   // Constructs a span from a contiguous iterator and a size.
@@ -865,7 +870,12 @@
       // We can not protect here generally against an invalid iterator/count
       // being passed in, since we have no context to determine if the
       // iterator or count are valid.
-      : data_(base::to_address(first)), size_(count) {}
+      : data_(base::to_address(first)), size_(count) {
+    // `count != 0` implies non-null `data_`.  Consider using
+    // `base::SpanOrSize<T>` to represent a size that may or may not be
+    // accompanied by the actual data.
+    DCHECK(count == 0 || !!data_);
+  }
 
   // Constructs a span from a contiguous iterator and a size.
   //
diff --git a/base/containers/span_or_size.h b/base/containers/span_or_size.h
new file mode 100644
index 0000000..fdf12df
--- /dev/null
+++ b/base/containers/span_or_size.h
@@ -0,0 +1,68 @@
+// 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.
+
+#ifndef BASE_CONTAINERS_SPAN_OR_SIZE_H_
+#define BASE_CONTAINERS_SPAN_OR_SIZE_H_
+
+#include <stddef.h>
+
+#include <variant>
+
+#include "base/containers/span.h"
+#include "base/functional/overloaded.h"
+#include "base/types/optional_ref.h"
+
+namespace base {
+
+// `SpanOrSize<T>` contains either a `span<T>` or just the size of data.  This
+// is useful if the data is not retained in some scenarios, but size needs to be
+// available in all the scenarios.
+template <typename T>
+class SpanOrSize {
+ public:
+  explicit constexpr SpanOrSize(base::span<T> span) : span_or_size_(span) {}
+  explicit constexpr SpanOrSize(size_t size) : span_or_size_(size) {}
+
+  ~SpanOrSize() = default;
+
+  // `SpanOrSize` is copyable and movable (just like `span` and `size_t`).
+  SpanOrSize(const SpanOrSize&) = default;
+  SpanOrSize& operator=(const SpanOrSize&) = default;
+  SpanOrSize(SpanOrSize&&) = default;
+  SpanOrSize& operator=(SpanOrSize&&) = default;
+
+  constexpr T* ptr_or_null_if_no_data() const {
+    return std::visit(base::Overloaded{
+                          [](const base::span<T>& span) { return span.data(); },
+                          [](size_t size) -> T* { return nullptr; },
+                      },
+                      span_or_size_);
+  }
+
+  constexpr size_t size() const {
+    return std::visit(base::Overloaded{
+                          [](const base::span<T>& span) { return span.size(); },
+                          [](size_t size) { return size; },
+                      },
+                      span_or_size_);
+  }
+
+  constexpr optional_ref<const base::span<T>> span() const {
+    return std::visit(
+        base::Overloaded{
+            [](const base::span<T>& span) {
+              return optional_ref<const base::span<T>>(span);
+            },
+            [](size_t size) { return optional_ref<const base::span<T>>(); },
+        },
+        span_or_size_);
+  }
+
+ private:
+  std::variant<base::span<T>, size_t> span_or_size_;
+};
+
+}  // namespace base
+
+#endif  // BASE_CONTAINERS_SPAN_OR_SIZE_H_
diff --git a/base/containers/span_or_size_unittest.cc b/base/containers/span_or_size_unittest.cc
new file mode 100644
index 0000000..b45b43c
--- /dev/null
+++ b/base/containers/span_or_size_unittest.cc
@@ -0,0 +1,45 @@
+// 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.
+
+#include "base/containers/span_or_size.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace {
+
+TEST(SpanOrSizeTest, Size) {
+  SpanOrSize<int> s(123u);
+
+  EXPECT_FALSE(s.span().has_value());
+  EXPECT_EQ(s.size(), 123u);
+  EXPECT_EQ(s.ptr_or_null_if_no_data(), nullptr);
+}
+
+TEST(SpanOrSizeTest, Span) {
+  std::vector<int> v{1, 2, 3};
+  SpanOrSize<int> s{base::span<int>(v)};
+
+  EXPECT_TRUE(s.span().has_value());
+  EXPECT_EQ(s.span()->data(), v.data());
+  EXPECT_EQ(s.span()->size(), 3u);
+
+  EXPECT_EQ(s.size(), 3u);
+  EXPECT_EQ(s.ptr_or_null_if_no_data(), v.data());
+}
+
+TEST(SpanOrSizeTest, SpanDeductionGuide) {
+  std::vector<int> v{1, 42, 3};
+
+  // MAIN TEST: No need to spell out `SpanOrSize<int>` below
+  // (IIUC thanks to an implicit deduction guide inferred by the compiler).
+  auto s = SpanOrSize(base::span(v));
+
+  EXPECT_EQ(s.span().value()[1], 42);
+}
+
+}  // namespace
+}  // namespace base
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc
index c413eb5..ba153b7 100644
--- a/base/containers/span_unittest.cc
+++ b/base/containers/span_unittest.cc
@@ -198,6 +198,21 @@
   }
 }
 
+TEST(SpanTest, ConstructFromDataAndZeroSize) {
+  char* nullptr_to_char = nullptr;
+
+  auto empty_span = UNSAFE_BUFFERS(span<char>(nullptr_to_char, 0u));
+  EXPECT_EQ(empty_span.size(), 0u);
+  EXPECT_EQ(empty_span.data(), nullptr);
+  EXPECT_TRUE(empty_span.empty());
+
+  // We expect a `DCHECK` to catch construction of a dangling span - let's cover
+  // this expectation in a test, so that future `//base` refactorings (e.g.
+  // maybe switching to `std::span`) won't just silently change of this aspect
+  // of span behavior.
+  EXPECT_DCHECK_DEATH({ UNSAFE_BUFFERS(span<char>(nullptr_to_char, 123u)); });
+}
+
 TEST(SpanTest, ConstructFromIterAndSize) {
   constexpr int* kNull = nullptr;
   // SAFETY: zero size is correct when pointer argument is NULL.
diff --git a/base/profiler/stack_sampler.cc b/base/profiler/stack_sampler.cc
index 0ece357..297ae28 100644
--- a/base/profiler/stack_sampler.cc
+++ b/base/profiler/stack_sampler.cc
@@ -80,7 +80,7 @@
   const MetadataRecorder::MetadataProvider* const metadata_provider_;
 };
 
-bool g_use_thread_pool = false;
+bool g_use_thread_pool = true;
 
 }  // namespace
 
diff --git a/base/profiler/stack_sampler_unittest.cc b/base/profiler/stack_sampler_unittest.cc
index f69270f..e68e7bc 100644
--- a/base/profiler/stack_sampler_unittest.cc
+++ b/base/profiler/stack_sampler_unittest.cc
@@ -440,10 +440,13 @@
   CallRecordingUnwinder* aux_unwinder = owned_aux_unwinder.get();
   stack_sampler->AddAuxUnwinder(std::move(owned_aux_unwinder));
 
+  // The definition of this unwinder needs to be outside of the conditional
+  // for the `thread_pool_runner` otherwise we will hit a TSAN failure as
+  // we Record this thread's stack later in `RecordStackFrames`.
+  base::test::TestFuture<void> unwinder_added;
   // If we are running a thread pool we need to wait for the aux unwinder to
   // actually be added before we start recording stack frames.
   if (stack_sampler->thread_pool_runner_) {
-    base::test::TestFuture<void> unwinder_added;
     stack_sampler->thread_pool_runner_->PostTaskAndReply(
         FROM_HERE, base::DoNothing(), unwinder_added.GetCallback());
     ASSERT_TRUE(unwinder_added.Wait());
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
index 3fc4758..ce538d4 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
@@ -13,6 +13,7 @@
 
 import org.junit.Assert;
 
+import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 
 import java.util.concurrent.TimeUnit;
@@ -21,6 +22,7 @@
 
 /** Methods used for testing Application-level behavior. */
 public class ApplicationTestUtils {
+    private static final String TAG = "ApplicationTestUtils";
     private static final ActivityLifecycleMonitor sMonitor =
             ActivityLifecycleMonitorRegistry.getInstance();
 
@@ -57,7 +59,10 @@
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     if (sMonitor.getLifecycleStageOf(activity) != Stage.DESTROYED) {
+                        Log.i(TAG, "Finishing %s", activity);
                         activity.finish();
+                    } else {
+                        Log.i(TAG, "Not finishing - already destroyed: %s", activity);
                     }
                 });
         final String error =
diff --git a/base/trace_event/memory_infra_background_allowlist.cc b/base/trace_event/memory_infra_background_allowlist.cc
index e159aaa..d0968ed 100644
--- a/base/trace_event/memory_infra_background_allowlist.cc
+++ b/base/trace_event/memory_infra_background_allowlist.cc
@@ -249,6 +249,7 @@
         "skia/gpu_resources/context_0x?",
         "skia/gpu_resources/graphite_context_0x?",
         "skia/gpu_resources/gpu_main_graphite_recorder_0x?",
+        "skia/gpu_resources/viz_compositor_graphite_recorder_0x?",
         "skia/sk_glyph_cache",
         "skia/sk_resource_cache",
         "sqlite",
diff --git a/mojo/core/ipcz_driver/data_pipe.cc b/mojo/core/ipcz_driver/data_pipe.cc
index 532a2cf..04bffa8 100644
--- a/mojo/core/ipcz_driver/data_pipe.cc
+++ b/mojo/core/ipcz_driver/data_pipe.cc
@@ -334,8 +334,19 @@
   }
 
   FlushUpdatesFromPeer();
-  const base::span<uint8_t> output_bytes =
-      base::make_span(static_cast<uint8_t*>(elements), num_bytes);
+  base::span<uint8_t> output_bytes;
+  if (!(discard || query)) {
+    // `elements` can be null in the `discard` or `query` cases and would result
+    // in creating a non-empty, dangling `span` (hitting a `DCHECK` in `span`'s
+    // constructor).  OTOH, `elements` and `num_bytes` need to describe a valid
+    // span in all the other cases.
+    if (!elements && num_bytes > 0) {
+      return MOJO_RESULT_INVALID_ARGUMENT;
+    }
+
+    output_bytes = base::span(static_cast<uint8_t*>(elements), num_bytes);
+  }
+
   size_t read_size = num_bytes;
   scoped_refptr<PortalWrapper> portal;
   {
@@ -354,10 +365,6 @@
       return MOJO_RESULT_INVALID_ARGUMENT;
     }
 
-    if (!discard && !elements && data_size > 0) {
-      return MOJO_RESULT_INVALID_ARGUMENT;
-    }
-
     has_new_data_ = false;
     if (!allow_partial) {
       bool success;