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