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;