Commit b5f7a773 authored by Kamila's avatar Kamila Committed by Commit Bot

Auto-open bubble after for recently accepted media permissions

If a media (camera/mic/camera+mic) permission was recently accepted on a
site level, but it was blocked on a system level, auto open bubble
that leads users to system permissions.

Situation this will be triggered:
1) Site asks for media permission.
2) Permission prompt shows on the left side of the omnibox.
3) User accepts the permission prompt.
4) Blocked icon appears on the right side of the omnibox & the bubble
which gives the user the option to "Open system preferences" auto-opens.

Note that if mic and camera are requested individually, the bubble will
auto-open for each of them once.

Change-Id: I611b4f256ca4f0793d2e97bb8bc8bc4cd12babe1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1897659
Commit-Queue: Kamila Hasanbega <hkamila@google.com>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713354}
parent b3a886f1
...@@ -329,6 +329,10 @@ void ContentSettingImageModel::Update(content::WebContents* contents) { ...@@ -329,6 +329,10 @@ void ContentSettingImageModel::Update(content::WebContents* contents) {
ContentSettingImageModelStates::Get(contents)->SetAccessibilityNotified( ContentSettingImageModelStates::Get(contents)->SetAccessibilityNotified(
image_type(), false); image_type(), false);
} }
if (should_auto_open_bubble_) {
ContentSettingImageModelStates::Get(contents)->SetBubbleWasAutoOpened(
image_type(), false);
}
} }
} }
...@@ -359,6 +363,19 @@ void ContentSettingImageModel::AccessibilityWasNotified( ...@@ -359,6 +363,19 @@ void ContentSettingImageModel::AccessibilityWasNotified(
image_type(), true); image_type(), true);
} }
bool ContentSettingImageModel::ShouldAutoOpenBubble(
content::WebContents* contents) {
return should_auto_open_bubble_ &&
!ContentSettingImageModelStates::Get(contents)->BubbleWasAutoOpened(
image_type());
}
void ContentSettingImageModel::SetBubbleWasAutoOpened(
content::WebContents* contents) {
ContentSettingImageModelStates::Get(contents)->SetBubbleWasAutoOpened(
image_type(), true);
}
// Generic blocked content settings -------------------------------------------- // Generic blocked content settings --------------------------------------------
ContentSettingBlockedImageModel::ContentSettingBlockedImageModel( ContentSettingBlockedImageModel::ContentSettingBlockedImageModel(
...@@ -611,13 +628,15 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility( ...@@ -611,13 +628,15 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility(
DidMicAccessFailBecauseOfSystemLevelBlock()) { DidMicAccessFailBecauseOfSystemLevelBlock()) {
set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon);
set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED)); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED));
if (!content_settings->camera_was_just_granted_on_site_level() || if (content_settings->camera_was_just_granted_on_site_level() ||
!content_settings->mic_was_just_granted_on_site_level()) { content_settings->mic_was_just_granted_on_site_level()) {
// Automatically trigger the new bubble, if the camera
// and/or mic was just granted on a site level, but blocked on a
// system level.
set_should_auto_open_bubble(true);
} else {
set_explanatory_string_id(IDS_CAMERA_TURNED_OFF); set_explanatory_string_id(IDS_CAMERA_TURNED_OFF);
} }
// TODO(hkamila): Automatically trigger the new bubble, if the camera
// and/or mic was just granted on a site level, but blocked on a system
// level.
} else { } else {
set_icon(vector_icons::kVideocamIcon, gfx::kNoneIcon); set_icon(vector_icons::kVideocamIcon, gfx::kNoneIcon);
set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_ALLOWED)); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_ALLOWED));
...@@ -632,7 +651,9 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility( ...@@ -632,7 +651,9 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility(
} else if (DidCameraAccessFailBecauseOfSystemLevelBlock()) { } else if (DidCameraAccessFailBecauseOfSystemLevelBlock()) {
set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon);
set_tooltip(l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED)); set_tooltip(l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED));
if (!content_settings->camera_was_just_granted_on_site_level()) { if (content_settings->camera_was_just_granted_on_site_level()) {
set_should_auto_open_bubble(true);
} else {
set_explanatory_string_id(IDS_CAMERA_TURNED_OFF); set_explanatory_string_id(IDS_CAMERA_TURNED_OFF);
} }
} else { } else {
...@@ -649,7 +670,9 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility( ...@@ -649,7 +670,9 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility(
} else if (DidMicAccessFailBecauseOfSystemLevelBlock()) { } else if (DidMicAccessFailBecauseOfSystemLevelBlock()) {
set_icon(vector_icons::kMicIcon, kBlockedBadgeIcon); set_icon(vector_icons::kMicIcon, kBlockedBadgeIcon);
set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED)); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED));
if (!content_settings->mic_was_just_granted_on_site_level()) { if (content_settings->mic_was_just_granted_on_site_level()) {
set_should_auto_open_bubble(true);
} else {
set_explanatory_string_id(IDS_MIC_TURNED_OFF); set_explanatory_string_id(IDS_MIC_TURNED_OFF);
} }
} else { } else {
......
...@@ -82,6 +82,13 @@ class ContentSettingImageModel { ...@@ -82,6 +82,13 @@ class ContentSettingImageModel {
// so that we do not restart it when the parent view is updated. // so that we do not restart it when the parent view is updated.
void SetAnimationHasRun(content::WebContents* web_contents); void SetAnimationHasRun(content::WebContents* web_contents);
// Whether to automatically trigger the new bubble.
bool ShouldAutoOpenBubble(content::WebContents* contents);
// Remembers that the bubble was auto-opened for the given |web_contents|,
// so that we do not auto-open it again when the parent view is updated.
void SetBubbleWasAutoOpened(content::WebContents* contents);
bool is_visible() const { return is_visible_; } bool is_visible() const { return is_visible_; }
// Retrieve the icon that represents this content setting. Blocked content // Retrieve the icon that represents this content setting. Blocked content
...@@ -125,6 +132,9 @@ class ContentSettingImageModel { ...@@ -125,6 +132,9 @@ class ContentSettingImageModel {
} }
void set_tooltip(const base::string16& tooltip) { tooltip_ = tooltip; } void set_tooltip(const base::string16& tooltip) { tooltip_ = tooltip; }
void set_should_auto_open_bubble(const bool should_auto_open_bubble) {
should_auto_open_bubble_ = should_auto_open_bubble;
}
private: private:
bool is_visible_ = false; bool is_visible_ = false;
...@@ -135,7 +145,7 @@ class ContentSettingImageModel { ...@@ -135,7 +145,7 @@ class ContentSettingImageModel {
base::string16 tooltip_; base::string16 tooltip_;
const ImageType image_type_; const ImageType image_type_;
const bool image_type_should_notify_accessibility_; const bool image_type_should_notify_accessibility_;
bool should_auto_open_bubble_ = false;
DISALLOW_COPY_AND_ASSIGN(ContentSettingImageModel); DISALLOW_COPY_AND_ASSIGN(ContentSettingImageModel);
}; };
......
...@@ -48,6 +48,18 @@ bool ContentSettingImageModelStates::GetAccessibilityNotified( ...@@ -48,6 +48,18 @@ bool ContentSettingImageModelStates::GetAccessibilityNotified(
return accessibility_notified_[static_cast<int>(type)]; return accessibility_notified_[static_cast<int>(type)];
} }
void ContentSettingImageModelStates::SetBubbleWasAutoOpened(
ImageType type,
bool bubble_was_auto_opened) {
VerifyType(type);
auto_opened_bubbles_[static_cast<int>(type)] = bubble_was_auto_opened;
}
bool ContentSettingImageModelStates::BubbleWasAutoOpened(ImageType type) const {
VerifyType(type);
return auto_opened_bubbles_[static_cast<int>(type)];
}
ContentSettingImageModelStates::ContentSettingImageModelStates( ContentSettingImageModelStates::ContentSettingImageModelStates(
content::WebContents* contents) {} content::WebContents* contents) {}
......
...@@ -27,6 +27,9 @@ class ContentSettingImageModelStates ...@@ -27,6 +27,9 @@ class ContentSettingImageModelStates
void SetAccessibilityNotified(ImageType type, bool notified); void SetAccessibilityNotified(ImageType type, bool notified);
bool GetAccessibilityNotified(ImageType type) const; bool GetAccessibilityNotified(ImageType type) const;
void SetBubbleWasAutoOpened(ImageType type, bool animation_has_run);
bool BubbleWasAutoOpened(ImageType type) const;
private: private:
friend class content::WebContentsUserData<ContentSettingImageModelStates>; friend class content::WebContentsUserData<ContentSettingImageModelStates>;
explicit ContentSettingImageModelStates(content::WebContents* contents); explicit ContentSettingImageModelStates(content::WebContents* contents);
...@@ -45,6 +48,10 @@ class ContentSettingImageModelStates ...@@ -45,6 +48,10 @@ class ContentSettingImageModelStates
bool accessibility_notified_[static_cast<int>(ImageType::NUM_IMAGE_TYPES)] = bool accessibility_notified_[static_cast<int>(ImageType::NUM_IMAGE_TYPES)] =
{}; {};
// Array of bool for whether the bubble was auto-opened for a given image
// model. This bit is reset to false when the image is hidden.
bool auto_opened_bubbles_[static_cast<int>(ImageType::NUM_IMAGE_TYPES)] = {};
WEB_CONTENTS_USER_DATA_KEY_DECL(); WEB_CONTENTS_USER_DATA_KEY_DECL();
DISALLOW_COPY_AND_ASSIGN(ContentSettingImageModelStates); DISALLOW_COPY_AND_ASSIGN(ContentSettingImageModelStates);
......
...@@ -110,6 +110,11 @@ void ContentSettingImageView::Update() { ...@@ -110,6 +110,11 @@ void ContentSettingImageView::Update() {
content_setting_image_model_->AccessibilityWasNotified(web_contents); content_setting_image_model_->AccessibilityWasNotified(web_contents);
} }
if (content_setting_image_model_->ShouldAutoOpenBubble(web_contents)) {
ShowBubbleImpl();
content_setting_image_model_->SetBubbleWasAutoOpened(web_contents);
}
// If the content usage or blockage should be indicated to the user, start the // If the content usage or blockage should be indicated to the user, start the
// animation and record that the icon has been shown. // animation and record that the icon has been shown.
if (!can_animate_ || if (!can_animate_ ||
...@@ -174,6 +179,10 @@ bool ContentSettingImageView::ShouldShowSeparator() const { ...@@ -174,6 +179,10 @@ bool ContentSettingImageView::ShouldShowSeparator() const {
} }
bool ContentSettingImageView::ShowBubble(const ui::Event& event) { bool ContentSettingImageView::ShowBubble(const ui::Event& event) {
return ShowBubbleImpl();
}
bool ContentSettingImageView::ShowBubbleImpl() {
PauseAnimation(); PauseAnimation();
content::WebContents* web_contents = content::WebContents* web_contents =
delegate_->GetContentSettingWebContents(); delegate_->GetContentSettingWebContents();
......
...@@ -67,6 +67,8 @@ class ContentSettingImageView : public IconLabelBubbleView, ...@@ -67,6 +67,8 @@ class ContentSettingImageView : public IconLabelBubbleView,
void disable_animation() { can_animate_ = false; } void disable_animation() { can_animate_ = false; }
bool ShowBubbleImpl();
// IconLabelBubbleView: // IconLabelBubbleView:
const char* GetClassName() const override; const char* GetClassName() const override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment