diff --git a/browser/brave_wallet/BUILD.gn b/browser/brave_wallet/BUILD.gn index a05cf5f8d56..02c47ddbe31 100644 --- a/browser/brave_wallet/BUILD.gn +++ b/browser/brave_wallet/BUILD.gn @@ -89,6 +89,7 @@ source_set("brave_wallet_delegate") { "brave_wallet_service_delegate_impl.h", ] deps += [ + "//chrome/browser/notifications", "//chrome/browser/ui", "//chrome/browser/ui:browser_tab_strip", "//chrome/browser/ui/tabs:tab_strip", @@ -210,7 +211,6 @@ source_set("unit_tests") { "brave_wallet_hid_chooser_unittest.cc", "brave_wallet_tab_helper_unittest.cc", "ethereum_provider_impl_unittest.cc", - "notifications/wallet_notification_service_unittest.cc", "solana_provider_impl_unittest.cc", ] deps += [ diff --git a/browser/brave_wallet/brave_wallet_service_browsertest.cc b/browser/brave_wallet/brave_wallet_service_browsertest.cc index 18761f3d63c..65d860cc683 100644 --- a/browser/brave_wallet/brave_wallet_service_browsertest.cc +++ b/browser/brave_wallet/brave_wallet_service_browsertest.cc @@ -5,27 +5,43 @@ #include "brave/components/brave_wallet/browser/brave_wallet_service.h" -#include "base/memory/raw_ptr.h" +#include + +#include "base/command_line.h" #include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/bind.h" #include "base/test/mock_callback.h" +#include "base/test/run_until.h" #include "base/test/test_future.h" #include "brave/browser/brave_wallet/brave_wallet_service_factory.h" #include "brave/components/brave_wallet/browser/brave_wallet_service_observer_base.h" #include "brave/components/brave_wallet/browser/brave_wallet_utils.h" #include "brave/components/brave_wallet/browser/json_rpc_service.h" +#include "brave/components/brave_wallet/browser/keyring_service.h" +#include "brave/components/brave_wallet/browser/pref_names.h" #include "brave/components/brave_wallet/browser/test_utils.h" #include "brave/components/brave_wallet/browser/tx_service.h" #include "brave/components/brave_wallet/common/brave_wallet.mojom.h" #include "brave/components/constants/brave_paths.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/notifications/notification_handler.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/grit/brave_components_strings.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_mock_cert_verifier.h" +#include "content/public/test/test_navigation_observer.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" #include "url/origin.h" using base::test::TestFuture; @@ -72,10 +88,29 @@ class TestBraveWalletServiceObserver class BraveWalletServiceTest : public InProcessBrowserTest { public: BraveWalletServiceTest() - : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + : https_server_for_rpc_(net::EmbeddedTestServer::TYPE_HTTPS), + https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + InProcessBrowserTest::SetUpCommandLine(command_line); + mock_cert_verifier_.SetUpCommandLine(command_line); + } + + void SetUpInProcessBrowserTestFixture() override { + InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); + mock_cert_verifier_.SetUpInProcessBrowserTestFixture(); + } + + void TearDownInProcessBrowserTestFixture() override { + InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); + mock_cert_verifier_.TearDownInProcessBrowserTestFixture(); + } void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); + mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK); + notification_tester_ = std::make_unique( + browser()->profile()); base::FilePath test_data_dir; base::PathService::Get(brave::DIR_TEST_DATA, &test_data_dir); https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); @@ -102,6 +137,8 @@ class BraveWalletServiceTest : public InProcessBrowserTest { browser()->profile()); } + TxService* tx_service() { return wallet_service()->tx_service(); } + BraveWalletService* incognito_wallet_service() { if (!incognito_browser_) { incognito_browser_ = CreateIncognitoBrowser(browser()->profile()); @@ -116,7 +153,23 @@ class BraveWalletServiceTest : public InProcessBrowserTest { const net::EmbeddedTestServer* https_server() const { return &https_server_; } + std::vector GetWalletNotifications() { + return notification_tester_->GetDisplayedNotificationsForType( + NotificationHandler::Type::BRAVE_WALLET); + } + + void SimulateWalletNotificationClick(const std::string& notification_id) { + notification_tester_->SimulateClick(NotificationHandler::Type::BRAVE_WALLET, + notification_id, std::nullopt, + std::nullopt); + } + + protected: + net::EmbeddedTestServer https_server_for_rpc_; + private: + content::ContentMockCertVerifier mock_cert_verifier_; + std::unique_ptr notification_tester_; raw_ptr incognito_browser_ = nullptr; net::EmbeddedTestServer https_server_; }; @@ -178,6 +231,59 @@ IN_PROC_BROWSER_TEST_F(BraveWalletServiceTest, IsPrivateWindow) { TestIsPrivateWindow(wallet_service(), false); } +IN_PROC_BROWSER_TEST_F(BraveWalletServiceTest, DisplayTxNotification) { + AccountUtils account_utils(wallet_service()->keyring_service()); + account_utils.CreateWallet(kMnemonicDripCaution, kTestWalletPassword); + auto account = account_utils.EnsureEthAccount(0); + ASSERT_TRUE(account); + + const GURL expected_tx_url("chrome://wallet/crypto/accounts/" + + account->address + "/transactions"); + + const std::string tx_meta_id = "tx_meta_id"; + auto tx_info = mojom::TransactionInfo::New( + tx_meta_id, account->account_id.Clone(), "", + mojom::TxDataUnion::NewEthTxData( + mojom::TxData::New(mojom::kLocalhostChainId, "0x0", "0x1", "0x5208", + "0xbe862ad9abfe6f22bcb087716c7d89a26051f74c", + "0x0", std::vector())), + mojom::TransactionStatus::Confirmed, mojom::TransactionType::ETHSend, + std::vector(), std::vector(), + base::Milliseconds(0), base::Milliseconds(0), base::Milliseconds(0), + nullptr, mojom::kLocalhostChainId, std::nullopt, false, nullptr, nullptr); + tx_service()->OnTransactionStatusChanged(std::move(tx_info)); + + ASSERT_TRUE(base::test::RunUntil( + [&]() { return GetWalletNotifications().size() == 1u; })); + + auto notifications = GetWalletNotifications(); + ASSERT_EQ(notifications.size(), 1u); + const auto& notification = notifications.front(); + + EXPECT_EQ(notification.id(), tx_meta_id); + EXPECT_EQ(notification.title(), + l10n_util::GetStringUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_CONFIRMED)); + EXPECT_EQ(notification.message(), + l10n_util::GetStringFUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TEXT, + base::UTF8ToUTF16(account->name))); + EXPECT_EQ(notification.origin_url(), expected_tx_url); + EXPECT_TRUE(notification.rich_notification_data().remove_on_click); + EXPECT_EQ(notification.rich_notification_data().context_message, u" "); + + content::TestNavigationObserver nav_observer(expected_tx_url); + nav_observer.WatchExistingWebContents(); + nav_observer.StartWatchingNewWebContents(); + SimulateWalletNotificationClick(tx_meta_id); + nav_observer.Wait(); + EXPECT_EQ(browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL(), + expected_tx_url); +} + IN_PROC_BROWSER_TEST_F(BraveWalletServiceTest, IsolateTransactionInPrivateWindow) { AccountUtils account_utils(wallet_service()->keyring_service()); diff --git a/browser/brave_wallet/brave_wallet_service_delegate_impl.cc b/browser/brave_wallet/brave_wallet_service_delegate_impl.cc index b4f341d2beb..07b60c56281 100644 --- a/browser/brave_wallet/brave_wallet_service_delegate_impl.cc +++ b/browser/brave_wallet/brave_wallet_service_delegate_impl.cc @@ -10,18 +10,24 @@ #include "base/check.h" #include "base/functional/callback_helpers.h" +#include "base/strings/utf_string_conversions.h" #include "base/types/expected.h" #include "brave/components/brave_wallet/browser/brave_wallet_utils.h" #include "brave/components/brave_wallet/browser/permission_utils.h" #include "brave/components/constants/webui_url_constants.h" #include "brave/components/permissions/contexts/brave_wallet_permission_context.h" +#include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "components/grit/brave_components_strings.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" #include "url/gurl.h" #include "url/origin.h" @@ -50,6 +56,52 @@ void ClearWalletStoragePartition(content::BrowserContext* context, base::DoNothing()); } +std::u16string GetStatusTitle(brave_wallet::mojom::TransactionStatus status) { + switch (status) { + case brave_wallet::mojom::TransactionStatus::Confirmed: + return l10n_util::GetStringUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_CONFIRMED); + case brave_wallet::mojom::TransactionStatus::Error: + return l10n_util::GetStringUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_ERROR); + case brave_wallet::mojom::TransactionStatus::Dropped: + return l10n_util::GetStringUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_DROPPED); + default: + break; + } + + return std::u16string(); +} + +void DisplayTxNotificationImpl(content::BrowserContext* context, + brave_wallet::mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url) { + if (auto* notification_display_service = + NotificationDisplayServiceFactory::GetForProfile( + Profile::FromBrowserContext(context))) { + message_center::RichNotificationData notification_data; + notification_data.remove_on_click = true; + notification_data.context_message = + u" "; // Prevent origin from showing in the notification. + + auto notification = std::make_unique( + message_center::NOTIFICATION_TYPE_SIMPLE, tx_id, GetStatusTitle(status), + l10n_util::GetStringFUTF16( + IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TEXT, + base::UTF8ToUTF16(account_name)), + ui::ImageModel(), std::u16string(), tx_url, + message_center::NotifierId( + message_center::NotifierType::SYSTEM_COMPONENT, "service.wallet"), + notification_data, nullptr); + + notification_display_service->Display( + NotificationHandler::Type::BRAVE_WALLET, *notification, nullptr); + } +} + } // namespace BraveWalletServiceDelegateImpl::BraveWalletServiceDelegateImpl( @@ -194,4 +246,12 @@ void BraveWalletServiceDelegateImpl::ClearWalletUIStoragePartition() { ClearWalletStoragePartition(context_, GURL(kBraveUIWalletPanelURL)); } +void BraveWalletServiceDelegateImpl::DisplayTxNotification( + brave_wallet::mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url) { + DisplayTxNotificationImpl(context_, status, account_name, tx_id, tx_url); +} + } // namespace brave_wallet diff --git a/browser/brave_wallet/brave_wallet_service_delegate_impl.h b/browser/brave_wallet/brave_wallet_service_delegate_impl.h index af8bffdd5cf..567cae2ee07 100644 --- a/browser/brave_wallet/brave_wallet_service_delegate_impl.h +++ b/browser/brave_wallet/brave_wallet_service_delegate_impl.h @@ -11,7 +11,6 @@ #include #include "base/containers/flat_map.h" -#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "brave/browser/brave_wallet/brave_wallet_service_delegate_base.h" @@ -43,6 +42,7 @@ class BraveWalletServiceDelegateImpl : public BraveWalletServiceDelegateBase, static void SetActiveWebContentsForTesting( content::WebContents* web_contents); + // BraveWalletServiceDelegateBase: void IsExternalWalletInstalled(mojom::ExternalWalletType, IsExternalWalletInstalledCallback) override; void IsExternalWalletInitialized( @@ -56,6 +56,11 @@ class BraveWalletServiceDelegateImpl : public BraveWalletServiceDelegateBase, void ClearWalletUIStoragePartition() override; + void DisplayTxNotification(brave_wallet::mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url) override; + void AddObserver(BraveWalletServiceDelegate::Observer* observer) override; void RemoveObserver(BraveWalletServiceDelegate::Observer* observer) override; diff --git a/browser/brave_wallet/brave_wallet_service_unittest.cc b/browser/brave_wallet/brave_wallet_service_unittest.cc index d97d89985d3..af1cd9395b8 100644 --- a/browser/brave_wallet/brave_wallet_service_unittest.cc +++ b/browser/brave_wallet/brave_wallet_service_unittest.cc @@ -60,6 +60,7 @@ #include "content/public/test/browser_task_environment.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "ui/base/l10n/l10n_util.h" @@ -302,6 +303,22 @@ class TestBraveWalletServiceObserver observer_receiver_{this}; }; +class MockBraveWalletServiceDelegate : public BraveWalletServiceDelegate { + public: + MockBraveWalletServiceDelegate() = default; + ~MockBraveWalletServiceDelegate() override = default; + + MOCK_METHOD(void, + DisplayTxNotification, + (mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url), + (override)); + MOCK_METHOD(base::FilePath, GetWalletBaseDirectory, (), (override)); + MOCK_METHOD(bool, IsPrivateWindow, (), (override)); +}; + class BraveWalletServiceUnitTest : public testing::Test { public: BraveWalletServiceUnitTest() @@ -888,6 +905,11 @@ class BraveWalletServiceUnitTest : public testing::Test { AccountUtils GetAccountUtils() { return AccountUtils(keyring_service_); } + mojo::Receiver& + GetTxServiceObserverReceiver() { + return service_->tx_service_observer_receiver_; + } + content::BrowserTaskEnvironment task_environment_; network::TestURLLoaderFactory url_loader_factory_; TestingPrefServiceSimple local_state_; @@ -3430,4 +3452,56 @@ TEST_F(BraveWalletServiceUnitTest, GetNetworkForAccountOnActiveOrigin) { mojom::kCardanoTestnet); } +TEST_F(BraveWalletServiceUnitTest, DisplayTxNotification) { + SetupWallet(); + auto delegate = + std::make_unique>(); + auto* delegate_ptr = delegate.get(); + service_->SetDelegateForTesting(std::move(delegate)); + auto account = GetAccountUtils().EnsureEthAccount(0); + ASSERT_TRUE(account); + + const GURL expected_tx_url("chrome://wallet/crypto/accounts/" + + account->address + "/transactions"); + + struct TestCase { + mojom::TransactionStatus status; + uint32_t times_called; + }; + + std::vector test_cases = { + {mojom::TransactionStatus::Unapproved, 0}, + {mojom::TransactionStatus::Approved, 0}, + {mojom::TransactionStatus::Rejected, 0}, + {mojom::TransactionStatus::Submitted, 0}, + {mojom::TransactionStatus::Confirmed, 1}, + {mojom::TransactionStatus::Error, 1}, + {mojom::TransactionStatus::Dropped, 1}, + {mojom::TransactionStatus::Signed, 0}, + }; + + for (auto test_case : test_cases) { + SCOPED_TRACE(test_case.status); + auto tx_info = mojom::TransactionInfo::New( + "tx_meta_id", account->account_id.Clone(), "", + mojom::TxDataUnion::NewEthTxData( + mojom::TxData::New(mojom::kLocalhostChainId, "0x0", "0x1", "0x5208", + "0xbe862ad9abfe6f22bcb087716c7d89a26051f74c", + "0x0", std::vector())), + test_case.status, mojom::TransactionType::ETHSend, + std::vector(), std::vector(), + base::Milliseconds(0), base::Milliseconds(0), base::Milliseconds(0), + nullptr, mojom::kLocalhostChainId, std::nullopt, false, nullptr, + nullptr); + + EXPECT_CALL(*delegate_ptr, + DisplayTxNotification(test_case.status, account->name, + tx_info->id, expected_tx_url)) + .Times(test_case.times_called); + tx_service_->OnTransactionStatusChanged(tx_info.Clone()); + GetTxServiceObserverReceiver().FlushForTesting(); + testing::Mock::VerifyAndClearExpectations(delegate_ptr); + } +} + } // namespace brave_wallet diff --git a/browser/brave_wallet/notifications/BUILD.gn b/browser/brave_wallet/notifications/BUILD.gn new file mode 100644 index 00000000000..2e6f8d46913 --- /dev/null +++ b/browser/brave_wallet/notifications/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2026 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//brave/components/brave_wallet/common/buildflags/buildflags.gni") + +assert(enable_brave_wallet) +assert(!is_android) + +source_set("notifications") { + sources = [ + "brave_wallet_notification_handler.cc", + "brave_wallet_notification_handler.h", + ] + + deps = [ + "//brave/browser/brave_wallet", + "//brave/components/brave_wallet/browser", + "//chrome/browser/ui", + "//chrome/browser/ui/browser_window", + ] + + public_deps = [ + "//base", + "//chrome/browser/notifications", + ] +} diff --git a/browser/brave_wallet/notifications/brave_wallet_notification_handler.cc b/browser/brave_wallet/notifications/brave_wallet_notification_handler.cc new file mode 100644 index 00000000000..85d46c3c7cb --- /dev/null +++ b/browser/brave_wallet/notifications/brave_wallet_notification_handler.cc @@ -0,0 +1,51 @@ +/* Copyright (c) 2026 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/brave_wallet/notifications/brave_wallet_notification_handler.h" + +#include + +#include "brave/browser/ui/brave_pages.h" +#include "build/build_config.h" +#include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h" +#include "url/gurl.h" + +namespace brave_wallet { + +BraveWalletNotificationHandler::BraveWalletNotificationHandler(Profile& profile) + : profile_(profile) {} + +BraveWalletNotificationHandler::~BraveWalletNotificationHandler() = default; + +void BraveWalletNotificationHandler::OnClick( + Profile* profile, + const GURL& origin, + const std::string& notification_id, + const std::optional& action_index, + const std::optional& reply, + base::OnceClosure completed_closure) { + BrowserWindowInterface* browser = nullptr; + ForEachCurrentBrowserWindowInterfaceOrderedByActivation( + [profile, &browser](BrowserWindowInterface* bwi) { + if (bwi->GetProfile() == profile) { + browser = bwi; + return false; + } + return true; + }); + + if (browser) { + brave::ShowBraveWalletTxNotificationUrl(browser, origin); + } + + std::move(completed_closure).Run(); +} + +} // namespace brave_wallet diff --git a/browser/brave_wallet/notifications/brave_wallet_notification_handler.h b/browser/brave_wallet/notifications/brave_wallet_notification_handler.h new file mode 100644 index 00000000000..c6cf3c6d25d --- /dev/null +++ b/browser/brave_wallet/notifications/brave_wallet_notification_handler.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2026 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_BRAVE_WALLET_NOTIFICATION_HANDLER_H_ +#define BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_BRAVE_WALLET_NOTIFICATION_HANDLER_H_ + +#include +#include + +#include "base/functional/callback_forward.h" +#include "base/memory/raw_ref.h" +#include "chrome/browser/notifications/notification_handler.h" + +class GURL; +class Profile; + +namespace brave_wallet { + +class BraveWalletNotificationHandler : public NotificationHandler { + public: + explicit BraveWalletNotificationHandler(Profile& profile); + + BraveWalletNotificationHandler(const BraveWalletNotificationHandler&) = + delete; + BraveWalletNotificationHandler& operator=( + const BraveWalletNotificationHandler&) = delete; + BraveWalletNotificationHandler(BraveWalletNotificationHandler&&) = delete; + BraveWalletNotificationHandler& operator=(BraveWalletNotificationHandler&&) = + delete; + + ~BraveWalletNotificationHandler() override; + + // NotificationHandler: + void OnClick(Profile* profile, + const GURL& origin, + const std::string& notification_id, + const std::optional& action_index, + const std::optional& reply, + base::OnceClosure completed_closure) override; + + private: + const raw_ref profile_; +}; + +} // namespace brave_wallet + +#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_BRAVE_WALLET_NOTIFICATION_HANDLER_H_ diff --git a/browser/brave_wallet/notifications/sources.gni b/browser/brave_wallet/notifications/sources.gni deleted file mode 100644 index 81f274bc6fb..00000000000 --- a/browser/brave_wallet/notifications/sources.gni +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2022 The Brave Authors. All rights reserved. -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. - -brave_browser_brave_wallet_deps = - [ "//brave/components/brave_wallet/browser:pref_names" ] - -brave_browser_brave_wallet_sources = [] -if (!is_android) { - brave_browser_brave_wallet_sources += [ - "//brave/browser/brave_wallet/notifications/wallet_notification_service.cc", - "//brave/browser/brave_wallet/notifications/wallet_notification_service.h", - "//brave/browser/brave_wallet/notifications/wallet_notification_service_factory.cc", - "//brave/browser/brave_wallet/notifications/wallet_notification_service_factory.h", - ] -} diff --git a/browser/brave_wallet/notifications/wallet_notification_service.cc b/browser/brave_wallet/notifications/wallet_notification_service.cc deleted file mode 100644 index ce148ed1d05..00000000000 --- a/browser/brave_wallet/notifications/wallet_notification_service.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#include "brave/browser/brave_wallet/notifications/wallet_notification_service.h" - -#include -#include - -#include "base/strings/utf_string_conversions.h" -#include "brave/components/brave_wallet/browser/brave_wallet_service.h" -#include "brave/components/brave_wallet/browser/tx_service.h" -#include "chrome/browser/notifications/notification_display_service.h" -#include "chrome/browser/notifications/notification_display_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "components/grit/brave_components_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/image_model.h" -#include "ui/message_center/public/cpp/notification.h" -#include "ui/message_center/public/cpp/notification_types.h" -#include "ui/message_center/public/cpp/notifier_id.h" - -namespace { -int GetStatusTitle(brave_wallet::mojom::TransactionStatus status) { - switch (status) { - case brave_wallet::mojom::TransactionStatus::Confirmed: - return IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_CONFIRMED; - case brave_wallet::mojom::TransactionStatus::Error: - return IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_ERROR; - case brave_wallet::mojom::TransactionStatus::Dropped: - return IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TITLE_DROPPED; - default: - break; - } - return -1; -} - -std::unique_ptr CreateMessageCenterNotification( - const std::u16string& title, - const std::u16string& body, - const std::string& uuid, - const GURL& link) { - message_center::RichNotificationData notification_data; - // hack to prevent origin from showing in the notification - notification_data.context_message = u" "; - auto notification = std::make_unique( - message_center::NOTIFICATION_TYPE_SIMPLE, uuid, title, body, - ui::ImageModel(), std::u16string(), link, - message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT, - "service.wallet"), - notification_data, nullptr); - - return notification; -} - -void PushNotification(content::BrowserContext* context, - const std::string& uuid, - const std::string& from, - const std::u16string& title, - const std::u16string& body) { - auto notification = CreateMessageCenterNotification( - title, body, uuid, - GURL("brave://wallet/crypto/accounts/" + from + "#" + uuid)); - auto* profile = Profile::FromBrowserContext(context); - NotificationDisplayServiceFactory::GetForProfile(profile)->Display( - NotificationHandler::Type::ANNOUNCEMENT, *notification, nullptr); -} - -} // namespace - -namespace brave_wallet { - -WalletNotificationService::WalletNotificationService( - BraveWalletService* brave_wallet_service, - content::BrowserContext* context) - : brave_wallet_service_(brave_wallet_service), context_(context) { - if (brave_wallet_service_) { - brave_wallet_service_->tx_service()->AddObserver( - tx_observer_receiver_.BindNewPipeAndPassRemote()); - } -} - -WalletNotificationService::~WalletNotificationService() = default; - -bool WalletNotificationService::ShouldDisplayUserNotification( - mojom::TransactionStatus status) { - return (status == mojom::TransactionStatus::Confirmed || - status == mojom::TransactionStatus::Error || - status == mojom::TransactionStatus::Dropped); -} - -void WalletNotificationService::DisplayUserNotification( - mojom::TransactionStatus status, - const std::string& address, - const std::string& tx_id) { - PushNotification(context_, tx_id, address, - l10n_util::GetStringUTF16(GetStatusTitle(status)), - l10n_util::GetStringFUTF16( - IDS_WALLET_TRANSACTION_STATUS_UPDATE_MESSAGE_TEXT, - base::UTF8ToUTF16(address))); -} - -void WalletNotificationService::OnTransactionStatusChanged( - mojom::TransactionInfoPtr tx_info) { - if (ShouldDisplayUserNotification(tx_info->tx_status)) { - auto account = brave_wallet_service_->keyring_service()->FindAccount( - tx_info->from_account_id); - if (!account) { - return; - } - - DisplayUserNotification(tx_info->tx_status, account->name, tx_info->id); - } -} - -} // namespace brave_wallet diff --git a/browser/brave_wallet/notifications/wallet_notification_service.h b/browser/brave_wallet/notifications/wallet_notification_service.h deleted file mode 100644 index 3f6cea7b5b3..00000000000 --- a/browser/brave_wallet/notifications/wallet_notification_service.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_H_ -#define BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_H_ - -#include - -#include "base/memory/raw_ptr.h" -#include "brave/components/brave_wallet/common/brave_wallet.mojom.h" -#include "components/keyed_service/core/keyed_service.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace content { -class BrowserContext; -} // namespace content - -namespace brave_wallet { -class BraveWalletService; - -class WalletNotificationService : public KeyedService, - public mojom::TxServiceObserver { - public: - WalletNotificationService(BraveWalletService* brave_wallet_service, - content::BrowserContext* context); - ~WalletNotificationService() override; - WalletNotificationService(const WalletNotificationService&) = delete; - WalletNotificationService operator=(const WalletNotificationService&) = - delete; - - // mojom::TxServiceObserver - void OnNewUnapprovedTx(mojom::TransactionInfoPtr tx_info) override {} - void OnUnapprovedTxUpdated(mojom::TransactionInfoPtr tx_info) override {} - void OnTransactionStatusChanged(mojom::TransactionInfoPtr tx_info) override; - void OnTxServiceReset() override {} - - private: - friend class WalletNotificationServiceUnitTest; - - bool ShouldDisplayUserNotification(mojom::TransactionStatus status); - void DisplayUserNotification(mojom::TransactionStatus status, - const std::string& address, - const std::string& tx_id); - - raw_ptr brave_wallet_service_; - raw_ptr context_; - mojo::Receiver tx_observer_receiver_{this}; -}; - -} // namespace brave_wallet - -#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_H_ diff --git a/browser/brave_wallet/notifications/wallet_notification_service_factory.cc b/browser/brave_wallet/notifications/wallet_notification_service_factory.cc deleted file mode 100644 index 61af8750cad..00000000000 --- a/browser/brave_wallet/notifications/wallet_notification_service_factory.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#include "brave/browser/brave_wallet/notifications/wallet_notification_service_factory.h" - -#include - -#include "base/no_destructor.h" -#include "brave/browser/brave_wallet/brave_wallet_context_utils.h" -#include "brave/browser/brave_wallet/brave_wallet_service_factory.h" -#include "brave/browser/brave_wallet/notifications/wallet_notification_service.h" -#include "chrome/browser/notifications/notification_display_service_factory.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" - -namespace brave_wallet { - -// static -WalletNotificationServiceFactory* -WalletNotificationServiceFactory::GetInstance() { - static base::NoDestructor instance; - return instance.get(); -} - -WalletNotificationServiceFactory::WalletNotificationServiceFactory() - : BrowserContextKeyedServiceFactory( - "WalletNotificationService", - BrowserContextDependencyManager::GetInstance()) { - DependsOn(NotificationDisplayServiceFactory::GetInstance()); - DependsOn(brave_wallet::BraveWalletServiceFactory::GetInstance()); -} - -WalletNotificationServiceFactory::~WalletNotificationServiceFactory() = default; - -std::unique_ptr -WalletNotificationServiceFactory::BuildServiceInstanceForBrowserContext( - content::BrowserContext* context) const { - return std::make_unique( - BraveWalletServiceFactory::GetServiceForContext(context), context); -} - -// static -WalletNotificationService* -WalletNotificationServiceFactory::GetServiceForContext( - content::BrowserContext* context) { - if (!IsAllowedForContext(context)) { - return nullptr; - } - return static_cast( - GetInstance()->GetServiceForBrowserContext(context, true)); -} - -} // namespace brave_wallet diff --git a/browser/brave_wallet/notifications/wallet_notification_service_factory.h b/browser/brave_wallet/notifications/wallet_notification_service_factory.h deleted file mode 100644 index 294d823c714..00000000000 --- a/browser/brave_wallet/notifications/wallet_notification_service_factory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_FACTORY_H_ -#define BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_FACTORY_H_ - -#include - -#include "brave/browser/brave_wallet/notifications/wallet_notification_service.h" -#include "brave/components/brave_wallet/common/buildflags/buildflags.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -static_assert(BUILDFLAG(ENABLE_BRAVE_WALLET)); -namespace base { -template -class NoDestructor; -} // namespace base - -namespace brave_wallet { - -// Singleton that owns all WalletNotificationService and associates them with -// BrowserContext. -class WalletNotificationServiceFactory - : public BrowserContextKeyedServiceFactory { - public: - WalletNotificationServiceFactory(const WalletNotificationServiceFactory&) = - delete; - WalletNotificationServiceFactory& operator=( - const WalletNotificationServiceFactory&) = delete; - - static WalletNotificationServiceFactory* GetInstance(); - static WalletNotificationService* GetServiceForContext( - content::BrowserContext* context); - - private: - friend base::NoDestructor; - - WalletNotificationServiceFactory(); - ~WalletNotificationServiceFactory() override; - - // BrowserContextKeyedServiceFactory: - std::unique_ptr BuildServiceInstanceForBrowserContext( - content::BrowserContext* context) const override; -}; - -} // namespace brave_wallet - -#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_FACTORY_H_ diff --git a/browser/brave_wallet/notifications/wallet_notification_service_unittest.cc b/browser/brave_wallet/notifications/wallet_notification_service_unittest.cc deleted file mode 100644 index 3e0de9da09f..00000000000 --- a/browser/brave_wallet/notifications/wallet_notification_service_unittest.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#include "brave/browser/brave_wallet/notifications/wallet_notification_service.h" - -#include -#include -#include -#include - -#include "base/files/scoped_temp_dir.h" -#include "brave/components/brave_wallet/browser/brave_wallet_service.h" -#include "brave/components/brave_wallet/browser/eth_transaction.h" -#include "brave/components/brave_wallet/browser/eth_tx_meta.h" -#include "brave/components/brave_wallet/browser/keyring_service.h" -#include "brave/components/brave_wallet/browser/pref_names.h" -#include "brave/components/brave_wallet/browser/test_utils.h" -#include "brave/components/brave_wallet/browser/tx_service.h" -#include "brave/components/brave_wallet/common/brave_wallet.mojom.h" -#include "chrome/browser/notifications/notification_display_service_tester.h" -#include "chrome/test/base/testing_profile.h" -#include "components/prefs/testing_pref_service.h" -#include "content/public/test/browser_task_environment.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace brave_wallet { - -class WalletNotificationServiceUnitTest : public testing::Test { - public: - WalletNotificationServiceUnitTest() - : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} - - void SetUp() override { - RegisterLocalStatePrefs(local_state_.registry()); - RegisterLocalStatePrefsForMigration(local_state_.registry()); - - brave_wallet_service_ = std::make_unique( - url_loader_factory_.GetSafeWeakWrapper(), - TestBraveWalletServiceDelegate::Create(), prefs(), local_state()); - - notification_service_ = std::make_unique( - brave_wallet_service_.get(), profile()); - tester_ = std::make_unique(profile()); - GetAccountUtils().CreateWallet(kMnemonicDivideCruise, kTestWalletPassword); - } - Profile* profile() { return &profile_; } - PrefService* prefs() { return profile_.GetPrefs(); } - PrefService* local_state() { return &local_state_; } - - AccountUtils GetAccountUtils() { - return AccountUtils(brave_wallet_service_->keyring_service()); - } - - mojom::AccountIdPtr EthAccount(size_t index) { - return GetAccountUtils().EnsureEthAccount(index)->account_id->Clone(); - } - - bool ShouldDisplayNotifications(mojom::TransactionStatus status) { - return notification_service_->ShouldDisplayUserNotification(status); - } - - bool WasNotificationDisplayedOnStatusChange(mojom::TransactionStatus status) { - std::unique_ptr tx = std::make_unique( - *EthTransaction::FromTxData(mojom::TxData::New( - mojom::kMainnetChainId, "0x01", "0x4a817c800", "0x5208", - "0x3535353535353535353535353535353535353535", "0x0de0b6b3a7640000", - std::vector()))); - EthTxMeta meta(EthAccount(0), std::move(tx)); - meta.set_status(status); - notification_service_->OnTransactionStatusChanged(meta.ToTransactionInfo()); - auto notification = tester_->GetNotification(meta.id()); - tester_->RemoveAllNotifications(NotificationHandler::Type::ANNOUNCEMENT, - true /* by_user */); - return notification.has_value(); - } - - private: - content::BrowserTaskEnvironment task_environment_; - base::ScopedTempDir temp_dir_; - std::unique_ptr tester_; - TestingProfile profile_; - TestingPrefServiceSimple local_state_; - network::TestURLLoaderFactory url_loader_factory_; - std::unique_ptr brave_wallet_service_; - std::unique_ptr notification_service_; -}; - -TEST_F(WalletNotificationServiceUnitTest, ShouldShowNotifications) { - EXPECT_TRUE(ShouldDisplayNotifications(mojom::TransactionStatus::Confirmed)); - EXPECT_TRUE(ShouldDisplayNotifications(mojom::TransactionStatus::Error)); - EXPECT_TRUE(ShouldDisplayNotifications(mojom::TransactionStatus::Dropped)); - - EXPECT_FALSE(ShouldDisplayNotifications(mojom::TransactionStatus::Approved)); - EXPECT_FALSE(ShouldDisplayNotifications(mojom::TransactionStatus::Rejected)); - EXPECT_FALSE(ShouldDisplayNotifications(mojom::TransactionStatus::Submitted)); -} - -TEST_F(WalletNotificationServiceUnitTest, TransactionStatusChanged) { - EXPECT_TRUE(WasNotificationDisplayedOnStatusChange( - mojom::TransactionStatus::Confirmed)); - EXPECT_TRUE( - WasNotificationDisplayedOnStatusChange(mojom::TransactionStatus::Error)); - EXPECT_TRUE(WasNotificationDisplayedOnStatusChange( - mojom::TransactionStatus::Dropped)); - - EXPECT_FALSE(WasNotificationDisplayedOnStatusChange( - mojom::TransactionStatus::Approved)); - EXPECT_FALSE(WasNotificationDisplayedOnStatusChange( - mojom::TransactionStatus::Rejected)); - EXPECT_FALSE(WasNotificationDisplayedOnStatusChange( - mojom::TransactionStatus::Submitted)); -} - -} // namespace brave_wallet diff --git a/browser/browser_context_keyed_service_factories.cc b/browser/browser_context_keyed_service_factories.cc index 5b45cd6184d..2aab2a421f3 100644 --- a/browser/browser_context_keyed_service_factories.cc +++ b/browser/browser_context_keyed_service_factories.cc @@ -106,7 +106,6 @@ #if BUILDFLAG(ENABLE_BRAVE_WALLET) #include "brave/browser/brave_wallet/brave_wallet_service_factory.h" -#include "brave/browser/brave_wallet/notifications/wallet_notification_service_factory.h" #endif #if BUILDFLAG(ENABLE_BRAVE_NEWS) @@ -169,9 +168,6 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { #endif #if BUILDFLAG(ENABLE_BRAVE_WALLET) -#if !BUILDFLAG(IS_ANDROID) - brave_wallet::WalletNotificationServiceFactory::GetInstance(); -#endif brave_wallet::BraveWalletServiceFactory::GetInstance(); #endif diff --git a/browser/notifications/BUILD.gn b/browser/notifications/BUILD.gn index 118a725b6ff..84267edc514 100644 --- a/browser/notifications/BUILD.gn +++ b/browser/notifications/BUILD.gn @@ -4,6 +4,7 @@ # You can obtain one at https://mozilla.org/MPL/2.0/. import("//brave/components/brave_ads/buildflags/buildflags.gni") +import("//brave/components/brave_wallet/common/buildflags/buildflags.gni") assert(enable_brave_ads) diff --git a/browser/sources.gni b/browser/sources.gni index b0f4d14f46a..5fe6ad8b14e 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -63,7 +63,6 @@ if (enable_brave_rewards) { if (enable_brave_wallet) { import("//brave/browser/brave_wallet/android/sources.gni") - import("//brave/browser/brave_wallet/notifications/sources.gni") } if (enable_playlist) { @@ -355,6 +354,10 @@ if (enable_brave_wallet) { "//brave/components/decentralized_dns/content", "//brave/components/decentralized_dns/core", ] + if (!is_android) { + brave_chrome_browser_deps += + [ "//brave/browser/brave_wallet/notifications" ] + } } if (enable_email_aliases) { @@ -767,11 +770,6 @@ brave_chrome_browser_deps += brave_browser_webcompat_reporter_deps brave_chrome_browser_deps += brave_chromium_src_chrome_browser_deps brave_chrome_browser_deps += brave_chromium_src_chrome_browser_prefs_deps -if (enable_brave_wallet) { - brave_chrome_browser_sources += brave_browser_brave_wallet_sources - brave_chrome_browser_deps += brave_browser_brave_wallet_deps -} - brave_chrome_browser_ui_allow_circular_includes_from = [ "//brave/browser/ui" ] brave_chrome_browser_ui_allow_circular_includes_from += brave_ui_allow_circular_includes_from diff --git a/browser/ui/brave_pages.cc b/browser/ui/brave_pages.cc index 3fd8b9f3d40..ad197550b12 100644 --- a/browser/ui/brave_pages.cc +++ b/browser/ui/brave_pages.cc @@ -7,7 +7,6 @@ #include -#include "base/strings/strcat.h" #include "brave/browser/ui/webui/webcompat_reporter/webcompat_reporter_dialog.h" #include "brave/components/brave_talk/buildflags/buildflags.h" #include "brave/components/constants/webui_url_constants.h" @@ -76,6 +75,7 @@ void ShowWebcompatReporter(Browser* browser) { web_contents, webcompat_reporter::UISource::kAppMenu); } +#if BUILDFLAG(ENABLE_BRAVE_WALLET) void ShowBraveWallet(Browser* browser) { ShowSingletonTabOverwritingNTP(browser, GURL(kBraveUIWalletURL)); } @@ -84,20 +84,21 @@ void ShowBraveWalletOnboarding(Browser* browser) { ShowSingletonTabOverwritingNTP(browser, GURL(kBraveUIWalletOnboardingURL)); } +void ShowBraveWalletTxNotificationUrl(BrowserWindowInterface* browser, + GURL url) { + if (url.GetWithEmptyPath() != GURL(kBraveUIWalletURL)) { + return; + } + ShowSingletonTabOverwritingNTP(browser, url); +} + void ShowBraveWalletAccountCreation(Browser* browser, std::string_view coin_name) { ShowSingletonTabOverwritingNTP( browser, GURL(base::StrCat({kBraveUIWalletAccountCreationURL, coin_name}))); } - -void ShowExtensionSettings(Browser* browser) { - ShowSingletonTabOverwritingNTP(browser, GURL(kExtensionSettingsURL)); -} - -void ShowWalletSettings(Browser* browser) { - ShowSingletonTabOverwritingNTP(browser, GURL(kWalletSettingsURL)); -} +#endif void ShowAppsPage(Browser* browser) { ShowSingletonTabOverwritingNTP(browser, GURL(chrome::kChromeUIAppsURL)); diff --git a/browser/ui/brave_pages.h b/browser/ui/brave_pages.h index 870f089f920..7167a1eacae 100644 --- a/browser/ui/brave_pages.h +++ b/browser/ui/brave_pages.h @@ -10,20 +10,26 @@ #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/brave_talk/buildflags/buildflags.h" +#include "brave/components/brave_wallet/common/buildflags/buildflags.h" class Browser; +class BrowserWindowInterface; +class GURL; namespace brave { void ShowBraveAdblock(Browser* browser); void ShowWebcompatReporter(Browser* browser); void ShowBraveRewards(Browser* browser); +#if BUILDFLAG(ENABLE_BRAVE_WALLET) void ShowBraveWallet(Browser* browser); void ShowBraveWalletOnboarding(Browser* browser); +void ShowBraveWalletTxNotificationUrl(BrowserWindowInterface* browser, + GURL url); void ShowBraveWalletAccountCreation(Browser* browser, std::string_view coin_name); +#endif void ShowExtensionSettings(Browser* browser); -void ShowWalletSettings(Browser* browser); void ShowSync(Browser* browser); void ShowBraveNewsConfigure(Browser* browser); void ShowShortcutsPage(Browser* browser); diff --git a/chromium_src/chrome/browser/notifications/DEPS b/chromium_src/chrome/browser/notifications/DEPS index 600c3abf4bf..638f823c4cd 100644 --- a/chromium_src/chrome/browser/notifications/DEPS +++ b/chromium_src/chrome/browser/notifications/DEPS @@ -1,5 +1,6 @@ specific_include_rules = { "notification_display_service_impl\.cc": [ "+brave/components/brave_ads/buildflags/buildflags.h", + "+brave/components/brave_wallet/common/buildflags/buildflags.h", ], } diff --git a/chromium_src/chrome/browser/notifications/notification_display_service_impl.cc b/chromium_src/chrome/browser/notifications/notification_display_service_impl.cc index 951ee9344a7..d94ce48303c 100644 --- a/chromium_src/chrome/browser/notifications/notification_display_service_impl.cc +++ b/chromium_src/chrome/browser/notifications/notification_display_service_impl.cc @@ -4,10 +4,13 @@ * You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "brave/components/brave_ads/buildflags/buildflags.h" +#include "brave/components/brave_wallet/common/buildflags/buildflags.h" +#include "build/build_config.h" #if BUILDFLAG(ENABLE_BRAVE_ADS) -#include "brave/browser/notifications/ads_notification_handler.h" +#include "brave/browser/notifications/ads_notification_handler.h" // IWYU pragma: keep +// CHROMIUM_SRC_INTERNAL_USE #define BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER \ AddNotificationHandler( \ NotificationHandler::Type::BRAVE_ADS, \ @@ -16,5 +19,24 @@ #define BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER #endif // BUILDFLAG(ENABLE_BRAVE_ADS) +#if BUILDFLAG(ENABLE_BRAVE_WALLET) && !BUILDFLAG(IS_ANDROID) +#include "brave/browser/brave_wallet/notifications/brave_wallet_notification_handler.h" // IWYU pragma: keep + +// CHROMIUM_SRC_INTERNAL_USE +#define BRAVE_ADD_BRAVE_WALLET_NOTIFICATION_HANDLER \ + AddNotificationHandler( \ + NotificationHandler::Type::BRAVE_WALLET, \ + std::make_unique( \ + *profile)); +#else +#define BRAVE_ADD_BRAVE_WALLET_NOTIFICATION_HANDLER +#endif // BUILDFLAG(ENABLE_BRAVE_WALLET) && !BUILDFLAG(IS_ANDROID) + +#define BRAVE_NOTIFICATION_DISPLAY_SERVICE_IMPL_CONSTRUCTOR \ + BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER; \ + BRAVE_ADD_BRAVE_WALLET_NOTIFICATION_HANDLER + #include #undef BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER +#undef BRAVE_ADD_BRAVE_WALLET_NOTIFICATION_HANDLER +#undef BRAVE_NOTIFICATION_DISPLAY_SERVICE_IMPL_CONSTRUCTOR diff --git a/chromium_src/chrome/browser/notifications/notification_handler_impl.h b/chromium_src/chrome/browser/notifications/notification_handler_impl.h index 2b347154cbf..47d23ef9491 100644 --- a/chromium_src/chrome/browser/notifications/notification_handler_impl.h +++ b/chromium_src/chrome/browser/notifications/notification_handler_impl.h @@ -27,7 +27,8 @@ class NotificationHandler : public NotificationHandler_ChromiumImpl { NOTIFICATIONS_MUTED = 10, TAILORED_SECURITY = 11, DEFAULT_BROWSER_CHANGED = 12, - MAX = DEFAULT_BROWSER_CHANGED, + BRAVE_WALLET = 13, + MAX = BRAVE_WALLET, }; static_assert( diff --git a/components/brave_wallet/browser/BUILD.gn b/components/brave_wallet/browser/BUILD.gn index 3688507387f..4b6a8b0247f 100644 --- a/components/brave_wallet/browser/BUILD.gn +++ b/components/brave_wallet/browser/BUILD.gn @@ -270,6 +270,7 @@ static_library("browser") { "tx_meta.h", "tx_service.cc", "tx_service.h", + "tx_service_observer_base.h", "tx_state_manager.cc", "tx_state_manager.h", "tx_storage.cc", diff --git a/components/brave_wallet/browser/brave_wallet_service.cc b/components/brave_wallet/browser/brave_wallet_service.cc index 58f50889e64..a12371c44ee 100644 --- a/components/brave_wallet/browser/brave_wallet_service.cc +++ b/components/brave_wallet/browser/brave_wallet_service.cc @@ -62,6 +62,22 @@ namespace { inline constexpr char kZCashDataFolderName[] = "zcash_data"; +bool ShouldDisplayTxNotification(mojom::TransactionStatus status) { + return (status == mojom::TransactionStatus::Confirmed || + status == mojom::TransactionStatus::Error || + status == mojom::TransactionStatus::Dropped); +} + +GURL GetTxNotificationUrl(const mojom::AccountInfoPtr& account) { + // Matches `makeAccountRoute` in brave_wallet_routes.ts + auto account_route_entry = account->address.empty() + ? account->account_id->unique_key + : account->address; + + return GURL(base::StrCat({"chrome://wallet/crypto/accounts/", + account_route_entry, "/transactions"})); +} + bool AccountMatchesCoinAndChain(const mojom::AccountId& account_id, mojom::CoinType coin, const std::string& chain_id) { @@ -272,6 +288,8 @@ BraveWalletService::BraveWalletService( &BraveWalletService::OnWalletReset, weak_ptr_factory_.GetWeakPtr())); keyring_service_->AddObserver( keyring_observer_receiver_.BindNewPipeAndPassRemote()); + tx_service_->AddObserver( + tx_service_observer_receiver_.BindNewPipeAndPassRemote()); DCHECK(profile_prefs_); @@ -1411,6 +1429,21 @@ void BraveWalletService::WalletRestored() { account_discovery_manager_->StartDiscovery(); } +void BraveWalletService::OnTransactionStatusChanged( + mojom::TransactionInfoPtr tx_info) { + if (!ShouldDisplayTxNotification(tx_info->tx_status)) { + return; + } + + auto account = keyring_service()->FindAccount(tx_info->from_account_id); + if (!account) { + return; + } + + delegate_->DisplayTxNotification(tx_info->tx_status, account->name, + tx_info->id, GetTxNotificationUrl(account)); +} + void BraveWalletService::OnDiscoverAssetsStarted() { for (const auto& observer : observers_) { observer->OnDiscoverAssetsStarted(); @@ -2164,4 +2197,9 @@ void BraveWalletService::OnWalletReset() { account_discovery_manager_.reset(); } +void BraveWalletService::SetDelegateForTesting( // IN-TEST + std::unique_ptr delegate) { + delegate_ = std::move(delegate); +} + } // namespace brave_wallet diff --git a/components/brave_wallet/browser/brave_wallet_service.h b/components/brave_wallet/browser/brave_wallet_service.h index d205b268ef6..2d62e1ad027 100644 --- a/components/brave_wallet/browser/brave_wallet_service.h +++ b/components/brave_wallet/browser/brave_wallet_service.h @@ -23,8 +23,10 @@ #include "brave/components/brave_wallet/browser/brave_wallet_p3a.h" #include "brave/components/brave_wallet/browser/brave_wallet_service_delegate.h" #include "brave/components/brave_wallet/browser/cardano/cardano_wallet_service.h" +#include "brave/components/brave_wallet/browser/keyring_service_observer_base.h" #include "brave/components/brave_wallet/browser/polkadot/polkadot_wallet_service.h" #include "brave/components/brave_wallet/browser/simple_hash_client.h" +#include "brave/components/brave_wallet/browser/tx_service_observer_base.h" #include "brave/components/brave_wallet/browser/zcash/zcash_wallet_service.h" #include "brave/components/brave_wallet/common/brave_wallet.mojom.h" #include "brave/components/brave_wallet/common/buildflags/buildflags.h" @@ -63,6 +65,7 @@ struct PendingGetEncryptPublicKeyRequest; class BraveWalletService : public KeyedService, public mojom::BraveWalletService, public KeyringServiceObserverBase, + public TxServiceObserverBase, public BraveWalletServiceDelegate::Observer { public: using APIRequestHelper = api_request_helper::APIRequestHelper; @@ -299,6 +302,9 @@ class BraveWalletService : public KeyedService, // KeyringServiceObserverBase: void WalletRestored() override; + // TxServiceObserverBase: + void OnTransactionStatusChanged(mojom::TransactionInfoPtr tx_info) override; + void OnDiscoverAssetsStarted(); void OnDiscoverAssetsCompleted( @@ -350,6 +356,9 @@ class BraveWalletService : public KeyedService, return delegate_.get(); } + void SetDelegateForTesting( + std::unique_ptr delegate); + base::CallbackListSubscription RegisterSignMessageRequestAddedCallback( base::RepeatingClosure cb); base::CallbackListSubscription RegisterSignTransactionRequestAddedCallback( @@ -507,6 +516,8 @@ class BraveWalletService : public KeyedService, mojo::ReceiverSet receivers_; mojo::Receiver keyring_observer_receiver_{this}; + mojo::Receiver + tx_service_observer_receiver_{this}; PrefChangeRegistrar pref_change_registrar_; base::WeakPtrFactory weak_ptr_factory_; }; diff --git a/components/brave_wallet/browser/brave_wallet_service_delegate.cc b/components/brave_wallet/browser/brave_wallet_service_delegate.cc index 658e81255e8..004d921e183 100644 --- a/components/brave_wallet/browser/brave_wallet_service_delegate.cc +++ b/components/brave_wallet/browser/brave_wallet_service_delegate.cc @@ -85,4 +85,12 @@ void BraveWalletServiceDelegate::ResetWebSitePermission( std::move(callback).Run(false); } +void BraveWalletServiceDelegate::DisplayTxNotification( + brave_wallet::mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url) { + NOTIMPLEMENTED(); +} + } // namespace brave_wallet diff --git a/components/brave_wallet/browser/brave_wallet_service_delegate.h b/components/brave_wallet/browser/brave_wallet_service_delegate.h index 206457cd72a..b03e1a8c933 100644 --- a/components/brave_wallet/browser/brave_wallet_service_delegate.h +++ b/components/brave_wallet/browser/brave_wallet_service_delegate.h @@ -82,6 +82,11 @@ class BraveWalletServiceDelegate { virtual bool IsPrivateWindow() = 0; + virtual void DisplayTxNotification(mojom::TransactionStatus status, + const std::string& account_name, + const std::string& tx_id, + const GURL& tx_url); + static std::unique_ptr Create( content::BrowserContext* browser_context); }; diff --git a/components/brave_wallet/browser/tx_service_observer_base.h b/components/brave_wallet/browser/tx_service_observer_base.h new file mode 100644 index 00000000000..6a3725fb82d --- /dev/null +++ b/components/brave_wallet/browser/tx_service_observer_base.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2026 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_BRAVE_WALLET_BROWSER_TX_SERVICE_OBSERVER_BASE_H_ +#define BRAVE_COMPONENTS_BRAVE_WALLET_BROWSER_TX_SERVICE_OBSERVER_BASE_H_ + +#include "brave/components/brave_wallet/common/brave_wallet.mojom.h" +#include "brave/components/brave_wallet/common/buildflags/buildflags.h" + +static_assert(BUILDFLAG(ENABLE_BRAVE_WALLET)); +namespace brave_wallet { + +class TxServiceObserverBase : public mojom::TxServiceObserver { + void OnNewUnapprovedTx(mojom::TransactionInfoPtr tx_info) override {} + void OnUnapprovedTxUpdated(mojom::TransactionInfoPtr tx_info) override {} + void OnTransactionStatusChanged(mojom::TransactionInfoPtr tx_info) override {} + void OnTxServiceReset() override {} +}; + +} // namespace brave_wallet + +#endif // BRAVE_COMPONENTS_BRAVE_WALLET_BROWSER_TX_SERVICE_OBSERVER_BASE_H_ diff --git a/patches/chrome-browser-notifications-notification_display_service_impl.cc.patch b/patches/chrome-browser-notifications-notification_display_service_impl.cc.patch index 2b8930fd8ca..72717497c53 100644 --- a/patches/chrome-browser-notifications-notification_display_service_impl.cc.patch +++ b/patches/chrome-browser-notifications-notification_display_service_impl.cc.patch @@ -6,7 +6,7 @@ index c185575c57d0f0e72edc3c9bcfc5874e4c2a63dd..0632480d7827cf594eb696db0237068e std::make_unique()); } #endif -+ BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER; ++ BRAVE_NOTIFICATION_DISPLAY_SERVICE_IMPL_CONSTRUCTOR; } bridge_delegator_ = std::make_unique(