1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/gpu/three_d_api_observer.h" 6 7#include "base/metrics/histogram.h" 8#include "chrome/browser/infobars/infobar_service.h" 9#include "chrome/browser/tab_contents/tab_util.h" 10#include "chrome/grit/generated_resources.h" 11#include "components/infobars/core/confirm_infobar_delegate.h" 12#include "components/infobars/core/infobar.h" 13#include "content/public/browser/gpu_data_manager.h" 14#include "grit/components_strings.h" 15#include "grit/theme_resources.h" 16#include "ui/base/l10n/l10n_util.h" 17 18 19// ThreeDAPIInfoBarDelegate --------------------------------------------------- 20 21class ThreeDAPIInfoBarDelegate : public ConfirmInfoBarDelegate { 22 public: 23 // Creates a 3D API infobar and delegate and adds the infobar to 24 // |infobar_service|. 25 static void Create(InfoBarService* infobar_service, 26 const GURL& url, 27 content::ThreeDAPIType requester); 28 29 private: 30 enum DismissalHistogram { 31 IGNORED, 32 RELOADED, 33 CLOSED_WITHOUT_ACTION, 34 DISMISSAL_MAX 35 }; 36 37 ThreeDAPIInfoBarDelegate(const GURL& url, content::ThreeDAPIType requester); 38 virtual ~ThreeDAPIInfoBarDelegate(); 39 40 // ConfirmInfoBarDelegate: 41 virtual bool EqualsDelegate( 42 infobars::InfoBarDelegate* delegate) const OVERRIDE; 43 virtual int GetIconID() const OVERRIDE; 44 virtual base::string16 GetMessageText() const OVERRIDE; 45 virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; 46 virtual bool Accept() OVERRIDE; 47 virtual bool Cancel() OVERRIDE; 48 virtual base::string16 GetLinkText() const OVERRIDE; 49 virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE; 50 51 GURL url_; 52 content::ThreeDAPIType requester_; 53 // Basically indicates whether the infobar was displayed at all, or 54 // was a temporary instance thrown away by the InfobarService. 55 mutable bool message_text_queried_; 56 bool action_taken_; 57 58 DISALLOW_COPY_AND_ASSIGN(ThreeDAPIInfoBarDelegate); 59}; 60 61// static 62void ThreeDAPIInfoBarDelegate::Create(InfoBarService* infobar_service, 63 const GURL& url, 64 content::ThreeDAPIType requester) { 65 if (!infobar_service) 66 return; // NULL for apps. 67 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar( 68 scoped_ptr<ConfirmInfoBarDelegate>( 69 new ThreeDAPIInfoBarDelegate(url, requester)))); 70} 71 72ThreeDAPIInfoBarDelegate::ThreeDAPIInfoBarDelegate( 73 const GURL& url, 74 content::ThreeDAPIType requester) 75 : ConfirmInfoBarDelegate(), 76 url_(url), 77 requester_(requester), 78 message_text_queried_(false), 79 action_taken_(false) { 80} 81 82ThreeDAPIInfoBarDelegate::~ThreeDAPIInfoBarDelegate() { 83 if (message_text_queried_ && !action_taken_) { 84 UMA_HISTOGRAM_ENUMERATION("GPU.ThreeDAPIInfoBarDismissal", 85 CLOSED_WITHOUT_ACTION, DISMISSAL_MAX); 86 } 87} 88 89bool ThreeDAPIInfoBarDelegate::EqualsDelegate( 90 infobars::InfoBarDelegate* delegate) const { 91 // For the time being, if a given web page is actually using both 92 // WebGL and Pepper 3D and both APIs are blocked, just leave the 93 // first infobar up. If the user selects "try again", both APIs will 94 // be unblocked and the web page reload will succeed. 95 return delegate->GetIconID() == GetIconID(); 96} 97 98int ThreeDAPIInfoBarDelegate::GetIconID() const { 99 return IDR_INFOBAR_3D_BLOCKED; 100} 101 102base::string16 ThreeDAPIInfoBarDelegate::GetMessageText() const { 103 message_text_queried_ = true; 104 105 base::string16 api_name; 106 switch (requester_) { 107 case content::THREE_D_API_TYPE_WEBGL: 108 api_name = l10n_util::GetStringUTF16(IDS_3D_APIS_WEBGL_NAME); 109 break; 110 case content::THREE_D_API_TYPE_PEPPER_3D: 111 api_name = l10n_util::GetStringUTF16(IDS_3D_APIS_PEPPER_3D_NAME); 112 break; 113 } 114 115 return l10n_util::GetStringFUTF16(IDS_3D_APIS_BLOCKED_TEXT, 116 api_name); 117} 118 119base::string16 ThreeDAPIInfoBarDelegate::GetButtonLabel( 120 InfoBarButton button) const { 121 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 122 IDS_3D_APIS_BLOCKED_OK_BUTTON_LABEL : 123 IDS_3D_APIS_BLOCKED_TRY_AGAIN_BUTTON_LABEL); 124} 125 126bool ThreeDAPIInfoBarDelegate::Accept() { 127 action_taken_ = true; 128 UMA_HISTOGRAM_ENUMERATION("GPU.ThreeDAPIInfoBarDismissal", IGNORED, 129 DISMISSAL_MAX); 130 return true; 131} 132 133bool ThreeDAPIInfoBarDelegate::Cancel() { 134 action_taken_ = true; 135 UMA_HISTOGRAM_ENUMERATION("GPU.ThreeDAPIInfoBarDismissal", RELOADED, 136 DISMISSAL_MAX); 137 content::GpuDataManager::GetInstance()->UnblockDomainFrom3DAPIs(url_); 138 InfoBarService::WebContentsFromInfoBar(infobar())->GetController().Reload( 139 true); 140 return true; 141} 142 143base::string16 ThreeDAPIInfoBarDelegate::GetLinkText() const { 144 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 145} 146 147bool ThreeDAPIInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) { 148 InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL( 149 content::OpenURLParams( 150 GURL("https://support.google.com/chrome/?p=ib_webgl"), 151 content::Referrer(), 152 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition, 153 ui::PAGE_TRANSITION_LINK, false)); 154 return false; 155} 156 157 158// ThreeDAPIObserver ---------------------------------------------------------- 159 160ThreeDAPIObserver::ThreeDAPIObserver() { 161 content::GpuDataManager::GetInstance()->AddObserver(this); 162} 163 164ThreeDAPIObserver::~ThreeDAPIObserver() { 165 content::GpuDataManager::GetInstance()->RemoveObserver(this); 166} 167 168void ThreeDAPIObserver::DidBlock3DAPIs(const GURL& url, 169 int render_process_id, 170 int render_view_id, 171 content::ThreeDAPIType requester) { 172 content::WebContents* web_contents = tab_util::GetWebContentsByID( 173 render_process_id, render_view_id); 174 if (!web_contents) 175 return; 176 ThreeDAPIInfoBarDelegate::Create( 177 InfoBarService::FromWebContents(web_contents), url, requester); 178} 179