plugin_info_message_filter.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/plugins/plugin_info_message_filter.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/metrics/histogram.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/prefs/pref_service.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_utils.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/plugins/plugin_finder.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/plugins/plugin_metadata.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/plugins/plugin_prefs.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/common/content_settings.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/common/pref_names.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/render_messages.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/plugin_service.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/plugin_service_filter.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "url/gurl.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS)
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/guest_view/web_view/web_view_renderer_state.h"
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_WIN)
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/win/metro.h"
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(DISABLE_NACL)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/nacl/common/nacl_constants.h"
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using content::PluginService;
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using content::WebPluginInfo;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// For certain sandboxed Pepper plugins, use the JavaScript Content Settings.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS &&
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(DISABLE_NACL)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Treat Native Client invocations like JavaScript.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (plugin.name == base::ASCIIToUTF16(nacl::kNaClPluginName))
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Treat CDM invocations like JavaScript.
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (plugin.name == base::ASCIIToUTF16(kWidevineCdmDisplayName)) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum PluginAvailabilityStatusForUMA {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PLUGIN_NOT_REGISTERED,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PLUGIN_AVAILABLE,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PLUGIN_DISABLED,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PLUGIN_AVAILABILITY_STATUS_MAX
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void SendPluginAvailabilityUMA(const std::string& mime_type,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      PluginAvailabilityStatusForUMA status) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(WIDEVINE_CDM_AVAILABLE)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only report results for Widevine CDM.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mime_type != kWidevineCdmPluginMimeType)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Plugin.AvailabilityStatus.WidevineCdm",
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            status, PLUGIN_AVAILABILITY_STATUS_MAX);
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif  // defined(WIDEVINE_CDM_AVAILABLE)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif  // defined(ENABLE_PEPPER_CDMS)
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PluginInfoMessageFilter::Context::Context(int render_process_id,
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          Profile* profile)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : render_process_id_(render_process_id),
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      resource_context_(profile->GetResourceContext()),
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_content_settings_map_(profile->GetHostContentSettingsMap()),
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      plugin_prefs_(PluginPrefs::GetForProfile(profile)) {
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  allow_outdated_plugins_.Init(prefs::kPluginsAllowOutdated,
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               profile->GetPrefs());
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  allow_outdated_plugins_.MoveToThread(
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::GetMessageLoopProxyForThread(
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          content::BrowserThread::IO));
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  always_authorize_plugins_.Init(prefs::kPluginsAlwaysAuthorize,
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 profile->GetPrefs());
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  always_authorize_plugins_.MoveToThread(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::BrowserThread::GetMessageLoopProxyForThread(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          content::BrowserThread::IO));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginInfoMessageFilter::Context::~Context() {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginInfoMessageFilter::PluginInfoMessageFilter(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int render_process_id,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : BrowserMessageFilter(ChromeMsgStart),
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context_(render_process_id, profile),
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      weak_ptr_factory_(this) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PluginInfoMessageFilter::OnMessageReceived(const IPC::Message& message) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PluginInfoMessageFilter, message)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetPluginInfo,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    OnGetPluginInfo)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ChromeViewHostMsg_IsInternalPluginAvailableForMimeType,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        OnIsInternalPluginAvailableForMimeType)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(return false)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PluginInfoMessageFilter::OnDestruct() const {
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const_cast<PluginInfoMessageFilter*>(this)->
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      weak_ptr_factory_.InvalidateWeakPtrs();
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Destroy on the UI thread because we contain a |PrefMember|.
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::DeleteOnUIThread::Destruct(this);
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PluginInfoMessageFilter::~PluginInfoMessageFilter() {}
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct PluginInfoMessageFilter::GetPluginInfo_Params {
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int render_frame_id;
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL url;
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL top_origin_url;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string mime_type;
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PluginInfoMessageFilter::OnGetPluginInfo(
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int render_frame_id,
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GURL& url,
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GURL& top_origin_url,
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& mime_type,
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    IPC::Message* reply_msg) {
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetPluginInfo_Params params = {
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    render_frame_id,
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    url,
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    top_origin_url,
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    mime_type
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  };
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PluginService::GetInstance()->GetPlugins(
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&PluginInfoMessageFilter::PluginsLoaded,
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 params, reply_msg));
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PluginInfoMessageFilter::PluginsLoaded(
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GetPluginInfo_Params& params,
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IPC::Message* reply_msg,
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::vector<WebPluginInfo>& plugins) {
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ChromeViewHostMsg_GetPluginInfo_Output output;
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This also fills in |actual_mime_type|.
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<PluginMetadata> plugin_metadata;
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (context_.FindEnabledPlugin(params.render_frame_id, params.url,
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 params.top_origin_url, params.mime_type,
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 &output.status, &output.plugin,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &output.actual_mime_type,
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 &plugin_metadata)) {
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    context_.DecidePluginStatus(params, output.plugin, plugin_metadata.get(),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                &output.status);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (plugin_metadata) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output.group_identifier = plugin_metadata->identifier();
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output.group_name = plugin_metadata->name();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context_.MaybeGrantAccess(output.status, output.plugin.path);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ChromeViewHostMsg_GetPluginInfo::WriteReplyParams(reply_msg, output);
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Send(reply_msg);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PluginInfoMessageFilter::OnIsInternalPluginAvailableForMimeType(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& mime_type,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* is_available,
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::string16>* additional_param_names,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::string16>* additional_param_values) {
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<WebPluginInfo> plugins;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PluginService::GetInstance()->GetInternalPlugins(&plugins);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_plugin_disabled = false;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < plugins.size(); ++i) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const WebPluginInfo& plugin = plugins[i];
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<content::WebPluginMimeType>& mime_types =
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        plugin.mime_types;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t j = 0; j < mime_types.size(); ++j) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (mime_types[j].mime_type == mime_type) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!context_.IsPluginEnabled(plugin)) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          is_plugin_disabled = true;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222        *is_available = true;
223        *additional_param_names = mime_types[j].additional_param_names;
224        *additional_param_values = mime_types[j].additional_param_values;
225        SendPluginAvailabilityUMA(mime_type, PLUGIN_AVAILABLE);
226        return;
227      }
228    }
229  }
230
231  *is_available = false;
232  SendPluginAvailabilityUMA(
233      mime_type, is_plugin_disabled ? PLUGIN_DISABLED : PLUGIN_NOT_REGISTERED);
234}
235
236#endif // defined(ENABLE_PEPPER_CDMS)
237
238void PluginInfoMessageFilter::Context::DecidePluginStatus(
239    const GetPluginInfo_Params& params,
240    const WebPluginInfo& plugin,
241    const PluginMetadata* plugin_metadata,
242    ChromeViewHostMsg_GetPluginInfo_Status* status) const {
243#if defined(OS_WIN)
244  if (plugin.type == WebPluginInfo::PLUGIN_TYPE_NPAPI &&
245      base::win::IsMetroProcess()) {
246    status->value =
247        ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported;
248    return;
249  }
250#endif
251  if (plugin.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
252    CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
253    // NPAPI plugins are not supported inside <webview> guests.
254#if defined(ENABLE_EXTENSIONS)
255    if (extensions::WebViewRendererState::GetInstance()->IsGuest(
256        render_process_id_)) {
257      status->value =
258          ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported;
259      return;
260    }
261#endif
262  }
263
264  ContentSetting plugin_setting = CONTENT_SETTING_DEFAULT;
265  bool uses_default_content_setting = true;
266  bool is_managed = false;
267  // Check plug-in content settings. The primary URL is the top origin URL and
268  // the secondary URL is the plug-in URL.
269  GetPluginContentSetting(plugin, params.top_origin_url, params.url,
270                          plugin_metadata->identifier(), &plugin_setting,
271                          &uses_default_content_setting, &is_managed);
272  DCHECK(plugin_setting != CONTENT_SETTING_DEFAULT);
273
274  PluginMetadata::SecurityStatus plugin_status =
275      plugin_metadata->GetSecurityStatus(plugin);
276#if defined(ENABLE_PLUGIN_INSTALLATION)
277  // Check if the plug-in is outdated.
278  if (plugin_status == PluginMetadata::SECURITY_STATUS_OUT_OF_DATE &&
279      !allow_outdated_plugins_.GetValue()) {
280    if (allow_outdated_plugins_.IsManaged()) {
281      status->value =
282          ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed;
283    } else {
284      status->value = ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked;
285    }
286    return;
287  }
288#endif
289  // Check if the plug-in or its group is enabled by policy.
290  PluginPrefs::PolicyStatus plugin_policy =
291      plugin_prefs_->PolicyStatusForPlugin(plugin.name);
292  PluginPrefs::PolicyStatus group_policy =
293      plugin_prefs_->PolicyStatusForPlugin(plugin_metadata->name());
294
295  // Check if the plug-in requires authorization.
296  if (plugin_status ==
297          PluginMetadata::SECURITY_STATUS_REQUIRES_AUTHORIZATION &&
298      plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS &&
299      plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS &&
300      !always_authorize_plugins_.GetValue() &&
301      plugin_setting != CONTENT_SETTING_BLOCK &&
302      uses_default_content_setting &&
303      plugin_policy != PluginPrefs::POLICY_ENABLED &&
304      group_policy != PluginPrefs::POLICY_ENABLED &&
305      !ChromePluginServiceFilter::GetInstance()->IsPluginRestricted(
306          plugin.path)) {
307    status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized;
308    return;
309  }
310
311  // Check if the plug-in is crashing too much.
312  if (PluginService::GetInstance()->IsPluginUnstable(plugin.path) &&
313      !always_authorize_plugins_.GetValue() &&
314      plugin_setting != CONTENT_SETTING_BLOCK &&
315      uses_default_content_setting) {
316    status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized;
317    return;
318  }
319
320  if (plugin_setting == CONTENT_SETTING_ASK) {
321      status->value = ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay;
322  } else if (plugin_setting == CONTENT_SETTING_BLOCK) {
323    status->value =
324        is_managed ? ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy
325                   : ChromeViewHostMsg_GetPluginInfo_Status::kBlocked;
326  }
327
328  if (status->value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed) {
329    // Allow an embedder of <webview> to block a plugin from being loaded inside
330    // the guest. In order to do this, set the status to 'Unauthorized' here,
331    // and update the status as appropriate depending on the response from the
332    // embedder.
333#if defined(ENABLE_EXTENSIONS)
334    if (extensions::WebViewRendererState::GetInstance()->IsGuest(
335        render_process_id_))
336      status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized;
337
338#endif
339  }
340}
341
342bool PluginInfoMessageFilter::Context::FindEnabledPlugin(
343    int render_frame_id,
344    const GURL& url,
345    const GURL& top_origin_url,
346    const std::string& mime_type,
347    ChromeViewHostMsg_GetPluginInfo_Status* status,
348    WebPluginInfo* plugin,
349    std::string* actual_mime_type,
350    scoped_ptr<PluginMetadata>* plugin_metadata) const {
351  bool allow_wildcard = true;
352  std::vector<WebPluginInfo> matching_plugins;
353  std::vector<std::string> mime_types;
354  PluginService::GetInstance()->GetPluginInfoArray(
355      url, mime_type, allow_wildcard, &matching_plugins, &mime_types);
356  if (matching_plugins.empty()) {
357    status->value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound;
358    return false;
359  }
360
361  content::PluginServiceFilter* filter =
362      PluginService::GetInstance()->GetFilter();
363  size_t i = 0;
364  for (; i < matching_plugins.size(); ++i) {
365    if (!filter || filter->IsPluginAvailable(render_process_id_,
366                                             render_frame_id,
367                                             resource_context_,
368                                             url,
369                                             top_origin_url,
370                                             &matching_plugins[i])) {
371      break;
372    }
373  }
374
375  // If we broke out of the loop, we have found an enabled plug-in.
376  bool enabled = i < matching_plugins.size();
377  if (!enabled) {
378    // Otherwise, we only found disabled plug-ins, so we take the first one.
379    i = 0;
380    status->value = ChromeViewHostMsg_GetPluginInfo_Status::kDisabled;
381  }
382
383  *plugin = matching_plugins[i];
384  *actual_mime_type = mime_types[i];
385  if (plugin_metadata)
386    *plugin_metadata = PluginFinder::GetInstance()->GetPluginMetadata(*plugin);
387
388  return enabled;
389}
390
391void PluginInfoMessageFilter::Context::GetPluginContentSetting(
392    const WebPluginInfo& plugin,
393    const GURL& policy_url,
394    const GURL& plugin_url,
395    const std::string& resource,
396    ContentSetting* setting,
397    bool* uses_default_content_setting,
398    bool* is_managed) const {
399  scoped_ptr<base::Value> value;
400  content_settings::SettingInfo info;
401  bool uses_plugin_specific_setting = false;
402  if (ShouldUseJavaScriptSettingForPlugin(plugin)) {
403    value.reset(
404        host_content_settings_map_->GetWebsiteSetting(
405            policy_url, policy_url, CONTENT_SETTINGS_TYPE_JAVASCRIPT,
406            std::string(), &info));
407  } else {
408    content_settings::SettingInfo specific_info;
409    scoped_ptr<base::Value> specific_setting(
410        host_content_settings_map_->GetWebsiteSetting(
411            policy_url, plugin_url, CONTENT_SETTINGS_TYPE_PLUGINS, resource,
412            &specific_info));
413    content_settings::SettingInfo general_info;
414    scoped_ptr<base::Value> general_setting(
415        host_content_settings_map_->GetWebsiteSetting(
416            policy_url, plugin_url, CONTENT_SETTINGS_TYPE_PLUGINS,
417            std::string(), &general_info));
418
419    // If there is a plugin-specific setting, we use it, unless the general
420    // setting was set by policy, in which case it takes precedence.
421    uses_plugin_specific_setting = specific_setting &&
422        (general_info.source != content_settings::SETTING_SOURCE_POLICY);
423    if (uses_plugin_specific_setting) {
424      value = specific_setting.Pass();
425      info = specific_info;
426    } else {
427      value = general_setting.Pass();
428      info = general_info;
429    }
430  }
431  *setting = content_settings::ValueToContentSetting(value.get());
432  *uses_default_content_setting =
433      !uses_plugin_specific_setting &&
434      info.primary_pattern == ContentSettingsPattern::Wildcard() &&
435      info.secondary_pattern == ContentSettingsPattern::Wildcard();
436  *is_managed = info.source == content_settings::SETTING_SOURCE_POLICY;
437}
438
439void PluginInfoMessageFilter::Context::MaybeGrantAccess(
440    const ChromeViewHostMsg_GetPluginInfo_Status& status,
441    const base::FilePath& path) const {
442  if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed ||
443      status.value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay) {
444    ChromePluginServiceFilter::GetInstance()->AuthorizePlugin(
445        render_process_id_, path);
446  }
447}
448
449bool PluginInfoMessageFilter::Context::IsPluginEnabled(
450    const content::WebPluginInfo& plugin) const {
451  return plugin_prefs_->IsPluginEnabled(plugin);
452}
453