- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / plugins / chrome_plugin_service_filter.cc
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::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_view_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_view_id == render_view_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_view_id(MSG_ROUTING_NONE) {
221 }
222
223 ChromePluginServiceFilter::OverriddenPlugin::~OverriddenPlugin() {
224 }
225
226 ChromePluginServiceFilter::ProcessDetails::ProcessDetails() {
227 }
228
229 ChromePluginServiceFilter::ProcessDetails::~ProcessDetails() {
230 }
231