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 21 class 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 62 void 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 72 ThreeDAPIInfoBarDelegate::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 82 ThreeDAPIInfoBarDelegate::~ThreeDAPIInfoBarDelegate() { 83 if (message_text_queried_ && !action_taken_) { 84 UMA_HISTOGRAM_ENUMERATION("GPU.ThreeDAPIInfoBarDismissal", 85 CLOSED_WITHOUT_ACTION, DISMISSAL_MAX); 86 } 87 } 88 89 bool 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 98 int ThreeDAPIInfoBarDelegate::GetIconID() const { 99 return IDR_INFOBAR_3D_BLOCKED; 100 } 101 102 base::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 119 base::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 126 bool ThreeDAPIInfoBarDelegate::Accept() { 127 action_taken_ = true; 128 UMA_HISTOGRAM_ENUMERATION("GPU.ThreeDAPIInfoBarDismissal", IGNORED, 129 DISMISSAL_MAX); 130 return true; 131 } 132 133 bool 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 143 base::string16 ThreeDAPIInfoBarDelegate::GetLinkText() const { 144 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 145 } 146 147 bool 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 160 ThreeDAPIObserver::ThreeDAPIObserver() { 161 content::GpuDataManager::GetInstance()->AddObserver(this); 162 } 163 164 ThreeDAPIObserver::~ThreeDAPIObserver() { 165 content::GpuDataManager::GetInstance()->RemoveObserver(this); 166 } 167 168 void 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