Skip to content

Commit 72ea8bb

Browse files
committed
Add PartitionedStorageActionView for container tabs in location bar
Introduce a page action icon that appears in the location bar when the current tab is in a Brave container (partitioned storage). The icon shows the container's icon, name, and background color from ContainerModel, giving users a clear indication of which container context the tab is using. Changes: - Register the icon type and creation path - brave_page_action_icon_type.h: declare `kPartitionedStorageActionIconType` - brave_page_action_icon_container_view.cc: add the type to `params.types_enabled` only when `BUILDFLAG(ENABLE_CONTAINERS)` and `containers::features::kContainers` are enabled - page_action_icon_controller.cc: add `BRAVE_PARTITIONED_STORAGE_ACTION_CASE` that creates `PartitionedStorageActionView` only when `BUILDFLAG(ENABLE_CONTAINERS)` is set and the `kContainers` feature is enabled; include/view code guarded by `BUILDFLAG(ENABLE_CONTAINERS)` - Add PartitionedStorageActionView (page_action/) as a new PageActionIconView that: - Resolves the current tab's container via GetContainerIdForWebContents and ContainerModel from prefs - Displays the container icon (scaled via ScaledContainerIconSource), name as a persistent label, and background color - Hides when the tab has no container
1 parent f703fce commit 72ea8bb

File tree

7 files changed

+287
-0
lines changed

7 files changed

+287
-0
lines changed

browser/ui/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ source_set("ui") {
672672
"//brave/browser/ui/views:layout_provider",
673673
"//brave/browser/ui/views/frame",
674674
"//brave/browser/ui/views/location_bar",
675+
"//brave/browser/ui/views/page_action",
675676
"//chrome/browser:shell_integration",
676677
"//chrome/browser/devtools",
677678
"//chrome/browser/enterprise/watermark:watermark_view_lib",

browser/ui/page_action/brave_page_action_icon_type.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define BRAVE_BROWSER_UI_PAGE_ACTION_BRAVE_PAGE_ACTION_ICON_TYPE_H_
88

99
#include "brave/components/brave_wayback_machine/buildflags/buildflags.h"
10+
#include "brave/components/containers/buildflags/buildflags.h"
1011
#include "brave/components/speedreader/common/buildflags/buildflags.h"
1112
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
1213

@@ -25,6 +26,9 @@ DECLARE_BRAVE_PAGE_ACTION_ICON_TYPE(kWaybackMachineActionIconType, -4);
2526
#if BUILDFLAG(ENABLE_SPEEDREADER)
2627
DECLARE_BRAVE_PAGE_ACTION_ICON_TYPE(kSpeedreaderPageActionIconType, -5);
2728
#endif
29+
#if BUILDFLAG(ENABLE_CONTAINERS)
30+
DECLARE_BRAVE_PAGE_ACTION_ICON_TYPE(kPartitionedStorageActionIconType, -6);
31+
#endif
2832

2933
#undef DECLARE_BRAVE_PAGE_ACTION_ICON_TYPE
3034

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (c) 2026 The Brave Authors. All rights reserved.
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
4+
# You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
import("//brave/components/containers/buildflags/buildflags.gni")
7+
8+
source_set("page_action") {
9+
# TODO(https://github.com/brave/brave-browser/issues/52829)
10+
# Other page action icons sources should be added here, not from
11+
# //b/b/ui/BUILD.gn
12+
sources = []
13+
deps = []
14+
15+
if (enable_containers) {
16+
sources += [
17+
"partitioned_storage_action_view.cc",
18+
"partitioned_storage_action_view.h",
19+
]
20+
deps += [
21+
"//brave/browser/ui/containers",
22+
"//brave/components/containers/content/browser",
23+
"//brave/components/containers/core/common:features",
24+
"//chrome/browser/profiles",
25+
"//chrome/browser/ui/views/page_action",
26+
]
27+
}
28+
}

browser/ui/views/page_action/brave_page_action_icon_container_view.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "base/check_is_test.h"
1111
#include "brave/browser/ui/page_action/brave_page_action_icon_type.h"
1212
#include "brave/components/brave_wayback_machine/buildflags/buildflags.h"
13+
#include "brave/components/containers/buildflags/buildflags.h"
1314
#include "brave/components/playlist/core/common/features.h"
1415
#include "brave/components/speedreader/common/buildflags/buildflags.h"
1516
#include "chrome/browser/profiles/profile.h"
@@ -22,6 +23,10 @@
2223
#include "brave/components/speedreader/common/features.h"
2324
#endif
2425

26+
#if BUILDFLAG(ENABLE_CONTAINERS)
27+
#include "brave/components/containers/core/common/features.h"
28+
#endif
29+
2530
namespace {
2631

2732
PageActionIconParams& ModifyIconParamsForBrave(PageActionIconParams& params) {
@@ -42,6 +47,15 @@ PageActionIconParams& ModifyIconParamsForBrave(PageActionIconParams& params) {
4247
brave::kWaybackMachineActionIconType);
4348
#endif
4449

50+
#if BUILDFLAG(ENABLE_CONTAINERS)
51+
if (base::FeatureList::IsEnabled(containers::features::kContainers)) {
52+
params.types_enabled.insert(
53+
std::ranges::find(params.types_enabled,
54+
PageActionIconType::kSharingHub),
55+
brave::kPartitionedStorageActionIconType);
56+
}
57+
#endif
58+
4559
if (base::FeatureList::IsEnabled(playlist::features::kPlaylist)) {
4660
// Browser could be null if the location bar was created for
4761
// PresentationReceiverWindowView.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Copyright (c) 2026 The Brave Authors. All rights reserved.
2+
// This Source Code Form is subject to the terms of the Mozilla Public
3+
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
4+
// You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
#include "brave/browser/ui/views/page_action/partitioned_storage_action_view.h"
7+
8+
#include <algorithm>
9+
10+
#include "base/strings/utf_string_conversions.h"
11+
#include "brave/components/containers/content/browser/storage_partition_utils.h"
12+
#include "brave/components/containers/core/common/features.h"
13+
#include "chrome/browser/profiles/profile.h"
14+
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
15+
#include "content/public/browser/web_contents.h"
16+
#include "third_party/skia/include/core/SkColor.h"
17+
#include "ui/base/metadata/metadata_impl_macros.h"
18+
#include "ui/base/models/image_model.h"
19+
#include "ui/compositor/compositor.h"
20+
#include "ui/gfx/canvas.h"
21+
#include "ui/gfx/image/canvas_image_source.h"
22+
#include "ui/gfx/image/image_skia.h"
23+
#include "ui/gfx/vector_icon_types.h"
24+
#include "ui/views/accessibility/view_accessibility.h"
25+
#include "ui/views/widget/widget.h"
26+
27+
namespace {
28+
29+
// Scales a container icon to the requested size for the page action icon.
30+
class ScaledContainerIconSource : public gfx::CanvasImageSource {
31+
public:
32+
ScaledContainerIconSource(const gfx::ImageSkia& source, int target_size)
33+
: CanvasImageSource(gfx::Size(target_size, target_size)),
34+
source_(source),
35+
target_size_(target_size) {}
36+
37+
void Draw(gfx::Canvas* canvas) override {
38+
canvas->DrawImageInt(/*image=*/source_, 0, 0, source_.width(),
39+
source_.height(), 0, 0, /*dest_w=*/target_size_,
40+
/*dest_h=*/target_size_,
41+
/*filter=*/true);
42+
}
43+
44+
private:
45+
gfx::ImageSkia source_;
46+
int target_size_;
47+
};
48+
49+
} // namespace
50+
51+
PartitionedStorageActionView::PartitionedStorageActionView(
52+
IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
53+
PageActionIconView::Delegate* page_action_icon_delegate,
54+
Browser* browser)
55+
: PageActionIconView(/*command_updater=*/nullptr,
56+
/*command_id=*/0,
57+
/*parent_delegate=*/icon_label_bubble_delegate,
58+
/*delegate=*/page_action_icon_delegate,
59+
/*name_for_histograms=*/"PartitionedStorageActionView",
60+
/*action_id*/ std::nullopt,
61+
browser) {
62+
CHECK(base::FeatureList::IsEnabled(containers::features::kContainers));
63+
SetVisible(false);
64+
SetUpForInOutAnimation();
65+
SetBackgroundVisibility(BackgroundVisibility::kWithLabel);
66+
67+
label()->SetMaximumWidthSingleLine(120);
68+
label()->SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL);
69+
}
70+
71+
PartitionedStorageActionView::~PartitionedStorageActionView() = default;
72+
73+
void PartitionedStorageActionView::UpdateImpl() {
74+
content::WebContents* web_contents = GetWebContents();
75+
if (!web_contents) {
76+
container_model_.reset();
77+
SetVisible(false);
78+
return;
79+
}
80+
81+
std::string container_id =
82+
containers::GetContainerIdForWebContents(web_contents);
83+
if (container_id.empty()) {
84+
container_model_.reset();
85+
SetVisible(false);
86+
return;
87+
}
88+
89+
Profile* profile =
90+
Profile::FromBrowserContext(web_contents->GetBrowserContext());
91+
CHECK(profile);
92+
93+
const float scale_factor =
94+
GetWidget()->GetCompositor()->device_scale_factor();
95+
96+
std::vector<containers::ContainerModel> models =
97+
containers::GetContainerModelsFromPrefs(*profile->GetPrefs(),
98+
scale_factor);
99+
auto it =
100+
std::ranges::find(models, container_id, &containers::ContainerModel::id);
101+
if (it != models.end()) {
102+
container_model_ = std::move(*it);
103+
} else {
104+
// Could happen as a result of sync
105+
container_model_ = containers::ContainerModel::CreateForUnknown(
106+
container_id, scale_factor);
107+
}
108+
109+
auto container_name = base::UTF8ToUTF16(container_model_->name());
110+
SetLabel(container_name, container_name);
111+
ResetSlideAnimation(/*show=*/!container_name.empty());
112+
SetVisible(true);
113+
UpdateIconImage();
114+
UpdateBackground();
115+
}
116+
117+
views::BubbleDialogDelegate* PartitionedStorageActionView::GetBubble() const {
118+
return nullptr;
119+
}
120+
121+
const gfx::VectorIcon& PartitionedStorageActionView::GetVectorIcon() const {
122+
return gfx::VectorIcon::EmptyIcon();
123+
}
124+
125+
ui::ImageModel PartitionedStorageActionView::GetSizedIconImage(int size) const {
126+
if (!container_model_.has_value()) {
127+
return ui::ImageModel();
128+
}
129+
130+
const ui::ColorProvider* color_provider = GetColorProvider();
131+
if (!color_provider) {
132+
return ui::ImageModel();
133+
}
134+
135+
gfx::ImageSkia rasterized =
136+
container_model_->icon().Rasterize(color_provider);
137+
if (rasterized.isNull()) {
138+
return ui::ImageModel();
139+
}
140+
141+
gfx::ImageSkia scaled(
142+
std::make_unique<ScaledContainerIconSource>(rasterized, size),
143+
gfx::Size(size, size));
144+
return ui::ImageModel::FromImageSkia(scaled);
145+
}
146+
147+
SkColor PartitionedStorageActionView::GetBackgroundColor() const {
148+
if (container_model_.has_value()) {
149+
return container_model_->background_color();
150+
}
151+
return PageActionIconView::GetBackgroundColor();
152+
}
153+
154+
SkColor PartitionedStorageActionView::GetForegroundColor() const {
155+
return SK_ColorWHITE;
156+
}
157+
158+
int PartitionedStorageActionView::GetExtraInternalSpacing() const {
159+
// Default internal spacing is 4 (See
160+
// IconLabelBubbleView::GetInternalSpacing). return -1 so total is 3.
161+
return -1;
162+
}
163+
164+
void PartitionedStorageActionView::OnExecuting(
165+
PageActionIconView::ExecuteSource source) {}
166+
167+
BEGIN_METADATA(PartitionedStorageActionView)
168+
END_METADATA
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2026 The Brave Authors. All rights reserved.
2+
// This Source Code Form is subject to the terms of the Mozilla Public
3+
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
4+
// You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
#ifndef BRAVE_BROWSER_UI_VIEWS_PAGE_ACTION_PARTITIONED_STORAGE_ACTION_VIEW_H_
7+
#define BRAVE_BROWSER_UI_VIEWS_PAGE_ACTION_PARTITIONED_STORAGE_ACTION_VIEW_H_
8+
9+
#include <optional>
10+
11+
#include "brave/browser/ui/containers/container_model.h"
12+
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
13+
#include "ui/base/metadata/metadata_header_macros.h"
14+
15+
class Browser;
16+
17+
// Page action icon that shows when the current tab is in a Brave container
18+
// (partitioned storage). Displays the container's icon, name, and background
19+
// color from ContainerModel.
20+
class PartitionedStorageActionView : public PageActionIconView {
21+
METADATA_HEADER(PartitionedStorageActionView, PageActionIconView)
22+
23+
public:
24+
PartitionedStorageActionView(
25+
IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
26+
PageActionIconView::Delegate* page_action_icon_delegate,
27+
Browser* browser);
28+
PartitionedStorageActionView(const PartitionedStorageActionView&) = delete;
29+
PartitionedStorageActionView& operator=(const PartitionedStorageActionView&) =
30+
delete;
31+
~PartitionedStorageActionView() override;
32+
33+
protected:
34+
// PageActionIconView:
35+
void UpdateImpl() override;
36+
void OnExecuting(PageActionIconView::ExecuteSource source) override;
37+
views::BubbleDialogDelegate* GetBubble() const override;
38+
const gfx::VectorIcon& GetVectorIcon() const override;
39+
ui::ImageModel GetSizedIconImage(int size) const override;
40+
SkColor GetBackgroundColor() const override;
41+
42+
// IconLabelBubbleView:
43+
SkColor GetForegroundColor() const override;
44+
int GetExtraInternalSpacing() const override;
45+
46+
private:
47+
std::optional<containers::ContainerModel> container_model_;
48+
};
49+
50+
#endif // BRAVE_BROWSER_UI_VIEWS_PAGE_ACTION_PARTITIONED_STORAGE_ACTION_VIEW_H_

chromium_src/chrome/browser/ui/views/page_action/page_action_icon_controller.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
44
* You can obtain one at http://mozilla.org/MPL/2.0/. */
55

6+
#include "base/feature_list.h"
67
#include "brave/browser/ui/page_action/brave_page_action_icon_type.h"
78
#include "brave/browser/ui/views/location_bar/brave_star_view.h"
89
#include "brave/components/brave_wayback_machine/buildflags/buildflags.h"
10+
#include "brave/components/containers/buildflags/buildflags.h"
911
#include "brave/components/playlist/core/common/buildflags/buildflags.h"
1012
#include "brave/components/speedreader/common/buildflags/buildflags.h"
1113
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
@@ -15,6 +17,11 @@
1517
#include "brave/browser/ui/views/page_action/wayback_machine_action_icon_view.h"
1618
#endif
1719

20+
#if BUILDFLAG(ENABLE_CONTAINERS)
21+
#include "brave/browser/ui/views/page_action/partitioned_storage_action_view.h"
22+
#include "brave/components/containers/core/common/features.h"
23+
#endif
24+
1825
#if BUILDFLAG(ENABLE_SPEEDREADER)
1926
#include "brave/browser/ui/views/speedreader/speedreader_icon_view.h"
2027
#endif
@@ -50,6 +57,19 @@ constexpr bool kSupportsPlaylistActionIconView = false;
5057
#define BRAVE_WAYBACK_MACHINE_PAGE_ACTION_CASE
5158
#endif
5259

60+
#if BUILDFLAG(ENABLE_CONTAINERS)
61+
#define BRAVE_PARTITIONED_STORAGE_ACTION_CASE \
62+
case brave::kPartitionedStorageActionIconType: \
63+
CHECK(base::FeatureList::IsEnabled(containers::features::kContainers)); \
64+
add_page_action_icon( \
65+
type, std::make_unique<PartitionedStorageActionView>( \
66+
params.icon_label_bubble_delegate, \
67+
params.page_action_icon_delegate, params.browser)); \
68+
break;
69+
#else
70+
#define BRAVE_PARTITIONED_STORAGE_ACTION_CASE
71+
#endif
72+
5373
// Circumvent creation of CookieControlsIconView in
5474
// PageActionIconController::Init's switch statement by injecting a case
5575
// with a non-existent value created above.
@@ -67,6 +87,7 @@ constexpr bool kSupportsPlaylistActionIconView = false;
6787
break; \
6888
BRAVE_WAYBACK_MACHINE_PAGE_ACTION_CASE \
6989
BRAVE_PAGE_ACTION_ICON_CONTROLLER_SPEEDREADER_CASE \
90+
BRAVE_PARTITIONED_STORAGE_ACTION_CASE \
7091
case brave::kUndefinedPageActionIconType
7192

7293
// We define additional PageActionIconType values (in
@@ -86,6 +107,7 @@ constexpr bool kSupportsPlaylistActionIconView = false;
86107
#undef StarView
87108
#undef kShown
88109
#undef kCookieControls
110+
#undef BRAVE_PARTITIONED_STORAGE_ACTION_CASE
89111
#undef BRAVE_WAYBACK_MACHINE_PAGE_ACTION_CASE
90112
#undef BRAVE_PAGE_ACTION_ICON_CONTROLLER_SPEEDREADER_CASE
91113

0 commit comments

Comments
 (0)