|  | // Copyright 2019 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/renderer_context_menu/accessibility_labels_menu_observer.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/metrics/histogram_macros.h" | 
|  | #include "base/strings/utf_string_conversions.h" | 
|  | #include "chrome/app/chrome_command_ids.h" | 
|  | #include "chrome/browser/accessibility/accessibility_labels_service.h" | 
|  | #include "chrome/browser/accessibility/accessibility_labels_service_factory.h" | 
|  | #include "chrome/browser/accessibility/accessibility_state_utils.h" | 
|  | #include "chrome/browser/profiles/profile.h" | 
|  | #include "chrome/browser/renderer_context_menu/accessibility_labels_bubble_model.h" | 
|  | #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" | 
|  | #include "chrome/browser/ui/confirm_bubble.h" | 
|  | #include "chrome/common/pref_names.h" | 
|  | #include "chrome/grit/generated_resources.h" | 
|  | #include "components/prefs/pref_service.h" | 
|  | #include "content/public/browser/browser_thread.h" | 
|  | #include "content/public/browser/context_menu_params.h" | 
|  | #include "content/public/browser/render_view_host.h" | 
|  | #include "content/public/browser/render_widget_host.h" | 
|  | #include "content/public/browser/render_widget_host_view.h" | 
|  | #include "content/public/browser/web_contents.h" | 
|  | #include "content/public/common/content_features.h" | 
|  | #include "ui/base/l10n/l10n_util.h" | 
|  | #include "ui/gfx/geometry/rect.h" | 
|  |  | 
|  | using content::BrowserThread; | 
|  |  | 
|  | AccessibilityLabelsMenuObserver::AccessibilityLabelsMenuObserver( | 
|  | RenderViewContextMenuProxy* proxy) | 
|  | : proxy_(proxy) {} | 
|  |  | 
|  | AccessibilityLabelsMenuObserver::~AccessibilityLabelsMenuObserver() {} | 
|  |  | 
|  | void AccessibilityLabelsMenuObserver::InitMenu( | 
|  | const content::ContextMenuParams& params) { | 
|  | Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext()); | 
|  | if (ShouldShowLabelsItem()) { | 
|  | proxy_->AddAccessibilityLabelsServiceItem(profile->GetPrefs()->GetBoolean( | 
|  | prefs::kAccessibilityImageLabelsEnabled)); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool AccessibilityLabelsMenuObserver::IsCommandIdSupported(int command_id) { | 
|  | return command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE; | 
|  | } | 
|  |  | 
|  | bool AccessibilityLabelsMenuObserver::IsCommandIdChecked(int command_id) { | 
|  | DCHECK(IsCommandIdSupported(command_id)); | 
|  | Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext()); | 
|  |  | 
|  | if (command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE) { | 
|  | return profile->GetPrefs()->GetBoolean( | 
|  | prefs::kAccessibilityImageLabelsEnabled); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool AccessibilityLabelsMenuObserver::IsCommandIdEnabled(int command_id) { | 
|  | DCHECK(IsCommandIdSupported(command_id)); | 
|  | if (command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS || | 
|  | command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE) { | 
|  | return ShouldShowLabelsItem(); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void AccessibilityLabelsMenuObserver::ExecuteCommand(int command_id) { | 
|  | DCHECK(IsCommandIdSupported(command_id)); | 
|  | Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext()); | 
|  | if (command_id == IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE) { | 
|  | // When a user enables the accessibility labeling item, we | 
|  | // show a bubble to confirm it. On the other hand, when a user disables this | 
|  | // item, we directly update/ the profile and stop integrating the labels | 
|  | // service immediately. | 
|  | if (!profile->GetPrefs()->GetBoolean( | 
|  | prefs::kAccessibilityImageLabelsEnabled)) { | 
|  | // Always show the confirm bubble when enabling the full feature, | 
|  | // regardless of whether it's been shown before. | 
|  | ShowConfirmBubble(profile, true /* enable always */); | 
|  | } else { | 
|  | profile->GetPrefs()->SetBoolean(prefs::kAccessibilityImageLabelsEnabled, | 
|  | false); | 
|  | } | 
|  | } else if (command_id == | 
|  | IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE) { | 
|  | // Only show the confirm bubble if it's never been shown before. | 
|  | if (!profile->GetPrefs()->GetBoolean( | 
|  | prefs::kAccessibilityImageLabelsOptInAccepted)) { | 
|  | ShowConfirmBubble(profile, false /* enable once only */); | 
|  | } else { | 
|  | AccessibilityLabelsServiceFactory::GetForProfile(profile) | 
|  | ->EnableLabelsServiceOnce(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | bool AccessibilityLabelsMenuObserver::ShouldShowLabelsItem() { | 
|  | // Hidden behind a feature flag. | 
|  | if (!base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels)) | 
|  | return false; | 
|  |  | 
|  | // Disabled by policy. | 
|  | Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext()); | 
|  | if (!profile->GetPrefs()->GetBoolean( | 
|  | prefs::kAccessibilityImageLabelsEnabled) && | 
|  | profile->GetPrefs()->IsManagedPreference( | 
|  | prefs::kAccessibilityImageLabelsEnabled)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return accessibility_state_utils::IsScreenReaderEnabled(); | 
|  | } | 
|  |  | 
|  | void AccessibilityLabelsMenuObserver::ShowConfirmBubble(Profile* profile, | 
|  | bool enable_always) { | 
|  | content::WebContents* web_contents = proxy_->GetWebContents(); | 
|  | content::RenderWidgetHostView* view = | 
|  | proxy_->GetRenderViewHost()->GetWidget()->GetView(); | 
|  | gfx::Rect rect = view->GetViewBounds(); | 
|  | auto model = std::make_unique<AccessibilityLabelsBubbleModel>( | 
|  | profile, web_contents, enable_always); | 
|  | chrome::ShowConfirmBubble( | 
|  | web_contents->GetTopLevelNativeWindow(), view->GetNativeView(), | 
|  | gfx::Point(rect.CenterPoint().x(), rect.y()), std::move(model)); | 
|  | } |