Home | History | Annotate | Download | only in plugins
      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/plugins/chrome_plugin_service_filter.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/plugins/plugin_metadata.h"
     11 #include "chrome/browser/plugins/plugin_prefs.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "content/public/browser/notification_service.h"
     15 #include "content/public/browser/plugin_service.h"
     16 #include "content/public/browser/render_process_host.h"
     17 #include "content/public/browser/resource_context.h"
     18 
     19 using content::BrowserThread;
     20 using content::PluginService;
     21 
     22 // static
     23 ChromePluginServiceFilter* ChromePluginServiceFilter::GetInstance() {
     24   return Singleton<ChromePluginServiceFilter>::get();
     25 }
     26 
     27 void ChromePluginServiceFilter::RegisterResourceContext(
     28     PluginPrefs* plugin_prefs,
     29     const void* context) {
     30   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     31   base::AutoLock lock(lock_);
     32   resource_context_map_[context] = plugin_prefs;
     33 }
     34 
     35 void ChromePluginServiceFilter::UnregisterResourceContext(
     36     const void* context) {
     37   base::AutoLock lock(lock_);
     38   resource_context_map_.erase(context);
     39 }
     40 
     41 void ChromePluginServiceFilter::OverridePluginForTab(
     42     int render_process_id,
     43     int render_view_id,
     44     const GURL& url,
     45     const content::WebPluginInfo& plugin) {
     46   base::AutoLock auto_lock(lock_);
     47   ProcessDetails* details = GetOrRegisterProcess(render_process_id);
     48   OverriddenPlugin overridden_plugin;
     49   overridden_plugin.render_view_id = render_view_id;
     50   overridden_plugin.url = url;
     51   overridden_plugin.plugin = plugin;
     52   details->overridden_plugins.push_back(overridden_plugin);
     53 }
     54 
     55 void ChromePluginServiceFilter::RestrictPluginToProfileAndOrigin(
     56     const base::FilePath& plugin_path,
     57     Profile* profile,
     58     const GURL& origin) {
     59   base::AutoLock auto_lock(lock_);
     60   restricted_plugins_[plugin_path] =
     61       std::make_pair(PluginPrefs::GetForProfile(profile).get(), origin);
     62 }
     63 
     64 void ChromePluginServiceFilter::UnrestrictPlugin(
     65     const base::FilePath& plugin_path) {
     66   base::AutoLock auto_lock(lock_);
     67   restricted_plugins_.erase(plugin_path);
     68 }
     69 
     70 bool ChromePluginServiceFilter::IsPluginAvailable(
     71     int render_process_id,
     72     int render_view_id,
     73     const void* context,
     74     const GURL& url,
     75     const GURL& policy_url,
     76     content::WebPluginInfo* plugin) {
     77   base::AutoLock auto_lock(lock_);
     78   const ProcessDetails* details = GetProcess(render_process_id);
     79 
     80   // Check whether the plugin is overridden.
     81   if (details) {
     82     for (size_t i = 0; i < details->overridden_plugins.size(); ++i) {
     83       if (details->overridden_plugins[i].render_view_id == render_view_id &&
     84           (details->overridden_plugins[i].url == url ||
     85            details->overridden_plugins[i].url.is_empty())) {
     86 
     87         bool use = details->overridden_plugins[i].plugin.path == plugin->path;
     88         if (use)
     89           *plugin = details->overridden_plugins[i].plugin;
     90         return use;
     91       }
     92     }
     93   }
     94 
     95   // Check whether the plugin is disabled.
     96   ResourceContextMap::iterator prefs_it =
     97       resource_context_map_.find(context);
     98   if (prefs_it == resource_context_map_.end())
     99     return false;
    100 
    101   PluginPrefs* plugin_prefs = prefs_it->second.get();
    102   if (!plugin_prefs->IsPluginEnabled(*plugin))
    103     return false;
    104 
    105   // Check whether the plugin is restricted to a URL.
    106   RestrictedPluginMap::const_iterator it =
    107       restricted_plugins_.find(plugin->path);
    108   if (it != restricted_plugins_.end()) {
    109     if (it->second.first != plugin_prefs)
    110       return false;
    111     const GURL& origin = it->second.second;
    112     if (!origin.is_empty() &&
    113         (policy_url.scheme() != origin.scheme() ||
    114          policy_url.host() != origin.host() ||
    115          policy_url.port() != origin.port())) {
    116       return false;
    117     }
    118   }
    119 
    120   return true;
    121 }
    122 
    123 bool ChromePluginServiceFilter::CanLoadPlugin(int render_process_id,
    124                                               const base::FilePath& path) {
    125   // The browser itself sometimes loads plug-ins to e.g. clear plug-in data.
    126   // We always grant the browser permission.
    127   if (!render_process_id)
    128     return true;
    129 
    130   base::AutoLock auto_lock(lock_);
    131   const ProcessDetails* details = GetProcess(render_process_id);
    132   if (!details)
    133     return false;
    134 
    135   if (details->authorized_plugins.find(path) ==
    136           details->authorized_plugins.end() &&
    137       details->authorized_plugins.find(base::FilePath()) ==
    138           details->authorized_plugins.end()) {
    139     return false;
    140   }
    141 
    142   return true;
    143 }
    144 
    145 void ChromePluginServiceFilter::AuthorizePlugin(
    146     int render_process_id,
    147     const base::FilePath& plugin_path) {
    148   base::AutoLock auto_lock(lock_);
    149   ProcessDetails* details = GetOrRegisterProcess(render_process_id);
    150   details->authorized_plugins.insert(plugin_path);
    151 }
    152 
    153 void ChromePluginServiceFilter::AuthorizeAllPlugins(int render_process_id) {
    154   AuthorizePlugin(render_process_id, base::FilePath());
    155 }
    156 
    157 ChromePluginServiceFilter::ChromePluginServiceFilter() {
    158   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    159   registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
    160                  content::NotificationService::AllSources());
    161   registrar_.Add(this, chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
    162                  content::NotificationService::AllSources());
    163 }
    164 
    165 ChromePluginServiceFilter::~ChromePluginServiceFilter() {
    166 }
    167 
    168 void ChromePluginServiceFilter::Observe(
    169     int type,
    170     const content::NotificationSource& source,
    171     const content::NotificationDetails& details) {
    172   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    173   switch (type) {
    174     case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
    175       int render_process_id =
    176           content::Source<content::RenderProcessHost>(source).ptr()->GetID();
    177 
    178       base::AutoLock auto_lock(lock_);
    179       plugin_details_.erase(render_process_id);
    180       break;
    181     }
    182     case chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED: {
    183       Profile* profile = content::Source<Profile>(source).ptr();
    184       PluginService::GetInstance()->PurgePluginListCache(profile, false);
    185       if (profile && profile->HasOffTheRecordProfile()) {
    186         PluginService::GetInstance()->PurgePluginListCache(
    187             profile->GetOffTheRecordProfile(), false);
    188       }
    189       break;
    190     }
    191     default: {
    192       NOTREACHED();
    193     }
    194   }
    195 }
    196 
    197 ChromePluginServiceFilter::ProcessDetails*
    198 ChromePluginServiceFilter::GetOrRegisterProcess(
    199     int render_process_id) {
    200   return &plugin_details_[render_process_id];
    201 }
    202 
    203 const ChromePluginServiceFilter::ProcessDetails*
    204 ChromePluginServiceFilter::GetProcess(
    205     int render_process_id) const {
    206   std::map<int, ProcessDetails>::const_iterator it =
    207       plugin_details_.find(render_process_id);
    208   if (it == plugin_details_.end())
    209     return NULL;
    210   return &it->second;
    211 }
    212 
    213 ChromePluginServiceFilter::OverriddenPlugin::OverriddenPlugin()
    214     : render_view_id(MSG_ROUTING_NONE) {
    215 }
    216 
    217 ChromePluginServiceFilter::OverriddenPlugin::~OverriddenPlugin() {
    218 }
    219 
    220 ChromePluginServiceFilter::ProcessDetails::ProcessDetails() {
    221 }
    222 
    223 ChromePluginServiceFilter::ProcessDetails::~ProcessDetails() {
    224 }
    225 
    226