Wallet notifications (#35992)
This commit is contained in:
@@ -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 += [
|
||||
|
||||
@@ -5,27 +5,43 @@
|
||||
|
||||
#include "brave/components/brave_wallet/browser/brave_wallet_service.h"
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include <optional>
|
||||
|
||||
#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<NotificationDisplayServiceTester>(
|
||||
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<message_center::Notification> 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<NotificationDisplayServiceTester> notification_tester_;
|
||||
raw_ptr<Browser> 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<uint8_t>())),
|
||||
mojom::TransactionStatus::Confirmed, mojom::TransactionType::ETHSend,
|
||||
std::vector<std::string>(), std::vector<std::string>(),
|
||||
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());
|
||||
|
||||
@@ -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>(
|
||||
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
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <string>
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
@@ -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<brave_wallet::mojom::TxServiceObserver>&
|
||||
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<testing::NiceMock<MockBraveWalletServiceDelegate>>();
|
||||
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<TestCase> 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<uint8_t>())),
|
||||
test_case.status, mojom::TransactionType::ETHSend,
|
||||
std::vector<std::string>(), std::vector<std::string>(),
|
||||
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
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
@@ -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 <optional>
|
||||
|
||||
#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<int>& action_index,
|
||||
const std::optional<std::u16string>& 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
|
||||
@@ -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 <optional>
|
||||
#include <string>
|
||||
|
||||
#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<int>& action_index,
|
||||
const std::optional<std::u16string>& reply,
|
||||
base::OnceClosure completed_closure) override;
|
||||
|
||||
private:
|
||||
const raw_ref<Profile> profile_;
|
||||
};
|
||||
|
||||
} // namespace brave_wallet
|
||||
|
||||
#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_BRAVE_WALLET_NOTIFICATION_HANDLER_H_
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
@@ -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 <memory>
|
||||
#include <string>
|
||||
|
||||
#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<message_center::Notification> 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>(
|
||||
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
|
||||
@@ -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 <string>
|
||||
|
||||
#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<BraveWalletService> brave_wallet_service_;
|
||||
raw_ptr<content::BrowserContext> context_;
|
||||
mojo::Receiver<mojom::TxServiceObserver> tx_observer_receiver_{this};
|
||||
};
|
||||
|
||||
} // namespace brave_wallet
|
||||
|
||||
#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_H_
|
||||
@@ -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 <memory>
|
||||
|
||||
#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<WalletNotificationServiceFactory> instance;
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
WalletNotificationServiceFactory::WalletNotificationServiceFactory()
|
||||
: BrowserContextKeyedServiceFactory(
|
||||
"WalletNotificationService",
|
||||
BrowserContextDependencyManager::GetInstance()) {
|
||||
DependsOn(NotificationDisplayServiceFactory::GetInstance());
|
||||
DependsOn(brave_wallet::BraveWalletServiceFactory::GetInstance());
|
||||
}
|
||||
|
||||
WalletNotificationServiceFactory::~WalletNotificationServiceFactory() = default;
|
||||
|
||||
std::unique_ptr<KeyedService>
|
||||
WalletNotificationServiceFactory::BuildServiceInstanceForBrowserContext(
|
||||
content::BrowserContext* context) const {
|
||||
return std::make_unique<WalletNotificationService>(
|
||||
BraveWalletServiceFactory::GetServiceForContext(context), context);
|
||||
}
|
||||
|
||||
// static
|
||||
WalletNotificationService*
|
||||
WalletNotificationServiceFactory::GetServiceForContext(
|
||||
content::BrowserContext* context) {
|
||||
if (!IsAllowedForContext(context)) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<WalletNotificationService*>(
|
||||
GetInstance()->GetServiceForBrowserContext(context, true));
|
||||
}
|
||||
|
||||
} // namespace brave_wallet
|
||||
@@ -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 <memory>
|
||||
|
||||
#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 <typename T>
|
||||
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();
|
||||
~WalletNotificationServiceFactory() override;
|
||||
|
||||
// BrowserContextKeyedServiceFactory:
|
||||
std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
|
||||
content::BrowserContext* context) const override;
|
||||
};
|
||||
|
||||
} // namespace brave_wallet
|
||||
|
||||
#endif // BRAVE_BROWSER_BRAVE_WALLET_NOTIFICATIONS_WALLET_NOTIFICATION_SERVICE_FACTORY_H_
|
||||
@@ -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 <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<BraveWalletService>(
|
||||
url_loader_factory_.GetSafeWeakWrapper(),
|
||||
TestBraveWalletServiceDelegate::Create(), prefs(), local_state());
|
||||
|
||||
notification_service_ = std::make_unique<WalletNotificationService>(
|
||||
brave_wallet_service_.get(), profile());
|
||||
tester_ = std::make_unique<NotificationDisplayServiceTester>(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<EthTransaction> tx = std::make_unique<EthTransaction>(
|
||||
*EthTransaction::FromTxData(mojom::TxData::New(
|
||||
mojom::kMainnetChainId, "0x01", "0x4a817c800", "0x5208",
|
||||
"0x3535353535353535353535353535353535353535", "0x0de0b6b3a7640000",
|
||||
std::vector<uint8_t>())));
|
||||
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<NotificationDisplayServiceTester> tester_;
|
||||
TestingProfile profile_;
|
||||
TestingPrefServiceSimple local_state_;
|
||||
network::TestURLLoaderFactory url_loader_factory_;
|
||||
std::unique_ptr<BraveWalletService> brave_wallet_service_;
|
||||
std::unique_ptr<WalletNotificationService> 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+4
-6
@@ -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
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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<brave_wallet::BraveWalletNotificationHandler>( \
|
||||
*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 <chrome/browser/notifications/notification_display_service_impl.cc>
|
||||
#undef BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER
|
||||
#undef BRAVE_ADD_BRAVE_WALLET_NOTIFICATION_HANDLER
|
||||
#undef BRAVE_NOTIFICATION_DISPLAY_SERVICE_IMPL_CONSTRUCTOR
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<BraveWalletServiceDelegate> delegate) {
|
||||
delegate_ = std::move(delegate);
|
||||
}
|
||||
|
||||
} // namespace brave_wallet
|
||||
|
||||
@@ -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<BraveWalletServiceDelegate> delegate);
|
||||
|
||||
base::CallbackListSubscription RegisterSignMessageRequestAddedCallback(
|
||||
base::RepeatingClosure cb);
|
||||
base::CallbackListSubscription RegisterSignTransactionRequestAddedCallback(
|
||||
@@ -507,6 +516,8 @@ class BraveWalletService : public KeyedService,
|
||||
mojo::ReceiverSet<mojom::BraveWalletService> receivers_;
|
||||
mojo::Receiver<brave_wallet::mojom::KeyringServiceObserver>
|
||||
keyring_observer_receiver_{this};
|
||||
mojo::Receiver<brave_wallet::mojom::TxServiceObserver>
|
||||
tx_service_observer_receiver_{this};
|
||||
PrefChangeRegistrar pref_change_registrar_;
|
||||
base::WeakPtrFactory<BraveWalletService> weak_ptr_factory_;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<BraveWalletServiceDelegate> Create(
|
||||
content::BrowserContext* browser_context);
|
||||
};
|
||||
|
||||
@@ -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_
|
||||
@@ -6,7 +6,7 @@ index c185575c57d0f0e72edc3c9bcfc5874e4c2a63dd..0632480d7827cf594eb696db0237068e
|
||||
std::make_unique<NearbyNotificationHandler>());
|
||||
}
|
||||
#endif
|
||||
+ BRAVE_ADD_BRAVE_ADS_NOTIFICATION_HANDLER;
|
||||
+ BRAVE_NOTIFICATION_DISPLAY_SERVICE_IMPL_CONSTRUCTOR;
|
||||
}
|
||||
|
||||
bridge_delegator_ = std::make_unique<NotificationPlatformBridgeDelegator>(
|
||||
|
||||
Reference in New Issue
Block a user