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/pepper_broker_infobar_delegate.h" 6 7#include "base/prefs/pref_service.h" 8#include "chrome/browser/content_settings/host_content_settings_map.h" 9#include "chrome/browser/content_settings/tab_specific_content_settings.h" 10#include "chrome/browser/infobars/infobar_service.h" 11#include "chrome/browser/plugins/plugin_finder.h" 12#include "chrome/browser/plugins/plugin_metadata.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/pref_names.h" 15#include "content/public/browser/page_navigator.h" 16#include "content/public/browser/plugin_service.h" 17#include "content/public/browser/user_metrics.h" 18#include "content/public/browser/web_contents.h" 19#include "content/public/common/referrer.h" 20#include "content/public/common/webplugininfo.h" 21#include "grit/generated_resources.h" 22#include "grit/theme_resources.h" 23#include "net/base/net_util.h" 24#include "ui/base/l10n/l10n_util.h" 25 26#if defined(GOOGLE_TV) 27#include "base/android/context_types.h" 28#endif 29 30 31// static 32void PepperBrokerInfoBarDelegate::Create( 33 content::WebContents* web_contents, 34 const GURL& url, 35 const base::FilePath& plugin_path, 36 const base::Callback<void(bool)>& callback) { 37 Profile* profile = 38 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 39 // TODO(wad): Add ephemeral device ID support for broker in guest mode. 40 if (profile->IsGuestSession()) { 41 callback.Run(false); 42 return; 43 } 44 45 TabSpecificContentSettings* tab_content_settings = 46 TabSpecificContentSettings::FromWebContents(web_contents); 47 48#if defined(OS_CHROMEOS) 49 // On ChromeOS, we're ok with granting broker access to the Netflix and 50 // Widevine plugins, since they can only come installed with the OS. 51 const char kWidevinePluginFileName[] = "libwidevinecdmadapter.so"; 52 const char kNetflixDomain[] = "netflix.com"; 53 54 base::FilePath plugin_file_name = plugin_path.BaseName(); 55 if (plugin_file_name.value() == FILE_PATH_LITERAL(kWidevinePluginFileName) && 56 url.DomainIs(kNetflixDomain)) { 57 tab_content_settings->SetPepperBrokerAllowed(true); 58 callback.Run(true); 59 return; 60 } 61#endif 62 63#if defined(GOOGLE_TV) 64 // On GoogleTV, Netflix crypto/mdx plugin and DRM server adapter plugin can 65 // only come pre-installed with the OS, so we're willing to auto-grant access 66 // to them. PluginRootName should be matched with PEPPER_PLUGIN_ROOT 67 // in PepperPluginManager.java. 68 const char kPluginRootName[] = "/system/lib/pepperplugin"; 69 const char kNetflixCryptoPluginFileName[] = "libnrddpicrypto.so"; 70 const char kNetflixMdxPluginFileName[] = "libnrdmdx.so"; 71 const char kDrmServerAdapterPluginFileName[] = "libdrmserveradapter.so"; 72 base::FilePath::StringType plugin_dir_name = plugin_path.DirName().value(); 73 base::FilePath::StringType plugin_file_name = plugin_path.BaseName().value(); 74 if (base::android::IsRunningInWebapp() && 75 plugin_dir_name == FILE_PATH_LITERAL(kPluginRootName) && 76 (plugin_file_name == FILE_PATH_LITERAL(kNetflixCryptoPluginFileName) || 77 plugin_file_name == FILE_PATH_LITERAL(kNetflixMdxPluginFileName) || 78 plugin_file_name == 79 FILE_PATH_LITERAL(kDrmServerAdapterPluginFileName))) { 80 tab_content_settings->SetPepperBrokerAllowed(true); 81 callback.Run(true); 82 return; 83 } 84#endif 85 86 HostContentSettingsMap* content_settings = 87 profile->GetHostContentSettingsMap(); 88 ContentSetting setting = 89 content_settings->GetContentSetting(url, url, 90 CONTENT_SETTINGS_TYPE_PPAPI_BROKER, 91 std::string()); 92 93 if (setting == CONTENT_SETTING_ASK) { 94 content::RecordAction( 95 content::UserMetricsAction("PPAPI.BrokerInfobarDisplayed")); 96 InfoBarService* infobar_service = 97 InfoBarService::FromWebContents(web_contents); 98 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 99 new PepperBrokerInfoBarDelegate( 100 infobar_service, url, plugin_path, 101 profile->GetPrefs()->GetString(prefs::kAcceptLanguages), 102 content_settings, tab_content_settings, callback))); 103 return; 104 } 105 106 bool allowed = (setting == CONTENT_SETTING_ALLOW); 107 content::RecordAction(allowed ? 108 content::UserMetricsAction("PPAPI.BrokerSettingAllow") : 109 content::UserMetricsAction("PPAPI.BrokerSettingDeny")); 110 tab_content_settings->SetPepperBrokerAllowed(allowed); 111 callback.Run(allowed); 112} 113 114PepperBrokerInfoBarDelegate::PepperBrokerInfoBarDelegate( 115 InfoBarService* infobar_service, 116 const GURL& url, 117 const base::FilePath& plugin_path, 118 const std::string& languages, 119 HostContentSettingsMap* content_settings, 120 TabSpecificContentSettings* tab_content_settings, 121 const base::Callback<void(bool)>& callback) 122 : ConfirmInfoBarDelegate(infobar_service), 123 url_(url), 124 plugin_path_(plugin_path), 125 languages_(languages), 126 content_settings_(content_settings), 127 tab_content_settings_(tab_content_settings), 128 callback_(callback) { 129} 130 131PepperBrokerInfoBarDelegate::~PepperBrokerInfoBarDelegate() { 132 if (!callback_.is_null()) 133 callback_.Run(false); 134} 135 136int PepperBrokerInfoBarDelegate::GetIconID() const { 137 return IDR_INFOBAR_PLUGIN_INSTALL; 138} 139 140string16 PepperBrokerInfoBarDelegate::GetMessageText() const { 141 content::PluginService* plugin_service = 142 content::PluginService::GetInstance(); 143 content::WebPluginInfo plugin; 144 bool success = plugin_service->GetPluginInfoByPath(plugin_path_, &plugin); 145 DCHECK(success); 146 scoped_ptr<PluginMetadata> plugin_metadata( 147 PluginFinder::GetInstance()->GetPluginMetadata(plugin)); 148 return l10n_util::GetStringFUTF16(IDS_PEPPER_BROKER_MESSAGE, 149 plugin_metadata->name(), 150 net::FormatUrl(url_.GetOrigin(), 151 languages_)); 152} 153 154string16 PepperBrokerInfoBarDelegate::GetButtonLabel( 155 InfoBarButton button) const { 156 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 157 IDS_PEPPER_BROKER_ALLOW_BUTTON : IDS_PEPPER_BROKER_DENY_BUTTON); 158} 159 160bool PepperBrokerInfoBarDelegate::Accept() { 161 DispatchCallback(true); 162 return true; 163} 164 165bool PepperBrokerInfoBarDelegate::Cancel() { 166 DispatchCallback(false); 167 return true; 168} 169 170string16 PepperBrokerInfoBarDelegate::GetLinkText() const { 171 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 172} 173 174bool PepperBrokerInfoBarDelegate::LinkClicked( 175 WindowOpenDisposition disposition) { 176 GURL learn_more_url("https://support.google.com/chrome/?p=ib_pepper_broker"); 177 web_contents()->OpenURL(content::OpenURLParams( 178 learn_more_url, content::Referrer(), 179 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition, 180 content::PAGE_TRANSITION_LINK, false)); 181 return false; 182} 183 184void PepperBrokerInfoBarDelegate::DispatchCallback(bool result) { 185 content::RecordAction(result ? 186 content::UserMetricsAction("PPAPI.BrokerInfobarClickedAllow") : 187 content::UserMetricsAction("PPAPI.BrokerInfobarClickedDeny")); 188 callback_.Run(result); 189 callback_ = base::Callback<void(bool)>(); 190 content_settings_->SetContentSetting( 191 ContentSettingsPattern::FromURLNoWildcard(url_), 192 ContentSettingsPattern::Wildcard(), 193 CONTENT_SETTINGS_TYPE_PPAPI_BROKER, 194 std::string(), result ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); 195 tab_content_settings_->SetPepperBrokerAllowed(result); 196} 197