forked from brave/brave-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create BraveActionsContainer and add Shields extension button to it.
Fix brave/brave-browser#668 Intention is for Shields 'extension' to feel built-in. BraveActionsContainer hooks in to extension system in order to display and update the button icon when necessary. Displays a custom badge which is sized and positioned specifically for the Shields count. Uses dynamic font sizing to maintain a target height and maximum width. Removes the Shields extension button from main extensions area (ToolbarActionsBar / BrowserActionsContainer). Disable context menu for shields extension button in brave actions area since there are no valid actions. Patches the content of a method at LocationBarView::Layout since it could be more harmful to copy that functionality to our subclass because it is complex and somewhat functional logic. Attempts to minimize the patching necessary by passing in a new argument to the method.
- Loading branch information
Showing
19 changed files
with
909 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
browser/ui/brave_actions/brave_action_icon_with_badge_image_source.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* 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/ui/brave_actions/brave_action_icon_with_badge_image_source.h" | ||
|
||
#include "base/strings/utf_string_conversions.h" | ||
#include "cc/paint/paint_flags.h" | ||
#include "chrome/browser/extensions/extension_action.h" | ||
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" | ||
#include "chrome/grit/theme_resources.h" | ||
#include "third_party/skia/include/core/SkColor.h" | ||
#include "ui/base/resource/resource_bundle.h" | ||
#include "ui/gfx/canvas.h" | ||
#include "ui/gfx/color_palette.h" | ||
#include "ui/gfx/font.h" | ||
#include "ui/gfx/geometry/rect.h" | ||
#include "ui/gfx/geometry/size.h" | ||
#include "ui/gfx/image/image_skia_operations.h" | ||
#include "ui/gfx/skia_paint_util.h" | ||
|
||
void BraveActionIconWithBadgeImageSource::PaintBadge(gfx::Canvas* canvas) { | ||
if (!badge_ || badge_->text.empty()) | ||
return; | ||
|
||
SkColor text_color = SkColorGetA(badge_->text_color) == SK_AlphaTRANSPARENT | ||
? SK_ColorWHITE | ||
: badge_->text_color; | ||
|
||
SkColor background_color = SkColorSetA(badge_->background_color, SK_AlphaOPAQUE); | ||
|
||
// Always use same height to avoid jumping up and down with different | ||
// characters which will differ slightly, | ||
// but vary the width so we cover as little of the icon as possible. | ||
constexpr int kBadgeHeight = 12; | ||
constexpr int kBadgeMaxWidth = 14; | ||
constexpr int kVPadding = 1; | ||
const int kTextHeightTarget = kBadgeHeight - (kVPadding * 2); | ||
int h_padding = 2; | ||
int text_max_width = kBadgeMaxWidth - (h_padding * 2); | ||
|
||
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | ||
gfx::FontList base_font = rb->GetFontList(ui::ResourceBundle::BaseFont) | ||
.DeriveWithHeightUpperBound(kTextHeightTarget); | ||
base::string16 utf16_text = base::UTF8ToUTF16(badge_->text); | ||
|
||
// Calculate best font size to fit maximum Width and constant Height | ||
int text_height = 0; | ||
int text_width = 0; | ||
gfx::Canvas::SizeStringInt(utf16_text, base_font, &text_width, | ||
&text_height, | ||
0, gfx::Canvas::NO_ELLIPSIS); | ||
// Leaving extremely verbose log lines commented in case we want to change | ||
// any sizes in this algorithm, these logs are helpful. | ||
// LOG(ERROR) << "BraveAction badge text size initial, " | ||
// << "w:" | ||
// << text_width | ||
// << " h:" | ||
// << text_height; | ||
if (text_width > text_max_width) { | ||
// Too wide | ||
// Reduce the padding | ||
h_padding -= 1; | ||
text_max_width += 2; // 2 * padding delta | ||
// If still cannot squeeze it in, reduce font size | ||
if (text_width > text_max_width) { | ||
// Reduce font size until we find the first one that fits within the width | ||
// TODO: Consider adding minimum font-size and adjusting | ||
// |max_decrement_attempts| accordingly | ||
int max_decrement_attempts = base_font.GetFontSize() - 1; | ||
for (int i = 0; i < max_decrement_attempts; ++i) { | ||
base_font = | ||
base_font.Derive(-1, 0, gfx::Font::Weight::NORMAL); | ||
gfx::Canvas::SizeStringInt(utf16_text, base_font, &text_width, &text_height, 0, | ||
gfx::Canvas::NO_ELLIPSIS); | ||
// LOG(ERROR) << "reducing to font size - w:" << text_width << " h:" << text_height; | ||
if (text_width <= text_max_width) | ||
break; | ||
} | ||
} | ||
} else if (text_height < kTextHeightTarget) { | ||
// Narrow enough, but could grow taller | ||
// Increase font size until text fills height and is not too wide | ||
// LOG(ERROR) << "can increase height"; | ||
constexpr int kMaxIncrementAttempts = 5; | ||
for (size_t i = 0; i < kMaxIncrementAttempts; ++i) { | ||
int w = 0; | ||
int h = 0; | ||
gfx::FontList bigger_font = | ||
base_font.Derive(1, 0, gfx::Font::Weight::NORMAL); | ||
gfx::Canvas::SizeStringInt(utf16_text, bigger_font, &w, &h, 0, | ||
gfx::Canvas::NO_ELLIPSIS); | ||
if (h > kTextHeightTarget || w > text_max_width) | ||
break; | ||
base_font = bigger_font; | ||
text_width = w; | ||
text_height = h; | ||
// LOG(ERROR) << "increasing to font size - w:" | ||
// << text_width | ||
// << " h:" << text_height; | ||
} | ||
} | ||
|
||
// Calculate badge size. It is clamped to a min width just because it looks | ||
// silly if it is too skinny. | ||
int badge_width = text_width + h_padding * 2; | ||
// Has to at least be as wide as it is tall, otherwise it looks weird | ||
badge_width = std::max(kBadgeHeight, badge_width); | ||
|
||
const gfx::Rect icon_area = GetIconAreaRect(); | ||
// Force the pixel width of badge to be either odd (if the icon width is odd) | ||
// or even otherwise. If there is a mismatch you get http://crbug.com/26400. | ||
if (icon_area.width() != 0 && (badge_width % 2 != icon_area.width() % 2)) | ||
badge_width += 1; | ||
|
||
// Calculate the badge background rect. It is usually right-aligned, but it | ||
// can also be center-aligned if it is large. | ||
const int badge_offset_x = icon_area.width() - badge_width; | ||
const int badge_offset_y = 0; | ||
gfx::Rect rect(icon_area.x() + badge_offset_x, icon_area.y() + badge_offset_y, | ||
badge_width, kBadgeHeight); | ||
cc::PaintFlags rect_flags; | ||
rect_flags.setStyle(cc::PaintFlags::kFill_Style); | ||
rect_flags.setAntiAlias(true); | ||
rect_flags.setColor(background_color); | ||
|
||
// Paint the backdrop. | ||
constexpr int kOuterCornerRadius = 5; | ||
canvas->DrawRoundRect(rect, kOuterCornerRadius, rect_flags); | ||
|
||
// Paint the text. | ||
const int kTextExtraVerticalPadding = (kTextHeightTarget - text_height) / 2; | ||
const int kVerticalPadding = kVPadding + kTextExtraVerticalPadding; | ||
// l, t, r, b | ||
rect.Inset(0, kVerticalPadding, 0, kVerticalPadding); | ||
// Draw string with ellipsis if it does not fit | ||
canvas->DrawStringRectWithFlags(utf16_text, base_font, text_color, rect, | ||
gfx::Canvas::TEXT_ALIGN_CENTER); | ||
} | ||
|
||
gfx::Rect BraveActionIconWithBadgeImageSource::GetIconAreaRect() const { | ||
return gfx::Rect(size()); | ||
} |
27 changes: 27 additions & 0 deletions
27
browser/ui/brave_actions/brave_action_icon_with_badge_image_source.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* 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_ICON_WITH_BADGE_IMAGE_SOURCE_H_ | ||
#define BRAVE_BROWSER_UI_BRAVE_ACTIONS_BRAVE_ACTION_ICON_WITH_BADGE_IMAGE_SOURCE_H_ | ||
|
||
#include "chrome/browser/ui/extensions/icon_with_badge_image_source.h" | ||
|
||
namespace gfx { | ||
class Canvas; | ||
class Rect; | ||
} | ||
|
||
// The purpose of this subclass is to: | ||
// - Paint the BraveAction badge in a custom location and with a different size | ||
// to regular BrowserAction extensions. | ||
class BraveActionIconWithBadgeImageSource : public IconWithBadgeImageSource { | ||
public: | ||
using IconWithBadgeImageSource::IconWithBadgeImageSource; | ||
private: | ||
void PaintBadge(gfx::Canvas* canvas) override; | ||
gfx::Rect GetIconAreaRect() const override; | ||
DISALLOW_COPY_AND_ASSIGN(BraveActionIconWithBadgeImageSource); | ||
}; | ||
|
||
#endif |
64 changes: 64 additions & 0 deletions
64
browser/ui/brave_actions/shields_action_view_controller.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* 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/ui/brave_actions/shields_action_view_controller.h" | ||
|
||
#include "brave/browser/ui/brave_actions/brave_action_icon_with_badge_image_source.h" | ||
#include "chrome/browser/extensions/extension_action.h" | ||
#include "chrome/browser/themes/theme_properties.h" | ||
#include "chrome/browser/sessions/session_tab_helper.h" | ||
#include "components/vector_icons/vector_icons.h" | ||
#include "ui/base/theme_provider.h" | ||
#include "ui/gfx/canvas.h" | ||
#include "ui/gfx/image/canvas_image_source.h" | ||
#include "ui/gfx/image/image_skia.h" | ||
#include "ui/gfx/paint_vector_icon.h" | ||
#include "ui/gfx/scoped_canvas.h" | ||
|
||
void ShieldsActionViewController::HideActivePopup() { | ||
// Usually, for an extension this should call the main extensions | ||
// toolbar_actions_bar_->HideActivePopup(), but we don't have a reference | ||
// to that, and it doesn't seem neccessary, whether the extension is opened | ||
// via mouse or keyboard (if a `commands` extension property is present) | ||
} | ||
|
||
bool ShieldsActionViewController::DisabledClickOpensMenu() const { | ||
// disabled is a per-tab state | ||
return false; | ||
} | ||
|
||
ui::MenuModel* ShieldsActionViewController::GetContextMenu() { | ||
// no context menu for shields button | ||
return nullptr; | ||
} | ||
|
||
gfx::Image ShieldsActionViewController::GetIcon(content::WebContents* web_contents, const gfx::Size& size) { | ||
return gfx::Image(gfx::ImageSkia(GetIconImageSource(web_contents, size), size)); | ||
} | ||
|
||
std::unique_ptr<BraveActionIconWithBadgeImageSource> ShieldsActionViewController::GetIconImageSource( | ||
content::WebContents* web_contents, const gfx::Size& size) { | ||
int tab_id = SessionTabHelper::IdForTab(web_contents).id(); | ||
// generate icon | ||
std::unique_ptr<BraveActionIconWithBadgeImageSource> image_source( | ||
new BraveActionIconWithBadgeImageSource(size)); | ||
image_source->SetIcon(icon_factory_.GetIcon(tab_id)); | ||
// set text | ||
std::unique_ptr<IconWithBadgeImageSource::Badge> badge; | ||
std::string badge_text = extension_action()->GetBadgeText(tab_id); | ||
if (!badge_text.empty()) { | ||
badge.reset(new IconWithBadgeImageSource::Badge( | ||
badge_text, | ||
extension_action()->GetBadgeTextColor(tab_id), | ||
extension_action()->GetBadgeBackgroundColor(tab_id))); | ||
} | ||
image_source->SetBadge(std::move(badge)); | ||
// state | ||
// If the extension doesn't want to run on the active web contents, we | ||
// grayscale it to indicate that. | ||
bool is_enabled_for_tab = extension_action()->GetIsVisible(tab_id); | ||
image_source->set_grayscale(!is_enabled_for_tab); | ||
image_source->set_paint_page_action_decoration(false); | ||
return image_source; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* 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_SHIELDS_ACTION_VIEW_CONTROLLER_H_ | ||
#define BRAVE_BROWSER_UI_BRAVE_ACTIONS_SHIELDS_ACTION_VIEW_CONTROLLER_H_ | ||
|
||
#include "chrome/browser/ui/extensions/extension_action_view_controller.h" | ||
|
||
class BraveActionIconWithBadgeImageSource; | ||
|
||
namespace ui { | ||
class MenuModel; | ||
} | ||
|
||
// The purposes of this subclass are to: | ||
// - Overcome the DCHECK in HideActivePopup since a toolbar will not be provided | ||
// - Use our custom class for painting the badge differently compared to | ||
// user-installed extensions | ||
// - Remove the context menu from the button since we do not allow uninstall | ||
class ShieldsActionViewController : public ExtensionActionViewController { | ||
public: | ||
using ExtensionActionViewController::ExtensionActionViewController; | ||
void HideActivePopup() override; | ||
gfx::Image GetIcon(content::WebContents* web_contents, const gfx::Size& size) override; | ||
bool DisabledClickOpensMenu() const override; | ||
ui::MenuModel* GetContextMenu() override; | ||
private: | ||
// Returns the image source for the icon. | ||
std::unique_ptr<BraveActionIconWithBadgeImageSource> GetIconImageSource( | ||
content::WebContents* web_contents, | ||
const gfx::Size& size); | ||
DISALLOW_COPY_AND_ASSIGN(ShieldsActionViewController); | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* 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/ui/toolbar/brave_toolbar_actions_model.h" | ||
|
||
#include "brave/common/extensions/extension_constants.h" | ||
#include "chrome/browser/ui/toolbar/toolbar_actions_model.h" | ||
#include "extensions/common/extension.h" | ||
|
||
bool BraveToolbarActionsModel::ShouldAddExtension(const extensions::Extension* extension) { | ||
// Don't show the Brave 'extension' in the ToolbarActions extensions area. It | ||
// will instead be shown in the BraveActions area. | ||
if (extension->id() == brave_extension_id) { | ||
return false; | ||
} | ||
return ToolbarActionsModel::ShouldAddExtension(extension); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* 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_TOOLBAR_TOOLBAR_ACTIONS_MODEL_H_ | ||
#define BRAVE_BROWSER_UI_TOOLBAR_TOOLBAR_ACTIONS_MODEL_H_ | ||
|
||
#include "chrome/browser/ui/toolbar/toolbar_actions_model.h" | ||
|
||
#include "extensions/common/extension.h" | ||
|
||
// The purposes of this subclass are to: | ||
// - Hide the Brave 'extension' item from the |ToolbarActionsBar|, since it is | ||
// displayed in the |BraveActionsContainer| | ||
class BraveToolbarActionsModel : public ToolbarActionsModel { | ||
public: | ||
using ToolbarActionsModel::ToolbarActionsModel; | ||
bool ShouldAddExtension(const extensions::Extension* extension) override; | ||
private: | ||
DISALLOW_COPY_AND_ASSIGN(BraveToolbarActionsModel); | ||
}; | ||
|
||
#endif |
Oops, something went wrong.