From 73e30e91bf6a4b1cfe5b6828718c9d533494c467 Mon Sep 17 00:00:00 2001 From: Pete Miller Date: Thu, 10 Oct 2019 10:51:32 -0700 Subject: [PATCH] API to open Shields and Rewards dialog UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces `chrome.{ braveRewards, braveShields }.openBrowserActionUI(optional windowId, optional relativePath)`. Several upcoming features require being able to summon a dialog attached to Shields or Rewards icons from some other user action that is not clicking on the icon buttons (the only current way to open the dialogs). These features include: • Offering to bypass paywalls (Publisher Access Pass) • Offering to turn shields off (Webcompat detection) • Offering to opt-in to Rewards or complete a Rewards captcha The API allows a custom path to be sent to open a specific HTML page other than the one configured for the active tab, e.g. offer-paywall.html, solve-captcha.html etc The API will default to the current window for the profile, which only works when called from a WebUI page. When called from a background script, a windowId will need to be provided so that the popup is shown on a compatible active or recently-active window (and not, e.g., a devtools window). This was prototyped for the Publisher Access Pass concept at brave/brave-core#3565 and modified for this PR to use the Observer pattern. If there is a webui page which has access to chrome.braveShields or chrome.braveRewards API, then simply call `chrome.brave{Shields | Rewards}.openBrowserActionUI()` and `chrome.brave{Shields | Rewards}.openBrowserActionUI('fake-page.html)` to test. A popup should open on the current window Test Plan: Open chrome://inspect, switch to the Extensions tab, and inspect either the Rewards or Brave extension. Then use the following API calls, one at a time (uncomment the line you wish to run): ``` chrome.windows.getAll(wins => { // test that we can open in a specified window // chrome.braveShields.openBrowserActionUI(wins[0].id) // test that we can specify a page (should be 404 though!) // chrome.braveShields.openBrowserActionUI(wins[0].id, 'another.html) }) // Test that we can call in the 'active' window (e.g. if the call is made from NTP, which is the intention for rewards). Run this command then switch focus to an actual browser window for the profile. // setTimeout(() => chrome.braveShields.openBrowserActionUI('popup.html?grant-id=42'), 2000) // And with the default popup html // setTimeout(() => chrome.braveShields.openBrowserActionUI(), 2000) ``` Then create or open another profile at the same time, and verify that calling the API from one profile cannot open a popup in a window id from another profile. Also check that the API works for the other profile. --- browser/extensions/BUILD.gn | 2 + browser/extensions/api/brave_action_api.cc | 166 ++++++++++++++++++ browser/extensions/api/brave_action_api.h | 62 +++++++ browser/extensions/api/brave_rewards_api.cc | 22 +++ browser/extensions/api/brave_rewards_api.h | 11 ++ browser/extensions/api/brave_shields_api.cc | 21 +++ browser/extensions/api/brave_shields_api.h | 11 ++ browser/ui/BUILD.gn | 1 + .../brave_action_view_controller.cc | 7 + .../brave_action_view_controller.h | 13 +- .../brave_actions/brave_actions_container.cc | 21 +++ .../brave_actions/brave_actions_container.h | 16 +- .../location_bar/brave_location_bar_view.cc | 1 + .../location_bar/brave_location_bar_view.h | 1 + common/extensions/api/brave_rewards.json | 18 ++ common/extensions/api/brave_shields.json | 18 ++ .../browser/rewards_service_browsertest.cc | 19 +- 17 files changed, 393 insertions(+), 17 deletions(-) create mode 100644 browser/extensions/api/brave_action_api.cc create mode 100644 browser/extensions/api/brave_action_api.h diff --git a/browser/extensions/BUILD.gn b/browser/extensions/BUILD.gn index 97198356df44..0ef27c286b7d 100644 --- a/browser/extensions/BUILD.gn +++ b/browser/extensions/BUILD.gn @@ -11,6 +11,8 @@ declare_args() { source_set("extensions") { sources = [ + "api/brave_action_api.cc", + "api/brave_action_api.h", "api/brave_extensions_api_client.cc", "api/brave_extensions_api_client.h", "api/brave_rewards_api.cc", diff --git a/browser/extensions/api/brave_action_api.cc b/browser/extensions/api/brave_action_api.cc new file mode 100644 index 000000000000..e9e0e6f85048 --- /dev/null +++ b/browser/extensions/api/brave_action_api.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2019 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/. + + +#include "brave/browser/extensions/api/brave_action_api.h" + +#include +#include +#include + +#include "base/no_destructor.h" +#include "components/keyed_service/core/dependency_manager.h" +#include "components/keyed_service/core/keyed_service_factory.h" +#include "chrome/browser/extensions/api/tabs/tabs_constants.h" +#include "chrome/browser/extensions/api/tabs/windows_util.h" +#include "chrome/browser/extensions/chrome_extension_function_details.h" +#include "chrome/browser/extensions/window_controller.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "extensions/browser/extension_function.h" + +namespace { + +class BraveActionAPIDependencyManager : public DependencyManager { + public: + static BraveActionAPIDependencyManager* GetInstance() { + static base::NoDestructor factory; + return factory.get(); + } + BraveActionAPIDependencyManager() { } + ~BraveActionAPIDependencyManager() override; + private: + DISALLOW_COPY_AND_ASSIGN(BraveActionAPIDependencyManager); +}; + +BraveActionAPIDependencyManager::~BraveActionAPIDependencyManager() { } + +class BraveActionAPIFactory : public KeyedServiceFactory { + public: + BraveActionAPIFactory() : KeyedServiceFactory("BraveActionAPI", + BraveActionAPIDependencyManager::GetInstance(), SIMPLE) { } + + extensions::BraveActionAPI* GetBraveActionAPI(Browser* context) { + return static_cast( + GetServiceForContext(context, true)); + } + + private: + // KeyedServiceFactory: + std::unique_ptr BuildServiceInstanceFor( + void* context) const final { + return base::WrapUnique(new extensions::BraveActionAPI()); + } + bool IsOffTheRecord(void* context) const final { + return static_cast(context) + ->profile()->IsOffTheRecord(); + } + void* GetContextToUse(void* context) const final { + return context; + } + void CreateServiceNow(void* context) final { + KeyedServiceFactory::GetServiceForContext(context, true); + } + DISALLOW_COPY_AND_ASSIGN(BraveActionAPIFactory); +}; + +static BraveActionAPIFactory* GetFactoryInstance() { + static base::NoDestructor instance; + return instance.get(); +} + +} // namespace + +namespace extensions { +// +// BraveActionAPI::Observer +// +BraveActionAPI::Observer::Observer() { } + +BraveActionAPI::Observer::~Observer() { } + +// +// BraveActionAPI +// +// static +BraveActionAPI* BraveActionAPI::Get(Browser* context) { + return GetFactoryInstance()->GetBraveActionAPI(context); +} + +// static +bool BraveActionAPI::ShowActionUI( + ExtensionFunction* extension_function, + const std::string& extension_id, + std::unique_ptr window_id_param, + std::unique_ptr ui_relative_path_param, + std::string* error) { + // Which browser should we send the action to + Browser* browser = nullptr; + // If the windowId is specified, find it. Otherwise get the active + // window for the profile. + if (!window_id_param.get()) { + browser = ChromeExtensionFunctionDetails(extension_function) + .GetCurrentBrowser(); + if (!browser) { + *error = tabs_constants::kNoCurrentWindowError; + return false; + } + } else { + int window_id = *window_id_param; + std::string get_browser_error; + if (!windows_util::GetBrowserFromWindowID( + extension_function, + window_id, + WindowController::GetAllWindowFilter(), + &browser, + &get_browser_error)) { + *error = get_browser_error; + return false; + } + } + return ShowActionUI(browser, extension_id, std::move(ui_relative_path_param), + error); +} + +// static +bool BraveActionAPI::ShowActionUI( + Browser* browser, + const std::string& extension_id, + std::unique_ptr ui_relative_path_param, + std::string* error) { + bool did_notify = BraveActionAPI::Get(browser)->NotifyObservers(extension_id, + std::move(ui_relative_path_param)); + if (!did_notify) { + *error = "No toolbar is registered to observe BraveActionUI " + "calls for this window"; + return false; + } + return true; +} + +BraveActionAPI::BraveActionAPI() {} + +BraveActionAPI::~BraveActionAPI() { +} + +void BraveActionAPI::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void BraveActionAPI::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +bool BraveActionAPI::NotifyObservers(const std::string& extension_id, + std::unique_ptr ui_relative_path_param) { + bool did_notify = false; + for (auto& observer : observers_) { + observer.OnBraveActionShouldTrigger(extension_id, + std::move(ui_relative_path_param)); + did_notify = true; + } + return did_notify; +} +} // namespace extensions diff --git a/browser/extensions/api/brave_action_api.h b/browser/extensions/api/brave_action_api.h new file mode 100644 index 000000000000..8293a6d44fe7 --- /dev/null +++ b/browser/extensions/api/brave_action_api.h @@ -0,0 +1,62 @@ +// Copyright (c) 2019 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/. + +#ifndef BRAVE_BROWSER_EXTENSIONS_API_BRAVE_ACTION_API_H_ +#define BRAVE_BROWSER_EXTENSIONS_API_BRAVE_ACTION_API_H_ + +#include +#include + +#include "components/keyed_service/core/keyed_service.h" +#include "extensions/browser/extension_function.h" +#include "extensions/common/extension.h" + +class Browser; + +namespace extensions { +class BraveActionAPI : public KeyedService { + public: + class Observer { + public: + Observer(); + virtual void OnBraveActionShouldTrigger( + const std::string& extension_id, + std::unique_ptr ui_relative_path) = 0; + + protected: + virtual ~Observer(); + }; + + static BraveActionAPI* Get(Browser* context); + static bool ShowActionUI( + ExtensionFunction* extension_function, + const std::string& extension_id, + std::unique_ptr window_id, + std::unique_ptr ui_relative_path, + std::string* error); + static bool ShowActionUI( + Browser* browser, + const std::string& extension_id, + std::unique_ptr ui_relative_path, + std::string* error); + BraveActionAPI(); + ~BraveActionAPI() override; + + // Add or remove observers. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + protected: + bool NotifyObservers(const std::string& extension_id, + std::unique_ptr ui_relative_path_param); + + private: + base::ObserverList::Unchecked observers_; + + DISALLOW_COPY_AND_ASSIGN(BraveActionAPI); +}; +} // namespace extensions + +#endif // BRAVE_BROWSER_EXTENSIONS_API_BRAVE_ACTION_API_H_ diff --git a/browser/extensions/api/brave_rewards_api.cc b/browser/extensions/api/brave_rewards_api.cc index 06ce2805ecf6..d5c30fb534cf 100644 --- a/browser/extensions/api/brave_rewards_api.cc +++ b/browser/extensions/api/brave_rewards_api.cc @@ -13,12 +13,15 @@ #include "base/bind.h" #include "base/strings/string_number_conversions.h" #include "brave/browser/brave_rewards/tip_dialog.h" +#include "brave/browser/extensions/api/brave_action_api.h" #include "brave/common/extensions/api/brave_rewards.h" +#include "brave/common/extensions/extension_constants.h" #include "brave/components/brave_ads/browser/ads_service.h" #include "brave/components/brave_ads/browser/ads_service_factory.h" #include "brave/components/brave_rewards/browser/rewards_service.h" #include "brave/components/brave_rewards/browser/rewards_service_factory.h" #include "chrome/browser/extensions/api/tabs/tabs_constants.h" +#include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/web_contents.h" @@ -53,6 +56,25 @@ ExtensionFunction::ResponseAction BraveRewardsCreateWalletFunction::Run() { return RespondNow(NoArguments()); } +BraveRewardsOpenBrowserActionUIFunction:: +~BraveRewardsOpenBrowserActionUIFunction() { +} + +ExtensionFunction::ResponseAction +BraveRewardsOpenBrowserActionUIFunction::Run() { + std::unique_ptr params( + brave_rewards::OpenBrowserActionUI::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + std::string error; + if (!BraveActionAPI::ShowActionUI(this, + brave_rewards_extension_id, + std::move(params->window_id), + std::move(params->relative_path), &error)) { + return RespondNow(Error(error)); + } + return RespondNow(NoArguments()); +} + BraveRewardsTipSiteFunction::~BraveRewardsTipSiteFunction() { } diff --git a/browser/extensions/api/brave_rewards_api.h b/browser/extensions/api/brave_rewards_api.h index a525e03eacdb..bd215c146d6b 100644 --- a/browser/extensions/api/brave_rewards_api.h +++ b/browser/extensions/api/brave_rewards_api.h @@ -33,6 +33,17 @@ class BraveRewardsCreateWalletFunction : public ExtensionFunction { void OnCreateWallet(int32_t result); }; +class BraveRewardsOpenBrowserActionUIFunction : + public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("braveRewards.openBrowserActionUI", UNKNOWN) + + protected: + ~BraveRewardsOpenBrowserActionUIFunction() override; + + ResponseAction Run() override; +}; + class BraveRewardsTipSiteFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveRewards.tipSite", UNKNOWN) diff --git a/browser/extensions/api/brave_shields_api.cc b/browser/extensions/api/brave_shields_api.cc index b63a8211f1f3..5b5083ad6a0b 100644 --- a/browser/extensions/api/brave_shields_api.cc +++ b/browser/extensions/api/brave_shields_api.cc @@ -10,6 +10,7 @@ #include #include "base/strings/string_number_conversions.h" +#include "brave/browser/extensions/api/brave_action_api.h" #include "brave/common/extensions/api/brave_shields.h" #include "brave/common/extensions/extension_constants.h" #include "brave/components/brave_shields/browser/brave_shields_p3a.h" @@ -18,6 +19,7 @@ #include "brave/components/brave_shields/common/brave_shield_constants.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/api/tabs/tabs_constants.h" +#include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/web_contents.h" @@ -58,6 +60,25 @@ ExtensionFunction::ResponseAction BraveShieldsAllowScriptsOnceFunction::Run() { return RespondNow(NoArguments()); } +BraveShieldsOpenBrowserActionUIFunction:: +~BraveShieldsOpenBrowserActionUIFunction() { +} + +ExtensionFunction::ResponseAction +BraveShieldsOpenBrowserActionUIFunction::Run() { + std::unique_ptr params( + brave_shields::OpenBrowserActionUI::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + std::string error; + if (!BraveActionAPI::ShowActionUI(this, + brave_extension_id, + std::move(params->window_id), + std::move(params->relative_path), &error)) { + return RespondNow(Error(error)); + } + return RespondNow(NoArguments()); +} + ExtensionFunction::ResponseAction BraveShieldsSetBraveShieldsEnabledFunction::Run() { std::unique_ptr params( diff --git a/browser/extensions/api/brave_shields_api.h b/browser/extensions/api/brave_shields_api.h index 84e016993d40..02b0c577dec5 100644 --- a/browser/extensions/api/brave_shields_api.h +++ b/browser/extensions/api/brave_shields_api.h @@ -21,6 +21,17 @@ class BraveShieldsAllowScriptsOnceFunction : public ExtensionFunction { ResponseAction Run() override; }; +class BraveShieldsOpenBrowserActionUIFunction : + public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("braveShields.openBrowserActionUI", UNKNOWN) + + protected: + ~BraveShieldsOpenBrowserActionUIFunction() override; + + ResponseAction Run() override; +}; + class BraveShieldsSetBraveShieldsEnabledFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("braveShields.setBraveShieldsEnabled", UNKNOWN) diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index 9cdf2fd66491..8abc61a37f44 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -226,6 +226,7 @@ source_set("ui") { "//brave/browser/resources/extensions:resources", "//brave/components/brave_extension:generated_resources", "//brave/components/brave_extension:static_resources", + "//brave/browser/extensions", "//chrome/browser/extensions", "//extensions/browser", ] diff --git a/browser/ui/brave_actions/brave_action_view_controller.cc b/browser/ui/brave_actions/brave_action_view_controller.cc index a3302b1a755b..0aad831432b7 100644 --- a/browser/ui/brave_actions/brave_action_view_controller.cc +++ b/browser/ui/brave_actions/brave_action_view_controller.cc @@ -46,6 +46,13 @@ ui::MenuModel* BraveActionViewController::GetContextMenu() { return nullptr; } +bool BraveActionViewController::ExecuteActionUI( + std::string relative_path) { + return TriggerPopupWithUrl(PopupShowAction::SHOW_POPUP, + extension()->GetResourceURL(relative_path), + true); +} + ExtensionActionViewController* BraveActionViewController::GetPreferredPopupViewController() { return this; diff --git a/browser/ui/brave_actions/brave_action_view_controller.h b/browser/ui/brave_actions/brave_action_view_controller.h index 3f1ab3406796..690cef3e4299 100644 --- a/browser/ui/brave_actions/brave_action_view_controller.h +++ b/browser/ui/brave_actions/brave_action_view_controller.h @@ -1,16 +1,18 @@ -/* Copyright (c) 2019 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/. */ +// Copyright (c) 2019 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/. #ifndef BRAVE_BROWSER_UI_BRAVE_ACTIONS_BRAVE_ACTION_VIEW_CONTROLLER_H_ #define BRAVE_BROWSER_UI_BRAVE_ACTIONS_BRAVE_ACTION_VIEW_CONTROLLER_H_ #include +#include #include "chrome/browser/ui/extensions/extension_action_view_controller.h" class BraveActionIconWithBadgeImageSource; +class ToolbarActionViewController; namespace ui { class MenuModel; @@ -29,6 +31,9 @@ class BraveActionViewController : public ExtensionActionViewController { const gfx::Size& size) override; bool DisabledClickOpensMenu() const override; ui::MenuModel* GetContextMenu() override; + bool ExecuteActionUI(std::string relative_path); + ToolbarActionViewController* GetExtensionViewController( + const std::string& extension_id); private: ExtensionActionViewController* GetPreferredPopupViewController() override; bool TriggerPopupWithUrl(PopupShowAction show_action, diff --git a/browser/ui/views/brave_actions/brave_actions_container.cc b/browser/ui/views/brave_actions/brave_actions_container.cc index 5c020d5204bf..67075e2a1d61 100644 --- a/browser/ui/views/brave_actions/brave_actions_container.cc +++ b/browser/ui/views/brave_actions/brave_actions_container.cc @@ -53,14 +53,17 @@ void BraveActionsContainer::BraveActionInfo::Reset() { BraveActionsContainer::BraveActionsContainer(Browser* browser, Profile* profile) : views::View(), + extensions::BraveActionAPI::Observer(), browser_(browser), extension_system_(extensions::ExtensionSystem::Get(profile)), extension_action_api_(extensions::ExtensionActionAPI::Get(profile)), extension_registry_(extensions::ExtensionRegistry::Get(profile)), extension_action_manager_( extensions::ExtensionActionManager::Get(profile)), + brave_action_api_(extensions::BraveActionAPI::Get(browser)), extension_registry_observer_(this), extension_action_observer_(this), + brave_action_observer_(this), weak_ptr_factory_(this) { // Handle when the extension system is ready extension_system_->ready().Post( @@ -329,6 +332,7 @@ void BraveActionsContainer::OnExtensionSystemReady() { // observe changes in extension system extension_registry_observer_.Add(extension_registry_); extension_action_observer_.Add(extension_action_api_); + brave_action_observer_.Add(brave_action_api_); // Check if extensions already loaded AddAction(brave_extension_id); #if BUILDFLAG(BRAVE_REWARDS_ENABLED) @@ -363,6 +367,23 @@ void BraveActionsContainer::OnExtensionActionUpdated( } // end ExtensionActionAPI::Observer +// BraveActionAPI::Observer +void BraveActionsContainer::OnBraveActionShouldTrigger( + const std::string& extension_id, + std::unique_ptr ui_relative_path) { + if (!IsContainerAction(extension_id)) { + return; + } + if (actions_[extension_id].view_controller_) { + if (ui_relative_path) + actions_[extension_id].view_controller_ + ->ExecuteActionUI(*ui_relative_path); + else + actions_[extension_id].view_controller_ + ->ExecuteAction(true); + } +} + void BraveActionsContainer::ChildPreferredSizeChanged(views::View* child) { PreferredSizeChanged(); } diff --git a/browser/ui/views/brave_actions/brave_actions_container.h b/browser/ui/views/brave_actions/brave_actions_container.h index 711b5404bceb..6484bf39d6e3 100644 --- a/browser/ui/views/brave_actions/brave_actions_container.h +++ b/browser/ui/views/brave_actions/brave_actions_container.h @@ -10,6 +10,7 @@ #include #include +#include "brave/browser/extensions/api/brave_action_api.h" #include "brave/components/brave_rewards/browser/buildflags/buildflags.h" #include "chrome/browser/ui/views/toolbar/toolbar_action_view.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" @@ -24,6 +25,7 @@ #include "brave/browser/ui/views/brave_actions/brave_rewards_action_stub_view.h" #endif +class BraveActionViewController; class BraveActionsContainerTest; class BraveRewardsBrowserTest; @@ -40,6 +42,7 @@ class Button; // TODO(petemill): consider splitting to separate model, like // ToolbarActionsModel and ToolbarActionsBar class BraveActionsContainer : public views::View, + public extensions::BraveActionAPI::Observer, public extensions::ExtensionActionAPI::Observer, public extensions::ExtensionRegistryObserver, public ToolbarActionView::Delegate, @@ -53,7 +56,6 @@ class BraveActionsContainer : public views::View, void Init(); void Update(); void SetShouldHide(bool should_hide); - // ToolbarActionView::Delegate content::WebContents* GetCurrentWebContents() override; bool ShownInsideMenu() const override; @@ -121,7 +123,7 @@ class BraveActionsContainer : public views::View, int position_; std::unique_ptr view_; - std::unique_ptr view_controller_; + std::unique_ptr view_controller_; }; // Actions that belong to the container @@ -140,6 +142,10 @@ class BraveActionsContainer : public views::View, void UpdateActionState(const std::string& id); void AttachAction(BraveActionInfo &action); + // BraveActionAPI::Observer + void OnBraveActionShouldTrigger(const std::string& extension_id, + std::unique_ptr ui_relative_path) override; + bool should_hide_ = false; bool is_rewards_pressed_ = false; @@ -155,6 +161,7 @@ class BraveActionsContainer : public views::View, extensions::ExtensionActionAPI* extension_action_api_; extensions::ExtensionRegistry* extension_registry_; extensions::ExtensionActionManager* extension_action_manager_; + extensions::BraveActionAPI* brave_action_api_; // Listen to extension load, unloaded notifications. ScopedObserver extension_action_observer_; + // Listen to when we need to open a popup + ScopedObserver + brave_action_observer_; + // Listen for Brave Rewards preferences changes. BooleanPrefMember brave_rewards_enabled_; BooleanPrefMember hide_brave_rewards_button_; diff --git a/browser/ui/views/location_bar/brave_location_bar_view.cc b/browser/ui/views/location_bar/brave_location_bar_view.cc index bebf00e33bed..71b55480d56b 100644 --- a/browser/ui/views/location_bar/brave_location_bar_view.cc +++ b/browser/ui/views/location_bar/brave_location_bar_view.cc @@ -8,6 +8,7 @@ #include "brave/browser/profiles/profile_util.h" #include "brave/browser/themes/brave_theme_service.h" #include "brave/browser/ui/views/brave_actions/brave_actions_container.h" +#include "brave/browser/ui/views/toolbar/brave_toolbar_view.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/layout_constants.h" diff --git a/browser/ui/views/location_bar/brave_location_bar_view.h b/browser/ui/views/location_bar/brave_location_bar_view.h index 2ef363cd4e48..2beaa5232d1d 100644 --- a/browser/ui/views/location_bar/brave_location_bar_view.h +++ b/browser/ui/views/location_bar/brave_location_bar_view.h @@ -22,6 +22,7 @@ class BraveLocationBarView : public LocationBarView { void Layout() override; void Update(const content::WebContents* contents) override; void OnChanged() override; + BraveActionsContainer* GetBraveActionsContainer() { return brave_actions_; } // views::View: gfx::Size CalculatePreferredSize() const override; diff --git a/common/extensions/api/brave_rewards.json b/common/extensions/api/brave_rewards.json index 1dd195163161..04b6f53c6dd0 100644 --- a/common/extensions/api/brave_rewards.json +++ b/common/extensions/api/brave_rewards.json @@ -379,6 +379,24 @@ } ], "functions": [ + { + "name": "openBrowserActionUI", + "type": "function", + "description": "Prompts the user with a popup UI", + "parameters": [ + { + "name": "windowId", + "type": "integer", + "minimum": 0, + "optional": true + }, + { + "name": "relativePath", + "type": "string", + "optional": true + } + ] + }, { "name": "createWallet", "type": "function", diff --git a/common/extensions/api/brave_shields.json b/common/extensions/api/brave_shields.json index e04cdd7c7900..ebf43e2ac497 100644 --- a/common/extensions/api/brave_shields.json +++ b/common/extensions/api/brave_shields.json @@ -28,6 +28,24 @@ } ], "functions": [ + { + "name": "openBrowserActionUI", + "type": "function", + "description": "Prompts the user with a popup UI", + "parameters": [ + { + "name": "windowID", + "type": "integer", + "minimum": 0, + "optional": true + }, + { + "name": "relativePath", + "type": "string", + "optional": true + } + ] + }, { "name": "setBraveShieldsEnabled", "type": "function", diff --git a/components/brave_rewards/browser/rewards_service_browsertest.cc b/components/brave_rewards/browser/rewards_service_browsertest.cc index e7e2f71070d8..9195b1b65a2c 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest.cc +++ b/components/brave_rewards/browser/rewards_service_browsertest.cc @@ -14,8 +14,7 @@ #include "bat/ledger/internal/uphold/uphold_util.h" #include "bat/ledger/internal/static_values.h" #include "bat/ledger/ledger.h" -#include "brave/browser/ui/views/brave_actions/brave_actions_container.h" -#include "brave/browser/ui/views/location_bar/brave_location_bar_view.h" +#include "brave/browser/extensions/api/brave_action_api.h" #include "brave/common/brave_paths.h" #include "brave/common/extensions/extension_constants.h" #include "brave/components/brave_rewards/browser/rewards_service_factory.h" @@ -497,15 +496,13 @@ class BraveRewardsBrowserTest : content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, content::NotificationService::AllSources()); - // Click on the Rewards button - BraveLocationBarView* brave_location_bar_view = - static_cast( - BrowserView::GetBrowserViewForBrowser(browser()) - ->GetLocationBarView()); - BraveActionsContainer* brave_actions_container = - brave_location_bar_view->brave_actions_; - EXPECT_TRUE(brave_actions_container->actions_.at(brave_rewards_extension_id) - .view_controller_->ExecuteAction(true)); + // Ask the popup to open + std::string error; + bool popup_shown = extensions::BraveActionAPI::ShowActionUI( + browser(), brave_rewards_extension_id, nullptr, &error); + if (!popup_shown) + LOG(ERROR) << "Could not open rewards popup: " << error; + EXPECT_TRUE(popup_shown); // Wait for the popup to load popup_observer.Wait();