aboutsummaryrefslogtreecommitdiff
path: root/srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch')
-rw-r--r--srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch357
1 files changed, 357 insertions, 0 deletions
diff --git a/srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch b/srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch
new file mode 100644
index 00000000000..8e7aa1db365
--- /dev/null
+++ b/srcpkgs/electron19/files/chromium-upstream-patches/0014-M102-Ensure-raw_ptr-T-and-T-are-treated-identically-.patch
@@ -0,0 +1,357 @@
+From f427936d32dbe1e9c27c0bcf54eff6818bddb906 Mon Sep 17 00:00:00 2001
+From: Daniel Cheng <dcheng@chromium.org>
+Date: Tue, 14 Jun 2022 19:11:17 +0000
+Subject: [PATCH 14/59] [M102] Ensure raw_ptr<T> and T* are treated identically
+ in //base callback.
+
+There are safety checks associated with raw pointers (e.g. ensuring
+receiver pointers are not raw pointers). Make sure these checks are
+applied whether the input type is T* or raw_ptr<T>.
+
+- Implement base::IsPointer<T> and base::RemovePointer<T>, which are
+ similar to std::is_pointer<T> and std::remove_pointer<T>, except they
+ also consider raw_ptr<T> a raw pointer type.
+- Fix failures from the strengthened asserts: WebAppInstallFinalizer
+ does not need a callback at all, while the privacy sandbox dialog
+ tests can safely use base::Unretained().
+- Add test cases to cover this in the //base callback nocompile test
+ suite.
+- Fix the existing nocompile tests, which did not escape `||` and
+ inadvertently matched any error text.
+
+(cherry picked from commit 00c072a2c7f24921af3bbf8441abb34ecb0551a6)
+
+Bug: 1335458
+Change-Id: I470e3d5bc35ed52bf125136db738a868ef90b7e7
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3700700
+Reviewed-by: Lei Zhang <thestig@chromium.org>
+Commit-Queue: Daniel Cheng <dcheng@chromium.org>
+Cr-Original-Commit-Position: refs/heads/main@{#1013266}
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3703779
+Cr-Commit-Position: refs/branch-heads/5005@{#1173}
+Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
+---
+ base/bind_internal.h | 17 +++++-----
+ base/bind_unittest.cc | 28 +++++++++++++++++
+ base/bind_unittest.nc | 31 +++++++++++++++++--
+ base/memory/raw_ptr.h | 31 +++++++++++++++++++
+ .../raw_scoped_refptr_mismatch_checker.h | 5 +--
+ ...privacy_sandbox_dialog_handler_unittest.cc | 26 +++++++++-------
+ .../web_app_install_finalizer.cc | 15 ++++-----
+ 7 files changed, 121 insertions(+), 32 deletions(-)
+
+diff --git a/base/bind_internal.h b/base/bind_internal.h
+index 60607efadb30..1b06e54b65a4 100644
+--- a/base/bind_internal.h
++++ b/base/bind_internal.h
+@@ -859,8 +859,8 @@ bool QueryCancellationTraits(const BindStateBase* base,
+ template <typename Functor, typename Receiver, typename... Unused>
+ std::enable_if_t<
+ !(MakeFunctorTraits<Functor>::is_method &&
+- std::is_pointer_v<std::decay_t<Receiver>> &&
+- IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value)>
++ IsPointerV<std::decay_t<Receiver>> &&
++ IsRefCountedType<RemovePointerT<std::decay_t<Receiver>>>::value)>
+ BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {}
+
+ template <typename Functor>
+@@ -870,8 +870,8 @@ void BanUnconstructedRefCountedReceiver() {}
+ template <typename Functor, typename Receiver, typename... Unused>
+ std::enable_if_t<
+ MakeFunctorTraits<Functor>::is_method &&
+- std::is_pointer_v<std::decay_t<Receiver>> &&
+- IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value>
++ IsPointerV<std::decay_t<Receiver>> &&
++ IsRefCountedType<RemovePointerT<std::decay_t<Receiver>>>::value>
+ BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
+ DCHECK(receiver);
+
+@@ -1006,19 +1006,20 @@ struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
+ static_assert(!std::is_array_v<std::remove_reference_t<Receiver>>,
+ "First bound argument to a method cannot be an array.");
+ static_assert(
+- !std::is_pointer_v<DecayedReceiver> ||
+- IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
++ !IsPointerV<DecayedReceiver> ||
++ IsRefCountedType<RemovePointerT<DecayedReceiver>>::value,
+ "Receivers may not be raw pointers. If using a raw pointer here is safe"
+ " and has no lifetime concerns, use base::Unretained() and document why"
+ " it's safe.");
++
+ static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
+ "A parameter is a refcounted type and needs scoped_refptr.");
+
+ public:
+ using Type = BindState<
+ std::decay_t<Functor>,
+- std::conditional_t<std::is_pointer_v<DecayedReceiver>,
+- scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
++ std::conditional_t<IsPointerV<DecayedReceiver>,
++ scoped_refptr<RemovePointerT<DecayedReceiver>>,
+ DecayedReceiver>,
+ MakeStorageType<BoundArgs>...>;
+ };
+diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
+index a5f681fe53b9..6844b6796d9f 100644
+--- a/base/bind_unittest.cc
++++ b/base/bind_unittest.cc
+@@ -1169,6 +1169,28 @@ TYPED_TEST(BindVariantsTest, UniquePtrReceiver) {
+ TypeParam::Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run();
+ }
+
++TYPED_TEST(BindVariantsTest, ImplicitRefPtrReceiver) {
++ StrictMock<HasRef> has_ref;
++ EXPECT_CALL(has_ref, AddRef()).Times(1);
++ EXPECT_CALL(has_ref, Release()).Times(1);
++ EXPECT_CALL(has_ref, HasAtLeastOneRef()).WillRepeatedly(Return(true));
++
++ HasRef* ptr = &has_ref;
++ auto ptr_cb = TypeParam::Bind(&HasRef::HasAtLeastOneRef, ptr);
++ EXPECT_EQ(1, std::move(ptr_cb).Run());
++}
++
++TYPED_TEST(BindVariantsTest, RawPtrReceiver) {
++ StrictMock<HasRef> has_ref;
++ EXPECT_CALL(has_ref, AddRef()).Times(1);
++ EXPECT_CALL(has_ref, Release()).Times(1);
++ EXPECT_CALL(has_ref, HasAtLeastOneRef()).WillRepeatedly(Return(true));
++
++ raw_ptr<HasRef> rawptr(&has_ref);
++ auto rawptr_cb = TypeParam::Bind(&HasRef::HasAtLeastOneRef, rawptr);
++ EXPECT_EQ(1, std::move(rawptr_cb).Run());
++}
++
+ // Tests for Passed() wrapper support:
+ // - Passed() can be constructed from a pointer to scoper.
+ // - Passed() can be constructed from a scoper rvalue.
+@@ -1751,6 +1773,12 @@ TEST(BindDeathTest, BanFirstOwnerOfRefCountedType) {
+ EXPECT_CALL(has_ref, HasAtLeastOneRef()).WillOnce(Return(false));
+ base::BindOnce(&HasRef::VoidMethod0, &has_ref);
+ });
++
++ EXPECT_DCHECK_DEATH({
++ raw_ptr<HasRef> rawptr(&has_ref);
++ EXPECT_CALL(has_ref, HasAtLeastOneRef()).WillOnce(Return(false));
++ base::BindOnce(&HasRef::VoidMethod0, rawptr);
++ });
+ }
+
+ } // namespace
+diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
+index 20b0e0ba2cee..29807298ca3c 100644
+--- a/base/bind_unittest.nc
++++ b/base/bind_unittest.nc
+@@ -93,7 +93,7 @@ void WontCompile() {
+ method_to_const_cb.Run();
+ }
+
+-#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!std::is_pointer_v<base::NoRef *> || IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained() and document why it's safe.\""]
++#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!IsPointerV<base::NoRef \*> \|\| IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained\(\) and document why it's safe.\""]
+
+
+ // Method bound to non-refcounted object.
+@@ -106,7 +106,7 @@ void WontCompile() {
+ no_ref_cb.Run();
+ }
+
+-#elif defined(NCTEST_CONST_METHOD_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!std::is_pointer_v<base::NoRef *> || IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained() and document why it's safe.\""]
++#elif defined(NCTEST_CONST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!IsPointerV<base::NoRef \*> \|\| IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained\(\) and document why it's safe.\""]
+
+ // Const Method bound to non-refcounted object.
+ //
+@@ -118,6 +118,33 @@ void WontCompile() {
+ no_ref_const_cb.Run();
+ }
+
++#elif defined(NCTEST_METHOD_BIND_RAW_PTR_RECEIVER_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!IsPointerV<base::raw_ptr<base::NoRef, [^>]+>> \|\| IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained\(\) and document why it's safe.\""]
++
++
++// Method bound to non-refcounted object.
++//
++// We require refcounts unless you have Unretained().
++void WontCompile() {
++ NoRef no_ref;
++ raw_ptr<NoRef> rawptr(&no_ref);
++ RepeatingCallback<void()> no_ref_cb =
++ BindRepeating(&NoRef::VoidMethod0, rawptr);
++ no_ref_cb.Run();
++}
++
++#elif defined(NCTEST_CONST_METHOD_BIND_RAW_PTR_RECEIVER_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed due to requirement '!IsPointerV<base::raw_ptr<base::NoRef, [^>]+>> \|\| IsRefCountedType<base::NoRef, void>::value' \"Receivers may not be raw pointers. If using a raw pointer here is safe and has no lifetime concerns, use base::Unretained\(\) and document why it's safe.\""]
++
++// Const Method bound to non-refcounted object.
++//
++// We require refcounts unless you have Unretained().
++void WontCompile() {
++ NoRef no_ref;
++ raw_ptr<NoRef> rawptr(&no_ref);
++ RepeatingCallback<void()> no_ref_const_cb =
++ BindRepeating(&NoRef::VoidConstMethod0, rawptr);
++ no_ref_const_cb.Run();
++}
++
+ #elif defined(NCTEST_CONST_POINTER) // [r"static_assert failed.+?BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kCanBeForwardedToBoundFunctor.+?Type mismatch between bound argument and bound functor's parameter\."]
+ // Const argument used with non-const pointer parameter of same type.
+ //
+diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
+index 4d978e979863..639713cd6199 100644
+--- a/base/memory/raw_ptr.h
++++ b/base/memory/raw_ptr.h
+@@ -1051,6 +1051,37 @@ ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
+ return lhs.GetForComparison() >= rhs.GetForComparison();
+ }
+
++// Template helpers for working with T* or raw_ptr<T>.
++template <typename T>
++struct IsPointer : std::false_type {};
++
++template <typename T>
++struct IsPointer<T*> : std::true_type {};
++
++template <typename T, typename I>
++struct IsPointer<raw_ptr<T, I>> : std::true_type {};
++
++template <typename T>
++inline constexpr bool IsPointerV = IsPointer<T>::value;
++
++template <typename T>
++struct RemovePointer {
++ using type = T;
++};
++
++template <typename T>
++struct RemovePointer<T*> {
++ using type = T;
++};
++
++template <typename T, typename I>
++struct RemovePointer<raw_ptr<T, I>> {
++ using type = T;
++};
++
++template <typename T>
++using RemovePointerT = typename RemovePointer<T>::type;
++
+ } // namespace base
+
+ using base::raw_ptr;
+diff --git a/base/memory/raw_scoped_refptr_mismatch_checker.h b/base/memory/raw_scoped_refptr_mismatch_checker.h
+index 9e50458ec98b..7afae066fa3e 100644
+--- a/base/memory/raw_scoped_refptr_mismatch_checker.h
++++ b/base/memory/raw_scoped_refptr_mismatch_checker.h
+@@ -7,6 +7,7 @@
+
+ #include <type_traits>
+
++#include "base/memory/raw_ptr.h"
+ #include "base/template_util.h"
+
+ // It is dangerous to post a task with a T* argument where T is a subtype of
+@@ -35,8 +36,8 @@ struct IsRefCountedType<T,
+ // pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) type.
+ template <typename T>
+ struct NeedsScopedRefptrButGetsRawPtr
+- : conjunction<std::is_pointer<T>,
+- IsRefCountedType<std::remove_pointer_t<T>>> {
++ : conjunction<base::IsPointer<T>,
++ IsRefCountedType<base::RemovePointerT<T>>> {
+ static_assert(!std::is_reference<T>::value,
+ "NeedsScopedRefptrButGetsRawPtr requires non-reference type.");
+ };
+diff --git a/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_handler_unittest.cc b/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_handler_unittest.cc
+index d812d82a08c3..ee22b02bdbed 100644
+--- a/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_handler_unittest.cc
++++ b/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_handler_unittest.cc
+@@ -93,9 +93,7 @@ class PrivacySandboxDialogHandlerTest : public testing::Test {
+ content::TestWebUI* web_ui() { return web_ui_.get(); }
+ PrivacySandboxDialogHandler* handler() { return handler_.get(); }
+ TestingProfile* profile() { return &profile_; }
+- raw_ptr<MockPrivacySandboxDialogView> dialog_mock() {
+- return dialog_mock_.get();
+- }
++ MockPrivacySandboxDialogView* dialog_mock() { return dialog_mock_.get(); }
+ MockPrivacySandboxService* mock_privacy_sandbox_service() {
+ return mock_privacy_sandbox_service_;
+ }
+@@ -120,15 +118,18 @@ class PrivacySandboxConsentDialogHandlerTest
+ : public PrivacySandboxDialogHandlerTest {
+ protected:
+ std::unique_ptr<PrivacySandboxDialogHandler> CreateHandler() override {
++ // base::Unretained is safe because the created handler does not outlive the
++ // mock.
+ return std::make_unique<PrivacySandboxDialogHandler>(
+- base::BindOnce(&MockPrivacySandboxDialogView::Close, dialog_mock()),
++ base::BindOnce(&MockPrivacySandboxDialogView::Close,
++ base::Unretained(dialog_mock())),
+ base::BindOnce(&MockPrivacySandboxDialogView::ResizeNativeView,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ base::BindOnce(&MockPrivacySandboxDialogView::ShowNativeView,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ base::BindOnce(
+ &MockPrivacySandboxDialogView::OpenPrivacySandboxSettings,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ PrivacySandboxService::DialogType::kConsent);
+ }
+ };
+@@ -247,15 +248,18 @@ class PrivacySandboxNoticeDialogHandlerTest
+ : public PrivacySandboxDialogHandlerTest {
+ protected:
+ std::unique_ptr<PrivacySandboxDialogHandler> CreateHandler() override {
++ // base::Unretained is safe because the created handler does not outlive the
++ // mock.
+ return std::make_unique<PrivacySandboxDialogHandler>(
+- base::BindOnce(&MockPrivacySandboxDialogView::Close, dialog_mock()),
++ base::BindOnce(&MockPrivacySandboxDialogView::Close,
++ base::Unretained(dialog_mock())),
+ base::BindOnce(&MockPrivacySandboxDialogView::ResizeNativeView,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ base::BindOnce(&MockPrivacySandboxDialogView::ShowNativeView,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ base::BindOnce(
+ &MockPrivacySandboxDialogView::OpenPrivacySandboxSettings,
+- dialog_mock()),
++ base::Unretained(dialog_mock())),
+ PrivacySandboxService::DialogType::kNotice);
+ }
+ };
+diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
+index 2b85d7645980..cf57d375d0d3 100644
+--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
++++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
+@@ -505,10 +505,6 @@ void WebAppInstallFinalizer::SetWebAppManifestFieldsAndWriteData(
+ web_app_info.shortcuts_menu_icon_bitmaps;
+ IconsMap other_icon_bitmaps = web_app_info.other_icon_bitmaps;
+
+- auto write_icons_callback = base::BindOnce(
+- &WebAppIconManager::WriteData, icon_manager_, app_id,
+- std::move(icon_bitmaps), std::move(shortcuts_menu_icon_bitmaps),
+- std::move(other_icon_bitmaps));
+ auto write_translations_callback = base::BindOnce(
+ &WebAppInstallFinalizer::WriteTranslations,
+ weak_ptr_factory_.GetWeakPtr(), app_id, std::move(web_app_info));
+@@ -516,11 +512,12 @@ void WebAppInstallFinalizer::SetWebAppManifestFieldsAndWriteData(
+ base::BindOnce(&WebAppInstallFinalizer::CommitToSyncBridge,
+ weak_ptr_factory_.GetWeakPtr(), std::move(web_app));
+
+- std::move(write_icons_callback)
+- .Run(base::BindOnce(
+- std::move(write_translations_callback),
+- base::BindOnce(std::move(commit_to_sync_bridge_callback),
+- std::move(commit_callback))));
++ icon_manager_->WriteData(
++ app_id, std::move(icon_bitmaps), std::move(shortcuts_menu_icon_bitmaps),
++ std::move(other_icon_bitmaps),
++ base::BindOnce(std::move(write_translations_callback),
++ base::BindOnce(std::move(commit_to_sync_bridge_callback),
++ std::move(commit_callback))));
+ }
+
+ void WebAppInstallFinalizer::WriteTranslations(
+--
+2.37.0
+