[Shields UI] Open page info when Shields detects repeated reloads (#32363)

This commit is contained in:
Kevin Smith
2025-11-18 12:49:33 -05:00
committed by GitHub
parent 55bb54e876
commit 52ac08c006
7 changed files with 213 additions and 0 deletions
+5
View File
@@ -18,6 +18,8 @@ source_set("location_bar") {
"brave_search_conversion/promotion_button_view.h",
"brave_selected_keyword_view_util.cc",
"brave_selected_keyword_view_util.h",
"brave_shields_page_info_controller.cc",
"brave_shields_page_info_controller.h",
"brave_star_view.cc",
"brave_star_view.h",
]
@@ -27,6 +29,8 @@ source_set("location_bar") {
"//brave/app/theme:brave_theme_resources",
"//brave/app/vector_icons",
"//brave/browser/ui:brave_tab_prefs",
"//brave/browser/ui/page_info",
"//brave/browser/ui/views/page_info",
"//brave/components/brave_search_conversion",
"//brave/components/commander/browser",
"//brave/components/commander/common",
@@ -43,6 +47,7 @@ source_set("location_bar") {
"//chrome/browser/ui/tabs:tab_strip",
"//chrome/browser/ui/views/location_bar",
"//chrome/browser/ui/views/page_action",
"//chrome/browser/ui/views/page_info",
"//components/image_fetcher/core",
"//components/search_engines",
"//components/version_info:channel",
@@ -14,11 +14,13 @@
#include "brave/app/vector_icons/vector_icons.h"
#include "brave/browser/themes/brave_theme_service.h"
#include "brave/browser/ui/color/brave_color_id.h"
#include "brave/browser/ui/page_info/features.h"
#include "brave/browser/ui/tabs/brave_tab_prefs.h"
#include "brave/browser/ui/views/brave_actions/brave_actions_container.h"
#include "brave/browser/ui/views/brave_news/brave_news_action_icon_view.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_controller.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_view.h"
#include "brave/browser/ui/views/location_bar/brave_shields_page_info_controller.h"
#include "brave/browser/ui/views/playlist/playlist_action_icon_view.h"
#include "brave/browser/ui/views/toolbar/brave_toolbar_view.h"
#include "brave/components/commander/common/buildflags/buildflags.h"
@@ -134,6 +136,12 @@ void BraveLocationBarView::Init() {
promotion_button_, omnibox_view_, browser());
}
if (page_info::features::IsShowBraveShieldsInPageInfoEnabled()) {
shields_page_info_controller_ =
std::make_unique<BraveShieldsPageInfoController>(
browser_->GetTabStripModel(), location_icon_view());
}
// brave action buttons
brave_actions_ = AddChildView(
std::make_unique<BraveActionsContainer>(browser_, profile()));
@@ -21,6 +21,7 @@
class BraveActionsContainer;
class BraveActionsContainerTest;
class BraveShieldsPageInfoController;
class PromotionButtonController;
class PromotionButtonView;
class PlaylistActionIconView;
@@ -135,6 +136,7 @@ class BraveLocationBarView : public LocationBarView {
raw_ptr<BraveNewsActionIconView> brave_news_action_icon_view_ = nullptr;
std::unique_ptr<PromotionButtonController> promotion_controller_;
raw_ptr<PromotionButtonView> promotion_button_ = nullptr;
std::unique_ptr<BraveShieldsPageInfoController> shields_page_info_controller_;
#if BUILDFLAG(ENABLE_TOR)
raw_ptr<OnionLocationView> onion_location_view_ = nullptr;
#endif
@@ -0,0 +1,97 @@
/* Copyright (c) 2025 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/ui/views/location_bar/brave_shields_page_info_controller.h"
#include "base/check_deref.h"
#include "brave/browser/ui/views/page_info/brave_page_info_bubble_view.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
#include "chrome/browser/ui/views/page_info/page_info_bubble_specification.h"
#include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "ui/views/view_utils.h"
namespace {
brave_shields::BraveShieldsTabHelper* GetShieldsHelper(
content::WebContents* web_contents) {
if (!web_contents) {
return nullptr;
}
return brave_shields::BraveShieldsTabHelper::FromWebContents(web_contents);
}
} // namespace
BraveShieldsPageInfoController::BraveShieldsPageInfoController(
TabStripModel* tab_strip_model,
LocationIconView* location_icon_view)
: tab_strip_model_(CHECK_DEREF(tab_strip_model)),
location_icon_view_(CHECK_DEREF(location_icon_view)) {
tab_strip_model_->AddObserver(this);
auto* web_contents = tab_strip_model_->GetActiveWebContents();
if (auto* shields_helper = GetShieldsHelper(web_contents)) {
shields_helper->AddObserver(this);
}
}
BraveShieldsPageInfoController::~BraveShieldsPageInfoController() {
auto* web_contents = tab_strip_model_->GetActiveWebContents();
if (auto* shields_helper = GetShieldsHelper(web_contents)) {
shields_helper->RemoveObserver(this);
}
}
void BraveShieldsPageInfoController::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) {
if (selection.active_tab_changed()) {
if (auto* shields_helper = GetShieldsHelper(selection.old_contents)) {
shields_helper->RemoveObserver(this);
}
if (auto* shields_helper = GetShieldsHelper(selection.new_contents)) {
shields_helper->AddObserver(this);
}
}
}
void BraveShieldsPageInfoController::OnResourcesChanged() {}
void BraveShieldsPageInfoController::OnRepeatedReloadsDetected() {
ShowBubbleForRepeatedReloads();
}
void BraveShieldsPageInfoController::ShowBubbleForRepeatedReloads() {
auto* web_contents = tab_strip_model_->GetActiveWebContents();
if (!web_contents) {
return;
}
content::NavigationEntry* entry =
web_contents->GetController().GetVisibleEntry();
if (!entry || entry->IsInitialEntry()) {
return;
}
std::unique_ptr<PageInfoBubbleSpecification> specification =
PageInfoBubbleSpecification::Builder(
&location_icon_view_.get(),
location_icon_view_->GetWidget()->GetNativeWindow(), web_contents,
entry->GetVirtualURL())
.Build();
views::BubbleDialogDelegateView* bubble =
PageInfoBubbleView::CreatePageInfoBubble(std::move(specification));
auto* page_info_bubble = views::AsViewClass<BravePageInfoBubbleView>(bubble);
CHECK(page_info_bubble);
page_info_bubble->SetHighlightedButton(&location_icon_view_.get());
page_info_bubble->GetWidget()->Show();
page_info_bubble->OpenShieldsPageAfterRepeatedReloads();
}
@@ -0,0 +1,49 @@
/* Copyright (c) 2025 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_UI_VIEWS_LOCATION_BAR_BRAVE_SHIELDS_PAGE_INFO_CONTROLLER_H_
#define BRAVE_BROWSER_UI_VIEWS_LOCATION_BAR_BRAVE_SHIELDS_PAGE_INFO_CONTROLLER_H_
#include "base/memory/raw_ref.h"
#include "brave/browser/brave_shields/brave_shields_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
class LocationIconView;
class TabStripModel;
// Controller that listens for Brave Shields events for the current active tab
// and opens the Page Info bubble when appropriate.
class BraveShieldsPageInfoController
: public brave_shields::BraveShieldsTabHelper::Observer,
public TabStripModelObserver {
public:
BraveShieldsPageInfoController(TabStripModel* tab_strip_model,
LocationIconView* location_icon_view);
BraveShieldsPageInfoController(const BraveShieldsPageInfoController&) =
delete;
BraveShieldsPageInfoController& operator=(
const BraveShieldsPageInfoController&) = delete;
~BraveShieldsPageInfoController() override;
// TabStripModelObserver:
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
// brave_shields::BraveShieldsTabHelper::Observer:
void OnResourcesChanged() override;
void OnRepeatedReloadsDetected() override;
private:
void ShowBubbleForRepeatedReloads();
raw_ref<TabStripModel> tab_strip_model_;
raw_ref<LocationIconView> location_icon_view_;
};
#endif // BRAVE_BROWSER_UI_VIEWS_LOCATION_BAR_BRAVE_SHIELDS_PAGE_INFO_CONTROLLER_H_
+1
View File
@@ -43,6 +43,7 @@ source_set("browser_tests") {
deps = [
":page_info",
"//brave/browser/ui/page_info",
"//brave/components/brave_shields/core/common",
"//chrome/browser/ui/views/frame",
"//chrome/browser/ui/views/location_bar",
"//chrome/browser/ui/views/page_info",
@@ -8,8 +8,10 @@
#include "base/test/scoped_feature_list.h"
#include "brave/browser/ui/page_info/features.h"
#include "brave/browser/ui/views/page_info/brave_page_info_view_ids.h"
#include "brave/components/brave_shields/core/common/features.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
@@ -21,6 +23,7 @@
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/page_info/page_info.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_navigation_observer.h"
#include "ui/events/test/test_event.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/test/button_test_api.h"
@@ -292,3 +295,51 @@ IN_PROC_BROWSER_TEST_F(BravePageInfoBubbleViewFlagDisabledBrowserTest,
// Verify that the shields web UI is not visible.
EXPECT_FALSE(IsShieldsViewDrawn(bubble_view));
}
class BravePageInfoBubbleViewRepeatedReloadsBrowserTest
: public BravePageInfoBubbleViewBrowserTestBase {
public:
BravePageInfoBubbleViewRepeatedReloadsBrowserTest() {
using brave_shields::features::kAdblockOnlyMode;
using brave_shields::features::kAdblockOnlyModePromptAfterPageReloadsMax;
using brave_shields::features::kAdblockOnlyModePromptAfterPageReloadsMin;
feature_list_.InitWithFeaturesAndParameters(
{{page_info::features::kShowBraveShieldsInPageInfo, {}},
{kAdblockOnlyMode,
{{kAdblockOnlyModePromptAfterPageReloadsMin.name, "2"},
{kAdblockOnlyModePromptAfterPageReloadsMax.name, "3"}}}},
{});
}
~BravePageInfoBubbleViewRepeatedReloadsBrowserTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
};
// Test that the page info bubble is automatically opened and shows the shields
// tab after repeated reloads.
IN_PROC_BROWSER_TEST_F(BravePageInfoBubbleViewRepeatedReloadsBrowserTest,
AutoOpenAfterRepeatedReloads) {
GURL test_url = embedded_https_test_server().GetURL("/test.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
auto reload = [&]() {
content::TestNavigationObserver reload_observer(
browser()->tab_strip_model()->GetActiveWebContents());
chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
reload_observer.Wait();
};
// The first reload should not open the bubble.
reload();
EXPECT_FALSE(GetBubbleView());
// The second reload should open the bubble with the Shield tab visible.
reload();
auto* bubble_view = GetBubbleView();
ASSERT_TRUE(bubble_view);
EXPECT_TRUE(IsShieldsViewDrawn(bubble_view));
EXPECT_FALSE(IsSiteSettingsViewDrawn(bubble_view));
}