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