Use chip framework for quiet notification prompt.
This CL adds the possibility to display a permission prompt in a less
prominent chip. Only requests from origins with an abusive reputation
will be scheduled for the quiet chip.
[Google internal] All test cases for the quiet chip.
https://docs.google.com/spreadsheets/d/1AxruYU2ZrqGN06sNtWxjmkr_a0EaG89vbJRHY4A36zA/edit?usp=sharing
Bug: 1177760
Change-Id: Iaf1a7204b56d64e3aedbdba4e68f7f82b62d43c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2690644
Commit-Queue: Illia Klimov <[email protected]>
Reviewed-by: Balazs Engedy <[email protected]>
Reviewed-by: Caitlin Fischer <[email protected]>
Reviewed-by: Andy Paicu <[email protected]>
Reviewed-by: Bret Sepulveda <[email protected]>
Cr-Commit-Position: refs/heads/master@{#899187}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2f44446..1096917 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -6456,6 +6456,9 @@
kOsDesktop,
FEATURE_VALUE_TYPE(
permissions::features::kPermissionChipRequestTypeSensitive)},
+ {"permission-quiet-chip", flag_descriptions::kPermissionQuietChipName,
+ flag_descriptions::kPermissionQuietChipDescription, kOsDesktop,
+ FEATURE_VALUE_TYPE(permissions::features::kPermissionQuietChip)},
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
{"dice-web-signin-interception",
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index cf844437..0e4d5f3 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4352,6 +4352,11 @@
"expiry_milestone": 93
},
{
+ "name": "permission-quiet-chip",
+ "owners": [ "elklm", "engedy"],
+ "expiry_milestone": 100
+ },
+ {
"name": "photo-picker-video-support",
"owners": [ "finnur" ],
"expiry_milestone": 92
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index c49aaaa..272a6fd 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2070,6 +2070,13 @@
"chrome://flags/#quiet-notification-prompts and `Safe Browsing Enhanced "
"Protection` to be enabled.";
+const char kPermissionQuietChipName[] = "Quiet Permission Chip Experiment";
+const char kPermissionQuietChipDescription[] =
+ "Enables an experimental permission prompt that uses the quiet chip "
+ "instead of the right-hand side address bar icon for quiet permission "
+ "prompts. Requires chrome://flags/#quiet-notification-prompts to be "
+ "enabled.";
+
const char kPlaybackSpeedButtonName[] = "Playback Speed Button";
const char kPlaybackSpeedButtonDescription[] =
"Enable the playback speed button on the media controls.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index c79cf54..ccdbe9a 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1183,6 +1183,9 @@
extern const char kPermissionPredictionsName[];
extern const char kPermissionPredictionsDescription[];
+extern const char kPermissionQuietChipName[];
+extern const char kPermissionQuietChipDescription[];
+
extern const char kPlaybackSpeedButtonName[];
extern const char kPlaybackSpeedButtonDescription[];
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc
index b70466a..e44899c 100644
--- a/chrome/browser/permissions/permission_request_manager_browsertest.cc
+++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -826,7 +826,7 @@
base::RunLoop().RunUntilIdle();
permissions::MockPermissionRequest request2(
- u"request2", permissions::RequestType::kGeolocation,
+ u"request2", permissions::RequestType::kMicStream,
permissions::PermissionRequestGestureType::UNKNOWN);
GetPermissionRequestManager()->AddRequest(source_frame, &request2);
base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a4809b6..c38cc96 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3992,6 +3992,8 @@
"views/location_bar/omnibox_chip_button.h",
"views/location_bar/permission_chip.cc",
"views/location_bar/permission_chip.h",
+ "views/location_bar/permission_quiet_chip.cc",
+ "views/location_bar/permission_quiet_chip.h",
"views/location_bar/permission_request_chip.cc",
"views/location_bar/permission_request_chip.h",
"views/location_bar/selected_keyword_view.cc",
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc
index 82ce975..2fa4777 100644
--- a/chrome/browser/ui/content_settings/content_setting_image_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -22,9 +22,11 @@
#include "chrome/browser/permissions/quiet_notification_permission_ui_state.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h"
+#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/content_settings/content_setting_image_model_states.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
@@ -35,6 +37,7 @@
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/features.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
+#include "components/permissions/features.h"
#include "components/permissions/permission_request_manager.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
@@ -977,8 +980,21 @@
auto* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
- if (!manager || !manager->ShouldCurrentRequestUseQuietUI())
+ // If `kPermissionQuietUIChip` is enabled, we shouldn't show the icon unless
+ // we're a PWA.
+ // TODO(crbug.com/1221189): Allow PermissionRequestManager to identify the
+ // correct UI style of a permission prompt.
+ const bool quiet_icon_allowed =
+ web_app::AppBrowserController::IsWebApp(
+ chrome::FindBrowserWithWebContents(web_contents)) ||
+ !base::FeatureList::IsEnabled(
+ permissions::features::kPermissionQuietChip);
+
+ if (!quiet_icon_allowed || !manager ||
+ !manager->ShouldCurrentRequestUseQuietUI()) {
return false;
+ }
+
// |manager| may be null in tests.
// Show promo the first time a quiet prompt is shown to the user.
set_should_show_promo(
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index c02d3168..ca31e38 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -56,6 +56,8 @@
#include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
+#include "chrome/browser/ui/views/location_bar/permission_quiet_chip.h"
+#include "chrome/browser/ui/views/location_bar/permission_request_chip.h"
#include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
#include "chrome/browser/ui/views/location_bar/star_view.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_container.h"
@@ -819,12 +821,16 @@
PermissionChip* LocationBarView::DisplayChip(
permissions::PermissionPrompt::Delegate* delegate) {
- DCHECK(!chip_);
DCHECK(delegate);
- // `chip_` must come first so it's in the correct place in the focus order.
- chip_ = AddChildViewAt(
- std::make_unique<PermissionRequestChip>(browser(), delegate), 0);
- return chip_;
+ return AddChip(std::make_unique<PermissionRequestChip>(browser(), delegate));
+}
+
+PermissionChip* LocationBarView::DisplayQuietChip(
+ permissions::PermissionPrompt::Delegate* delegate,
+ bool should_expand) {
+ DCHECK(delegate);
+ return AddChip(std::make_unique<PermissionQuietChip>(browser(), delegate,
+ should_expand));
}
void LocationBarView::FinalizeChip() {
@@ -914,6 +920,13 @@
0, LocationBarView::GetAvailableTextHeight() - (bubble_padding * 2));
}
+PermissionChip* LocationBarView::AddChip(std::unique_ptr<PermissionChip> chip) {
+ DCHECK(!chip_);
+ // `chip_` must come first so it's in the correct place in the focus order.
+ chip_ = AddChildViewAt(std::move(chip), 0);
+ return chip_;
+}
+
int LocationBarView::GetMinimumLeadingWidth() const {
// If the keyword bubble is showing, the view can collapse completely.
if (ShouldShowKeywordBubble())
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index c2cd957..a62759d 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -25,7 +25,7 @@
#include "chrome/browser/ui/views/extensions/extension_popup.h"
#include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
-#include "chrome/browser/ui/views/location_bar/permission_request_chip.h"
+#include "chrome/browser/ui/views/location_bar/permission_chip.h"
#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "components/security_state/core/security_state.h"
@@ -183,6 +183,11 @@
PermissionChip* DisplayChip(
permissions::PermissionPrompt::Delegate* delegate);
+ // Creates and displays an instance of PermissionQuietChip.
+ PermissionChip* DisplayQuietChip(
+ permissions::PermissionPrompt::Delegate* delegate,
+ bool should_expand);
+
// Removes previously displayed PermissionChip.
void FinalizeChip();
@@ -266,6 +271,9 @@
geolocation_permission_observation_{this};
#endif
+ // Adds `chip` as the first child view.
+ PermissionChip* AddChip(std::unique_ptr<PermissionChip> chip);
+
// Returns the amount of space required to the left of the omnibox text.
int GetMinimumLeadingWidth() const;
diff --git a/chrome/browser/ui/views/location_bar/omnibox_chip_button.cc b/chrome/browser/ui/views/location_bar/omnibox_chip_button.cc
index 2ed437d..63747e4 100644
--- a/chrome/browser/ui/views/location_bar/omnibox_chip_button.cc
+++ b/chrome/browser/ui/views/location_bar/omnibox_chip_button.cc
@@ -4,12 +4,10 @@
#include "chrome/browser/ui/views/location_bar/omnibox_chip_button.h"
-#include "base/location.h"
-#include "base/time/time.h"
+#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/layout_constants.h"
-#include "chrome/browser/ui/views/chrome_layout_provider.h"
-#include "components/vector_icons/vector_icons.h"
#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/theme_provider.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/highlight_path_generator.h"
@@ -116,14 +114,16 @@
}
SkColor OmniboxChipButton::GetMainColor() {
- ui::NativeTheme* native_theme = GetNativeTheme();
switch (theme_) {
case Theme::kBlue:
// TODO(crbug.com/1003612): ui::NativeTheme::kColorId_ProminentButtonColor
// does not always represent the blue color we need, but it is OK to use
// for now.
- return native_theme->GetSystemColor(
+ return GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor);
+ case Theme::kGray:
+ return GetThemeProvider()->GetColor(
+ ThemeProperties::COLOR_OMNIBOX_TEXT_DIMMED);
}
}
diff --git a/chrome/browser/ui/views/location_bar/omnibox_chip_button.h b/chrome/browser/ui/views/location_bar/omnibox_chip_button.h
index 1b37b8e8..84316fe 100644
--- a/chrome/browser/ui/views/location_bar/omnibox_chip_button.h
+++ b/chrome/browser/ui/views/location_bar/omnibox_chip_button.h
@@ -26,7 +26,7 @@
// of Chip.
enum class Theme {
kBlue,
- // TODO(crbug.com/1177760): Other themes will follow.
+ kGray,
};
void AnimateCollapse();
@@ -49,6 +49,8 @@
void SetTheme(Theme theme);
void SetForceExpandedForTesting(bool force_expanded_for_testing);
+ Theme get_theme_for_testing() { return theme_; }
+
private:
int GetIconSize() const;
diff --git a/chrome/browser/ui/views/location_bar/permission_chip.cc b/chrome/browser/ui/views/location_bar/permission_chip.cc
index eb9a266..1bc10c0 100644
--- a/chrome/browser/ui/views/location_bar/permission_chip.cc
+++ b/chrome/browser/ui/views/location_bar/permission_chip.cc
@@ -55,28 +55,25 @@
PermissionChip::PermissionChip(
permissions::PermissionPrompt::Delegate* delegate,
- const gfx::VectorIcon& icon,
- std::u16string message,
- bool should_start_open)
- : delegate_(delegate), should_start_open_(should_start_open) {
- DCHECK(delegate);
+ DisplayParams initializer)
+ : delegate_(delegate),
+ should_start_open_(initializer.should_start_open),
+ should_expand_(initializer.should_expand) {
+ DCHECK(delegate_);
SetUseDefaultFillLayout(true);
chip_button_ = AddChildView(std::make_unique<OmniboxChipButton>(
base::BindRepeating(&PermissionChip::ChipButtonPressed,
base::Unretained(this)),
- icon, message, true));
-
+ initializer.icon, initializer.message, initializer.is_prominent));
+ chip_button_->SetTheme(initializer.theme);
chip_button_->SetButtonController(std::make_unique<BubbleButtonController>(
chip_button_, this,
std::make_unique<views::Button::DefaultButtonControllerDelegate>(
chip_button_)));
-
chip_button_->SetExpandAnimationEndedCallback(base::BindRepeating(
&PermissionChip::ExpandAnimationEnded, base::Unretained(this)));
- chip_button_->SetTheme(OmniboxChipButton::Theme::kBlue);
-
Show(should_start_open_);
}
@@ -125,7 +122,8 @@
void PermissionChip::Show(bool always_open_bubble) {
// TODO(olesiamarukhno): Add tests for animation logic.
chip_button_->ResetAnimation();
- if (!delegate_->WasCurrentRequestAlreadyDisplayed() || always_open_bubble) {
+ if (should_expand_ &&
+ (!delegate_->WasCurrentRequestAlreadyDisplayed() || always_open_bubble)) {
chip_button_->AnimateExpand();
} else {
StartDismissTimer();
@@ -170,11 +168,18 @@
}
void PermissionChip::StartDismissTimer() {
- if (base::FeatureList::IsEnabled(
- permissions::features::kPermissionChipAutoDismiss)) {
- auto delay = base::TimeDelta::FromMilliseconds(
- permissions::features::kPermissionChipAutoDismissDelay.Get());
- dismiss_timer_.Start(FROM_HERE, delay, this, &PermissionChip::Dismiss);
+ if (should_expand_) {
+ if (base::FeatureList::IsEnabled(
+ permissions::features::kPermissionChipAutoDismiss)) {
+ auto delay = base::TimeDelta::FromMilliseconds(
+ permissions::features::kPermissionChipAutoDismissDelay.Get());
+ dismiss_timer_.Start(FROM_HERE, delay, this, &PermissionChip::Dismiss);
+ }
+ } else {
+ // Abusive origins do not support expand animation, hence the dismiss timer
+ // should be longer.
+ dismiss_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(18), this,
+ &PermissionChip::Dismiss);
}
}
diff --git a/chrome/browser/ui/views/location_bar/permission_chip.h b/chrome/browser/ui/views/location_bar/permission_chip.h
index 096880a0..e9b11213 100644
--- a/chrome/browser/ui/views/location_bar/permission_chip.h
+++ b/chrome/browser/ui/views/location_bar/permission_chip.h
@@ -28,12 +28,21 @@
class PermissionChip : public views::AccessiblePaneView,
public views::WidgetObserver,
public BubbleOwnerDelegate {
+ protected:
+ // Holds all parameters needed for a chip initialization.
+ struct DisplayParams {
+ const gfx::VectorIcon& icon;
+ std::u16string message;
+ bool should_start_open;
+ bool is_prominent;
+ OmniboxChipButton::Theme theme;
+ bool should_expand;
+ };
+
public:
METADATA_HEADER(PermissionChip);
- PermissionChip(permissions::PermissionPrompt::Delegate* delegate,
- const gfx::VectorIcon& icon,
- std::u16string message,
- bool should_start_open);
+ explicit PermissionChip(permissions::PermissionPrompt::Delegate* delegate,
+ DisplayParams initializer);
PermissionChip(const PermissionChip& chip) = delete;
PermissionChip& operator=(const PermissionChip& chip) = delete;
~PermissionChip() override;
@@ -61,6 +70,8 @@
GetPermissionPromptBubbleForTest() = 0;
bool should_start_open_for_testing() { return should_start_open_; }
+ bool should_expand_for_testing() { return should_expand_; }
+ OmniboxChipButton* get_chip_button_for_testing() { return chip_button_; }
protected:
permissions::PermissionPrompt::Delegate* delegate() const {
@@ -76,6 +87,7 @@
void Collapse(bool allow_restart);
void StartDismissTimer();
void Dismiss();
+
void AnimateCollapse();
void AnimateExpand();
@@ -92,6 +104,7 @@
OmniboxChipButton* chip_button_ = nullptr;
bool should_start_open_ = false;
+ bool should_expand_ = true;
};
#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_CHIP_H_
diff --git a/chrome/browser/ui/views/location_bar/permission_quiet_chip.cc b/chrome/browser/ui/views/location_bar/permission_quiet_chip.cc
new file mode 100644
index 0000000..a193dfa
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/permission_quiet_chip.cc
@@ -0,0 +1,133 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/location_bar/permission_quiet_chip.h"
+
+#include "base/location.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.h"
+#include "chrome/browser/ui/views/permission_bubble/permission_prompt_style.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/permissions/permission_request.h"
+#include "components/permissions/request_type.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/events/event.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/controls/button/button_controller.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/widget/widget.h"
+
+#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
+#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+
+namespace {
+
+const gfx::VectorIcon& GetPermissionIconId(
+ permissions::PermissionPrompt::Delegate* delegate) {
+ DCHECK(delegate);
+
+ if (delegate->Requests()[0]->GetRequestType() ==
+ permissions::RequestType::kNotifications) {
+ return vector_icons::kNotificationsOffIcon;
+ }
+
+ NOTREACHED();
+ return gfx::kNoneIcon;
+}
+
+std::u16string GetPermissionMessage(
+ permissions::PermissionPrompt::Delegate* delegate) {
+ DCHECK(delegate);
+
+ if (delegate->Requests()[0]->GetRequestType() ==
+ permissions::RequestType::kNotifications) {
+ return l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_OFF_EXPLANATORY_TEXT);
+ }
+
+ NOTREACHED();
+ return std::u16string();
+}
+
+} // namespace
+
+PermissionQuietChip::PermissionQuietChip(
+ Browser* browser,
+ permissions::PermissionPrompt::Delegate* delegate,
+ bool should_expand)
+ : PermissionChip(
+ delegate,
+ {GetPermissionIconId(delegate), GetPermissionMessage(delegate), false,
+ /*is_prominent=*/false, OmniboxChipButton::Theme::kGray,
+ /*should_expand=*/should_expand}),
+ browser_(browser) {
+ DCHECK_EQ(1u, delegate->Requests().size());
+ chip_shown_time_ = base::TimeTicks::Now();
+}
+
+PermissionQuietChip::~PermissionQuietChip() {
+ if (quiet_request_bubble_) {
+ views::Widget* widget = quiet_request_bubble_->GetWidget();
+ widget->RemoveObserver(this);
+ widget->Close();
+ }
+}
+
+void PermissionQuietChip::OpenBubble() {
+ // The prompt bubble is either not opened yet or already closed on
+ // deactivation.
+ DCHECK(!quiet_request_bubble_);
+
+ LocationBarView* lbv = GetLocationBarView();
+ content::WebContents* web_contents = lbv->GetContentSettingWebContents();
+
+ if (web_contents) {
+ quiet_request_bubble_ = new ContentSettingBubbleContents(
+ std::make_unique<ContentSettingNotificationsBubbleModel>(
+ lbv->GetContentSettingBubbleModelDelegate(), web_contents),
+ web_contents, lbv, views::BubbleBorder::TOP_LEFT);
+ quiet_request_bubble_->SetHighlightedButton(button());
+ views::Widget* bubble_widget =
+ views::BubbleDialogDelegateView::CreateBubble(quiet_request_bubble_);
+ bubble_widget->AddObserver(this);
+ bubble_widget->Show();
+ }
+
+ RecordChipButtonPressed();
+}
+
+views::BubbleDialogDelegateView*
+PermissionQuietChip::GetPermissionPromptBubbleForTest() {
+ return quiet_request_bubble_;
+}
+
+void PermissionQuietChip::OnWidgetClosing(views::Widget* widget) {
+ DCHECK_EQ(widget, quiet_request_bubble_->GetWidget());
+ PermissionChip::OnWidgetClosing(widget);
+ quiet_request_bubble_ = nullptr;
+}
+
+bool PermissionQuietChip::IsBubbleShowing() const {
+ return quiet_request_bubble_;
+}
+
+void PermissionQuietChip::RecordChipButtonPressed() {
+ base::UmaHistogramMediumTimes("Permissions.QuietChip.TimeToInteraction",
+ base::TimeTicks::Now() - chip_shown_time_);
+}
+
+LocationBarView* PermissionQuietChip::GetLocationBarView() {
+ return BrowserView::GetBrowserViewForBrowser(browser_)->GetLocationBarView();
+}
+
+BEGIN_METADATA(PermissionQuietChip, views::View)
+END_METADATA
diff --git a/chrome/browser/ui/views/location_bar/permission_quiet_chip.h b/chrome/browser/ui/views/location_bar/permission_quiet_chip.h
new file mode 100644
index 0000000..e49bef8
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/permission_quiet_chip.h
@@ -0,0 +1,49 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_QUIET_CHIP_H_
+#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_QUIET_CHIP_H_
+
+#include "chrome/browser/ui/views/location_bar/permission_chip.h"
+
+class Browser;
+class LocationBarView;
+
+// A less prominent version of `PermissionRequestChip`. It is used to display a
+// permission request from origins with an abusive reputation, low acceptance
+// rate, or if a user manually enabled "quieter messaging" in
+// chrome://settings/content/notifications.
+class PermissionQuietChip : public PermissionChip {
+ public:
+ METADATA_HEADER(PermissionQuietChip);
+ PermissionQuietChip(Browser* browser,
+ permissions::PermissionPrompt::Delegate* delegate,
+ bool should_expand);
+ PermissionQuietChip(const PermissionQuietChip& chip) = delete;
+ PermissionQuietChip& operator=(const PermissionQuietChip& chip) = delete;
+ ~PermissionQuietChip() override;
+
+ // PermissionChip:
+ void OpenBubble() override;
+ views::BubbleDialogDelegateView* GetPermissionPromptBubbleForTest() override;
+
+ // views::WidgetObserver:
+ void OnWidgetClosing(views::Widget* widget) override;
+
+ // BubbleOwnerDelegate:
+ bool IsBubbleShowing() const override;
+
+ private:
+ void RecordChipButtonPressed();
+ LocationBarView* GetLocationBarView();
+
+ Browser* browser_ = nullptr;
+
+ // The time when the chip was displayed.
+ base::TimeTicks chip_shown_time_;
+
+ views::BubbleDialogDelegateView* quiet_request_bubble_ = nullptr;
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_QUIET_CHIP_H_
diff --git a/chrome/browser/ui/views/location_bar/permission_request_chip.cc b/chrome/browser/ui/views/location_bar/permission_request_chip.cc
index 40c7e09..58a25bf7 100644
--- a/chrome/browser/ui/views/location_bar/permission_request_chip.cc
+++ b/chrome/browser/ui/views/location_bar/permission_request_chip.cc
@@ -25,6 +25,7 @@
#include "ui/views/widget/widget.h"
namespace {
+
bool IsCameraPermission(permissions::RequestType type) {
return type == permissions::RequestType::kCameraStream;
}
@@ -112,10 +113,11 @@
PermissionRequestChip::PermissionRequestChip(
Browser* browser,
permissions::PermissionPrompt::Delegate* delegate)
- : PermissionChip(delegate,
- GetPermissionIconId(delegate),
- GetPermissionMessage(delegate),
- ShouldBubbleStartOpen(delegate)),
+ : PermissionChip(
+ delegate,
+ {GetPermissionIconId(delegate), GetPermissionMessage(delegate),
+ ShouldBubbleStartOpen(delegate), /*is_prominent=*/true,
+ OmniboxChipButton::Theme::kBlue, /*should_expand=*/true}),
browser_(browser) {
chip_shown_time_ = base::TimeTicks::Now();
VerifyCameraAndMicRequest(delegate);
@@ -159,7 +161,7 @@
}
void PermissionRequestChip::RecordChipButtonPressed() {
- base::UmaHistogramLongTimes("Permissions.Chip.TimeToInteraction",
+ base::UmaHistogramMediumTimes("Permissions.Chip.TimeToInteraction",
base::TimeTicks::Now() - chip_shown_time_);
}
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
index 4c85bad..0db4616e 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
@@ -109,7 +109,7 @@
}
base::RunLoop().RunUntilIdle();
- PermissionChip* chip = GetPermissionRequestChipView();
+ PermissionChip* chip = GetChip();
if (chip) {
views::test::ButtonTestApi(chip->button())
.NotifyClick(ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(),
@@ -120,7 +120,7 @@
}
bool VerifyUi() override {
- const bool should_close_on_deactivate = GetPermissionRequestChipView();
+ const bool should_close_on_deactivate = GetChip();
views::Widget* prompt_widget = test_api_->GetPromptWindow();
views::BubbleDialogDelegate* bubble_dialog =
prompt_widget->widget_delegate()->AsBubbleDialogDelegate();
@@ -135,12 +135,24 @@
return browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
}
- PermissionChip* GetPermissionRequestChipView() {
+ PermissionChip* GetChip() {
BrowserView* browser_view =
BrowserView::GetBrowserViewForBrowser(browser());
return browser_view->toolbar()->location_bar()->chip();
}
+ ContentSettingImageView& GetContentSettingImageView(
+ ContentSettingImageModel::ImageType image_type) {
+ LocationBarView* location_bar_view =
+ BrowserView::GetBrowserViewForBrowser(browser())->GetLocationBarView();
+ return **std::find_if(
+ location_bar_view->GetContentSettingViewsForTest().begin(),
+ location_bar_view->GetContentSettingViewsForTest().end(),
+ [image_type](ContentSettingImageView* view) {
+ return view->GetTypeForTesting() == image_type;
+ });
+ }
+
permissions::PermissionRequest* MakeRegisterProtocolHandlerRequest() {
std::string protocol = "mailto";
ProtocolHandler handler =
@@ -217,10 +229,52 @@
}
}
- void VerifyDisposition(permissions::PermissionPromptDisposition disposition) {
- EXPECT_EQ(
- test_api_->manager()->current_request_prompt_disposition_for_testing(),
- disposition);
+ void ExpectQuietAbusiveChip() {
+ // PermissionChip lifetime is bound to a permission prompt view.
+ ASSERT_TRUE(test_api_->manager()->view_for_testing());
+ // The quiet chip will be shown even if the chip experiment is disabled.
+ PermissionChip* chip = GetChip();
+ ASSERT_TRUE(chip);
+
+ EXPECT_FALSE(chip->should_expand_for_testing());
+ EXPECT_FALSE(chip->get_chip_button_for_testing()->GetProminent());
+ EXPECT_FALSE(chip->get_chip_button_for_testing()->is_animating());
+ EXPECT_EQ(OmniboxChipButton::Theme::kGray,
+ chip->get_chip_button_for_testing()->get_theme_for_testing());
+ }
+
+ void ExpectQuietChip() {
+ // PermissionChip lifetime is bound to a permission prompt view.
+ ASSERT_TRUE(test_api_->manager()->view_for_testing());
+
+ // The quiet chip will be shown even if the chip experiment is disabled.
+ PermissionChip* chip = GetChip();
+ ASSERT_TRUE(chip);
+
+ EXPECT_TRUE(chip->should_expand_for_testing());
+ EXPECT_FALSE(chip->get_chip_button_for_testing()->GetProminent());
+ EXPECT_TRUE(chip->get_chip_button_for_testing()->is_animating());
+ EXPECT_EQ(OmniboxChipButton::Theme::kGray,
+ chip->get_chip_button_for_testing()->get_theme_for_testing());
+ }
+
+ void ExpectNormalChip() {
+ // PermissionChip lifetime is bound to a permission prompt view.
+ ASSERT_TRUE(test_api_->manager()->view_for_testing());
+ if (GetParam()) {
+ PermissionChip* chip = GetChip();
+ ASSERT_TRUE(chip);
+
+ EXPECT_TRUE(chip->should_expand_for_testing());
+ EXPECT_TRUE(chip->get_chip_button_for_testing()->GetProminent());
+ EXPECT_TRUE(chip->get_chip_button_for_testing()->is_animating());
+ EXPECT_EQ(OmniboxChipButton::Theme::kBlue,
+ chip->get_chip_button_for_testing()->get_theme_for_testing());
+
+ } else {
+ // Chip is disabled.
+ EXPECT_FALSE(GetChip());
+ }
}
base::test::ScopedFeatureList feature_list_;
@@ -237,7 +291,7 @@
// AnnounceText doesn't go through the path that uses Event::kAlert. Therefore
// we can't test it.
#if !defined(OS_MAC)
- PermissionChip* chip = GetPermissionRequestChipView();
+ PermissionChip* chip = GetChip();
// If chip UI is used, two notifications will be announced: one that
// permission was requested and second when bubble is opened.
if (chip && !chip->should_start_open_for_testing()) {
@@ -414,15 +468,8 @@
base::RunLoop().RunUntilIdle();
}
- LocationBarView* location_bar_view =
- BrowserView::GetBrowserViewForBrowser(browser())->GetLocationBarView();
- ContentSettingImageView& quiet_ui_icon = **std::find_if(
- location_bar_view->GetContentSettingViewsForTest().begin(),
- location_bar_view->GetContentSettingViewsForTest().end(),
- [](ContentSettingImageView* view) {
- return view->GetTypeForTesting() ==
- ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT;
- });
+ ContentSettingImageView& quiet_ui_icon = GetContentSettingImageView(
+ ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
EXPECT_FALSE(quiet_ui_icon.GetVisible());
// `ContentSettingImageView::AnimationEnded()` was not triggered and IPH is
@@ -517,7 +564,8 @@
DispositionNoAbusiveTest) {
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -527,7 +575,8 @@
ShowUi("notifications");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -571,7 +620,8 @@
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -581,7 +631,8 @@
ShowUi("notifications");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
permissions::PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON);
}
@@ -591,7 +642,8 @@
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -601,7 +653,8 @@
ShowUi("notifications");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
permissions::PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON);
}
@@ -613,7 +666,8 @@
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -623,8 +677,10 @@
ShowUi("notifications");
- VerifyDisposition(permissions::PermissionPromptDisposition::
- LOCATION_BAR_RIGHT_ANIMATED_ICON);
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ permissions::PermissionPromptDisposition::
+ LOCATION_BAR_RIGHT_ANIMATED_ICON);
}
// For `QuietUiReason::kPredictedVeryUnlikelyGrant` reputation we show an
@@ -636,7 +692,8 @@
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -646,8 +703,10 @@
ShowUi("notifications");
- VerifyDisposition(permissions::PermissionPromptDisposition::
- LOCATION_BAR_RIGHT_ANIMATED_ICON);
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ permissions::PermissionPromptDisposition::
+ LOCATION_BAR_RIGHT_ANIMATED_ICON);
}
// For `QuietUiReason::kTriggeredDueToAbusiveRequests` reputation we show a
@@ -659,7 +718,8 @@
ShowUi("geolocation");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
GetParam()
? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
: permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
@@ -669,17 +729,161 @@
ShowUi("notifications");
- VerifyDisposition(
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
permissions::PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON);
}
-INSTANTIATE_TEST_SUITE_P(All,
- PermissionPromptBubbleViewQuietUiBrowserTest,
- ::testing::Values(false, true));
+class QuietChipPermissionPromptBubbleViewBrowserTest
+ : public PermissionPromptBubbleViewQuietUiBrowserTest {
+ public:
+ QuietChipPermissionPromptBubbleViewBrowserTest() {
+ scoped_feature_list_.InitAndEnableFeature(
+ permissions::features::kPermissionQuietChip);
+ }
-INSTANTIATE_TEST_SUITE_P(All,
- PermissionPromptBubbleViewBrowserTest,
- ::testing::Values(false, true));
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(QuietChipPermissionPromptBubbleViewBrowserTest,
+ LoudChipOrAnchoredBubbleIsShownForNonAbusiveRequests) {
+ SetCannedUiDecision(absl::nullopt, absl::nullopt);
+
+ ShowUi("geolocation");
+
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ GetParam()
+ ? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
+ : permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+
+ ShowUi("notifications");
+
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ GetParam()
+ ? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
+ : permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
+}
+
+IN_PROC_BROWSER_TEST_P(QuietChipPermissionPromptBubbleViewBrowserTest,
+ QuietChipIsShownForAbusiveRequests) {
+ for (QuietUiReason reason : {QuietUiReason::kTriggeredByCrowdDeny,
+ QuietUiReason::kTriggeredDueToAbusiveRequests,
+ QuietUiReason::kTriggeredDueToAbusiveContent}) {
+ SetCannedUiDecision(reason, absl::nullopt);
+
+ ShowUi("geolocation");
+
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ GetParam()
+ ? permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP
+ : permissions::PermissionPromptDisposition::ANCHORED_BUBBLE);
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+
+ ShowUi("notifications");
+
+ // Quiet Chip is enabled, that means a quiet chip will be shown even if the
+ // Chip experiment is disabled.
+ EXPECT_EQ(
+ test_api_->manager()->current_request_prompt_disposition_for_testing(),
+ permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_CHIP);
+ }
+}
+
+// The quiet UI icon is verified to make sure that the quiet chip is not shown
+// when the quiet icon is shown.
+IN_PROC_BROWSER_TEST_P(QuietChipPermissionPromptBubbleViewBrowserTest,
+ QuietChipIsNotShownForNonAbusiveRequests) {
+ SetCannedUiDecision(absl::nullopt, absl::nullopt);
+
+ ContentSettingImageView& quiet_ui_icon = GetContentSettingImageView(
+ ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ EXPECT_FALSE(GetChip());
+
+ ShowUi("geolocation");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectNormalChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+
+ ShowUi("notifications");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectNormalChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+}
+
+IN_PROC_BROWSER_TEST_P(QuietChipPermissionPromptBubbleViewBrowserTest,
+ NotAnimatedQuietChipIsShownForAbusiveRequests) {
+ for (QuietUiReason reason : {QuietUiReason::kTriggeredByCrowdDeny,
+ QuietUiReason::kTriggeredDueToAbusiveRequests,
+ QuietUiReason::kTriggeredDueToAbusiveContent}) {
+ SetCannedUiDecision(reason, absl::nullopt);
+
+ ContentSettingImageView& quiet_ui_icon = GetContentSettingImageView(
+ ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ EXPECT_FALSE(GetChip());
+
+ ShowUi("geolocation");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectNormalChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+
+ ShowUi("notifications");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectQuietAbusiveChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+ }
+}
+
+IN_PROC_BROWSER_TEST_P(QuietChipPermissionPromptBubbleViewBrowserTest,
+ AnimatedQuietChipIsShownForNonAbusiveRequests) {
+ for (QuietUiReason reason : {QuietUiReason::kEnabledInPrefs,
+ QuietUiReason::kPredictedVeryUnlikelyGrant}) {
+ SetCannedUiDecision(reason, absl::nullopt);
+
+ ContentSettingImageView& quiet_ui_icon = GetContentSettingImageView(
+ ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ EXPECT_FALSE(GetChip());
+
+ ShowUi("geolocation");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectNormalChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+
+ ShowUi("notifications");
+
+ EXPECT_FALSE(quiet_ui_icon.GetVisible());
+ ExpectQuietChip();
+
+ test_api_->manager()->Accept();
+ base::RunLoop().RunUntilIdle();
+ }
+}
class OneTimePermissionPromptBubbleViewBrowserTest
: public PermissionPromptBubbleViewBrowserTest {
@@ -699,8 +903,18 @@
ShowAndVerifyUi();
}
+// False / True values determine if the PermissionChip feature is
+// disabled/enabled.
+INSTANTIATE_TEST_SUITE_P(All,
+ PermissionPromptBubbleViewBrowserTest,
+ ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(All,
+ PermissionPromptBubbleViewQuietUiBrowserTest,
+ ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(All,
+ QuietChipPermissionPromptBubbleViewBrowserTest,
+ ::testing::Values(false, true));
INSTANTIATE_TEST_SUITE_P(All,
OneTimePermissionPromptBubbleViewBrowserTest,
::testing::Values(false, true));
-
INSTANTIATE_TEST_SUITE_P(All, QuietUIPromoBrowserTest, ::testing::Values(true));
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
index 16adbbb6..957230bc 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/permission_bubble/file_handling_permission_prompt.h"
#include "chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.h"
+#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/web_launch/web_launch_files_helper.h"
#include "components/permissions/features.h"
#include "components/permissions/permission_request.h"
@@ -23,6 +24,27 @@
#include "content/public/browser/web_contents.h"
#include "ui/views/bubble/bubble_frame_view.h"
+namespace {
+
+bool IsFullScreenMode(content::WebContents* web_contents, Browser* browser) {
+ DCHECK(web_contents);
+ DCHECK(browser);
+
+ // PWA uses the title bar as a substitute for LocationBarView.
+ if (web_app::AppBrowserController::IsWebApp(browser))
+ return false;
+
+ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+ if (!browser_view)
+ return false;
+
+ LocationBarView* location_bar = browser_view->GetLocationBarView();
+
+ return !location_bar || !location_bar->IsDrawn();
+}
+
+} // namespace
+
std::unique_ptr<permissions::PermissionPrompt> CreatePermissionPrompt(
content::WebContents* web_contents,
permissions::PermissionPrompt::Delegate* delegate) {
@@ -33,6 +55,14 @@
return nullptr;
}
+ permissions::PermissionRequestManager* manager =
+ permissions::PermissionRequestManager::FromWebContents(web_contents);
+
+ if (manager->ShouldDropCurrentRequestIfCannotShowQuietly() &&
+ IsFullScreenMode(web_contents, browser)) {
+ return nullptr;
+ }
+
if (base::FeatureList::IsEnabled(features::kFileHandlingPermissionUiV2) &&
delegate->Requests().size() == 1U &&
delegate->Requests()[0]->GetRequestType() ==
@@ -51,29 +81,18 @@
web_contents_(web_contents),
delegate_(delegate),
browser_(browser),
- permission_requested_time_(base::TimeTicks::Now()) {
- permissions::PermissionRequestManager* manager =
- permissions::PermissionRequestManager::FromWebContents(web_contents_);
- if (manager->ShouldCurrentRequestUseQuietUI()) {
- prompt_style_ = PermissionPromptStyle::kQuiet;
- // Shows the prompt as an indicator in the right side of the omnibox.
- content_settings::UpdateLocationBarUiForWebContents(web_contents_);
+ permission_requested_time_(base::TimeTicks::Now()),
+ manager_(permissions::PermissionRequestManager::FromWebContents(
+ web_contents)) {
+ if (web_app::AppBrowserController::IsWebApp(browser_)) {
+ SelectPwaPrompt();
+ } else if (manager_->ShouldCurrentRequestUseQuietUI()) {
+ SelectQuietPrompt();
} else {
- LocationBarView* lbv = GetLocationBarView();
- if (lbv && lbv->IsDrawn() && ShouldCurrentRequestUseChipUI()) {
- ShowChipUI();
- } else {
- ShowBubble();
- }
+ SelectNormalPrompt();
}
}
-void PermissionPromptImpl::OnWidgetClosing(views::Widget* widget) {
- DCHECK_EQ(widget, prompt_bubble_->GetWidget());
- widget->RemoveObserver(this);
- prompt_bubble_ = nullptr;
-}
-
PermissionPromptImpl::~PermissionPromptImpl() {
switch (prompt_style_) {
case PermissionPromptStyle::kBubbleOnly:
@@ -82,11 +101,12 @@
prompt_bubble_->GetWidget()->Close();
break;
case PermissionPromptStyle::kChip:
+ case PermissionPromptStyle::kQuietChip:
DCHECK(!prompt_bubble_);
DCHECK(chip_);
FinalizeChip();
break;
- case PermissionPromptStyle::kQuiet:
+ case PermissionPromptStyle::kLocationBarRightIcon:
DCHECK(!prompt_bubble_);
DCHECK(!chip_);
content_settings::UpdateLocationBarUiForWebContents(web_contents_);
@@ -116,12 +136,12 @@
if (!prompt_bubble_)
return;
- if (ShouldCurrentRequestUseChipUI() && is_location_bar_drawn) {
+ if (ShouldCurrentRequestUseChip() && is_location_bar_drawn) {
// Change prompt style to chip to avoid dismissing request while
// switching UI style.
prompt_bubble_->SetPromptStyle(PermissionPromptStyle::kChip);
prompt_bubble_->GetWidget()->Close();
- ShowChipUI();
+ ShowChip();
chip_->OpenBubble();
} else {
// If |browser_| changed, recreate bubble for correct browser.
@@ -147,47 +167,27 @@
ShowBubble();
}
break;
- case PermissionPromptStyle::kQuiet:
+ case PermissionPromptStyle::kQuietChip:
+ DCHECK(!prompt_bubble_);
+
+ if (!lbv->chip()) {
+ chip_ = lbv->DisplayQuietChip(
+ delegate_,
+ !permissions::PermissionUiSelector::ShouldSuppressAnimation(
+ manager_->ReasonForUsingQuietUi()));
+ }
+ // If there is fresh pending request shown as chip UI and location bar
+ // isn't visible anymore, show bubble UI instead.
+ if (!chip_->is_fully_collapsed() && !is_location_bar_drawn) {
+ FinalizeChip();
+ ShowBubble();
+ }
+ break;
+ case PermissionPromptStyle::kLocationBarRightIcon:
break;
}
}
-LocationBarView* PermissionPromptImpl::GetLocationBarView() {
- BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
- return browser_view ? browser_view->GetLocationBarView() : nullptr;
-}
-
-void PermissionPromptImpl::ShowChipUI() {
- LocationBarView* lbv = GetLocationBarView();
- DCHECK(lbv);
-
- chip_ = lbv->DisplayChip(delegate_);
- prompt_style_ = PermissionPromptStyle::kChip;
-}
-
-void PermissionPromptImpl::ShowBubble() {
- prompt_style_ = PermissionPromptStyle::kBubbleOnly;
- prompt_bubble_ = new PermissionPromptBubbleView(
- browser_, delegate_, permission_requested_time_, prompt_style_);
- prompt_bubble_->Show();
- prompt_bubble_->GetWidget()->AddObserver(this);
-}
-
-bool PermissionPromptImpl::ShouldCurrentRequestUseChipUI() {
- if (!base::FeatureList::IsEnabled(permissions::features::kPermissionChip))
- return false;
-
- std::vector<permissions::PermissionRequest*> requests = delegate_->Requests();
- return std::all_of(requests.begin(), requests.end(), [](auto* request) {
- return request->GetChipText().has_value();
- });
-}
-
-void PermissionPromptImpl::FinalizeChip() {
- GetLocationBarView()->FinalizeChip();
- chip_ = nullptr;
-}
-
permissions::PermissionPrompt::TabSwitchingBehavior
PermissionPromptImpl::GetTabSwitchingBehavior() {
return permissions::PermissionPrompt::TabSwitchingBehavior::
@@ -201,11 +201,12 @@
return permissions::PermissionPromptDisposition::ANCHORED_BUBBLE;
case PermissionPromptStyle::kChip:
return permissions::PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP;
- case PermissionPromptStyle::kQuiet: {
- permissions::PermissionRequestManager* manager =
- permissions::PermissionRequestManager::FromWebContents(web_contents_);
+ case PermissionPromptStyle::kQuietChip:
+ return permissions::PermissionPromptDisposition::
+ LOCATION_BAR_LEFT_QUIET_CHIP;
+ case PermissionPromptStyle::kLocationBarRightIcon: {
return permissions::PermissionUiSelector::ShouldSuppressAnimation(
- manager->ReasonForUsingQuietUi())
+ manager_->ReasonForUsingQuietUi())
? permissions::PermissionPromptDisposition::
LOCATION_BAR_RIGHT_STATIC_ICON
: permissions::PermissionPromptDisposition::
@@ -213,3 +214,109 @@
}
}
}
+
+void PermissionPromptImpl::OnWidgetClosing(views::Widget* widget) {
+ DCHECK_EQ(widget, prompt_bubble_->GetWidget());
+ widget->RemoveObserver(this);
+ prompt_bubble_ = nullptr;
+}
+
+bool PermissionPromptImpl::IsLocationBarDisplayed() {
+ LocationBarView* lbv = GetLocationBarView();
+ return lbv && lbv->IsDrawn();
+}
+
+void PermissionPromptImpl::SelectPwaPrompt() {
+ if (manager_->ShouldCurrentRequestUseQuietUI()) {
+ ShowQuietIcon();
+ } else {
+ ShowBubble();
+ }
+}
+
+void PermissionPromptImpl::SelectNormalPrompt() {
+ DCHECK(!manager_->ShouldCurrentRequestUseQuietUI());
+ if (ShouldCurrentRequestUseChip()) {
+ ShowChip();
+ } else {
+ ShowBubble();
+ }
+}
+
+void PermissionPromptImpl::SelectQuietPrompt() {
+ if (ShouldCurrentRequestUseQuietChip()) {
+ if (IsLocationBarDisplayed()) {
+ ShowChip();
+ } else {
+ // If LocationBar is not displayed (Fullscreen mode), display a default
+ // bubble only for non-abusive origins.
+ DCHECK(!manager_->ShouldDropCurrentRequestIfCannotShowQuietly());
+ ShowBubble();
+ }
+ } else {
+ ShowQuietIcon();
+ }
+}
+
+LocationBarView* PermissionPromptImpl::GetLocationBarView() {
+ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
+ return browser_view ? browser_view->GetLocationBarView() : nullptr;
+}
+
+void PermissionPromptImpl::ShowQuietIcon() {
+ prompt_style_ = PermissionPromptStyle::kLocationBarRightIcon;
+ // Shows the prompt as an indicator in the right side of the omnibox.
+ content_settings::UpdateLocationBarUiForWebContents(web_contents_);
+}
+
+void PermissionPromptImpl::ShowBubble() {
+ prompt_style_ = PermissionPromptStyle::kBubbleOnly;
+ prompt_bubble_ = new PermissionPromptBubbleView(
+ browser_, delegate_, permission_requested_time_, prompt_style_);
+ prompt_bubble_->Show();
+ prompt_bubble_->GetWidget()->AddObserver(this);
+}
+
+void PermissionPromptImpl::ShowChip() {
+ LocationBarView* lbv = GetLocationBarView();
+ DCHECK(lbv);
+
+ if (manager_->ShouldCurrentRequestUseQuietUI()) {
+ chip_ = lbv->DisplayQuietChip(
+ delegate_, !permissions::PermissionUiSelector::ShouldSuppressAnimation(
+ manager_->ReasonForUsingQuietUi()));
+ prompt_style_ = PermissionPromptStyle::kQuietChip;
+ } else {
+ chip_ = lbv->DisplayChip(delegate_);
+ prompt_style_ = PermissionPromptStyle::kChip;
+ }
+}
+
+bool PermissionPromptImpl::ShouldCurrentRequestUseChip() {
+ if (!base::FeatureList::IsEnabled(permissions::features::kPermissionChip))
+ return false;
+
+ std::vector<permissions::PermissionRequest*> requests = delegate_->Requests();
+ return std::all_of(requests.begin(), requests.end(), [](auto* request) {
+ return request->GetChipText().has_value();
+ });
+}
+
+bool PermissionPromptImpl::ShouldCurrentRequestUseQuietChip() {
+ if (!base::FeatureList::IsEnabled(
+ permissions::features::kPermissionQuietChip)) {
+ return false;
+ }
+
+ std::vector<permissions::PermissionRequest*> requests = delegate_->Requests();
+ return std::all_of(requests.begin(), requests.end(), [](auto* request) {
+ return request->GetRequestType() ==
+ permissions::RequestType::kNotifications ||
+ request->GetRequestType() == permissions::RequestType::kGeolocation;
+ });
+}
+
+void PermissionPromptImpl::FinalizeChip() {
+ GetLocationBarView()->FinalizeChip();
+ chip_ = nullptr;
+}
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
index a7e8586..915288e 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
@@ -18,6 +18,10 @@
class BubbleDialogDelegateView;
}
+namespace permissions {
+class PermissionRequestManager;
+}
+
namespace content {
class WebContents;
} // namespace content
@@ -49,10 +53,16 @@
void OnWidgetClosing(views::Widget* widget) override;
private:
+ bool IsLocationBarDisplayed();
+ void SelectPwaPrompt();
+ void SelectNormalPrompt();
+ void SelectQuietPrompt();
LocationBarView* GetLocationBarView();
+ void ShowQuietIcon();
void ShowBubble();
- void ShowChipUI();
- bool ShouldCurrentRequestUseChipUI();
+ void ShowChip();
+ bool ShouldCurrentRequestUseChip();
+ bool ShouldCurrentRequestUseQuietChip();
void FinalizeChip();
// The popup bubble. Not owned by this class; it will delete itself when a
@@ -72,6 +82,9 @@
base::TimeTicks permission_requested_time_;
+ // PermissionRequestManager owns `this` and outlives `PermissionPromptImpl`.
+ permissions::PermissionRequestManager* manager_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(PermissionPromptImpl);
};
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_style.h b/chrome/browser/ui/views/permission_bubble/permission_prompt_style.h
index 7a02f1c..b6231b1 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_style.h
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_style.h
@@ -12,7 +12,10 @@
// The permission chip view in the location bar.
kChip,
// The prompt as an indicator in the right side of the omnibox.
- kQuiet
+ kLocationBarRightIcon,
+ // The less prominent (quiet) version of permission chip view in the location
+ // bar.
+ kQuietChip
};
#endif // CHROME_BROWSER_UI_VIEWS_PERMISSION_BUBBLE_PERMISSION_PROMPT_STYLE_H_