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::OverridePluginForFrame(
     42     int render_process_id,
     43     int render_frame_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_frame_id = render_frame_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::IsPluginRestricted(
     71     const base::FilePath& plugin_path) {
     72   base::AutoLock auto_lock(lock_);
     73   return restricted_plugins_.find(plugin_path) != restricted_plugins_.end();
     74 }
     75 
     76 bool ChromePluginServiceFilter::IsPluginAvailable(
     77     int render_process_id,
     78     int render_frame_id,
     79     const void* context,
     80     const GURL& url,
     81     const GURL& policy_url,
     82     content::WebPluginInfo* plugin) {
     83   base::AutoLock auto_lock(lock_);
     84   const ProcessDetails* details = GetProcess(render_process_id);
     85 
     86   // Check whether the plugin is overridden.
     87   if (details) {
     88     for (size_t i = 0; i < details->overridden_plugins.size(); ++i) {
     89       if (details->overridden_plugins[i].render_frame_id == render_frame_id &&
     90           (details->overridden_plugins[i].url == url ||
     91            details->overridden_plugins[i].url.is_empty())) {
     92 
     93         bool use = details->overridden_plugins[i].plugin.path == plugin->path;
     94         if (use)
     95           *plugin = details->overridden_plugins[i].plugin;
     96         return use;
     97       }
     98     }
     99   }
    100 
    101   // Check whether the plugin is disabled.
    102   ResourceContextMap::iterator prefs_it =
    103       resource_context_map_.find(context);
    104   if (prefs_it == resource_context_map_.end())
    105     return false;
    106 
    107   PluginPrefs* plugin_prefs = prefs_it->second.get();
    108   if (!plugin_prefs->IsPluginEnabled(*plugin))
    109     return false;
    110 
    111   // Check whether the plugin is restricted to a URL.
    112   RestrictedPluginMap::const_iterator it =
    113       restricted_plugins_.find(plugin->path);
    114   if (it != restricted_plugins_.end()) {
    115     if (it->second.first != plugin_prefs)
    116       return false;
    117     const GURL& origin = it->second.second;
    118     if (!origin.is_empty() &&
    119         (policy_url.scheme() != origin.scheme() ||
    120          policy_url.host() != origin.host() ||
    121          policy_url.port() != origin.port())) {
    122       return false;
    123     }
    124   }
    125 
    126   return true;
    127 }
    128 
    129 bool ChromePluginServiceFilter::CanLoadPlugin(int render_process_id,
    130                                               const base::FilePath& path) {
    131   // The browser itself sometimes loads plug-ins to e.g. clear plug-in data.
    132   // We always grant the browser permission.
    133   if (!render_process_id)
    134     return true;
    135 
    136   base::AutoLock auto_lock(lock_);
    137   const ProcessDetails* details = GetProcess(render_process_id);
    138   if (!details)
    139     return false;
    140 
    141   if (details->authorized_plugins.find(path) ==
    142           details->authorized_plugins.end() &&
    143       details->authorized_plugins.find(base::FilePath()) ==
    144           details->authorized_plugins.end()) {
    145     return false;
    146   }
    147 
    148   return true;
    149 }
    150 
    151 void ChromePluginServiceFilter::AuthorizePlugin(
    152     int render_process_id,
    153     const base::FilePath& plugin_path) {
    154   base::AutoLock auto_lock(lock_);
    155   ProcessDetails* details = GetOrRegisterProcess(render_process_id);
    156   details->authorized_plugins.insert(plugin_path);
    157 }
    158 
    159 void ChromePluginServiceFilter::AuthorizeAllPlugins(int render_process_id) {
    160   AuthorizePlugin(render_process_id, base::FilePath());
    161 }
    162 
    163 ChromePluginServiceFilter::ChromePluginServiceFilter() {
    164   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    165   registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
    166                  content::NotificationService::AllSources());
    167   registrar_.Add(this, chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
    168                  content::NotificationService::AllSources());
    169 }
    170 
    171 ChromePluginServiceFilter::~ChromePluginServiceFilter() {
    172 }
    173 
    174 void ChromePluginServiceFilter::Observe(
    175     int type,
    176     const content::NotificationSource& source,
    177     const content::NotificationDetails& details) {
    178   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    179   switch (type) {
    180     case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
    181       int render_process_id =
    182           content::Source<content::RenderProcessHost>(source).ptr()->GetID();
    183 
    184       base::AutoLock auto_lock(lock_);
    185       plugin_details_.erase(render_process_id);
    186       break;
    187     }
    188     case chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED: {
    189       Profile* profile = content::Source<Profile>(source).ptr();
    190       PluginService::GetInstance()->PurgePluginListCache(profile, false);
    191       if (profile && profile->HasOffTheRecordProfile()) {
    192         PluginService::GetInstance()->PurgePluginListCache(
    193             profile->GetOffTheRecordProfile(), false);
    194       }
    195       break;
    196     }
    197     default: {
    198       NOTREACHED();
    199     }
    200   }
    201 }
    202 
    203 ChromePluginServiceFilter::ProcessDetails*
    204 ChromePluginServiceFilter::GetOrRegisterProcess(
    205     int render_process_id) {
    206   return &plugin_details_[render_process_id];
    207 }
    208 
    209 const ChromePluginServiceFilter::ProcessDetails*
    210 ChromePluginServiceFilter::GetProcess(
    211     int render_process_id) const {
    212   std::map<int, ProcessDetails>::const_iterator it =
    213       plugin_details_.find(render_process_id);
    214   if (it == plugin_details_.end())
    215     return NULL;
    216   return &it->second;
    217 }
    218 
    219 ChromePluginServiceFilter::OverriddenPlugin::OverriddenPlugin()
    220     : render_frame_id(MSG_ROUTING_NONE) {
    221 }
    222 
    223 ChromePluginServiceFilter::OverriddenPlugin::~OverriddenPlugin() {
    224 }
    225 
    226 ChromePluginServiceFilter::ProcessDetails::ProcessDetails() {
    227 }
    228 
    229 ChromePluginServiceFilter::ProcessDetails::~ProcessDetails() {
    230 }
    231 
    232