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