Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: content/child/npapi/plugin_lib.cc

Issue 1851093005: Remove content/child/npapi (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remove_combined_01_02
Patch Set: rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/child/npapi/plugin_lib.h ('k') | content/child/npapi/plugin_lib_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "content/child/npapi/plugin_lib.h"
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_util.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "build/build_config.h"
17 #include "content/child/npapi/plugin_host.h"
18 #include "content/child/npapi/plugin_instance.h"
19 #include "content/common/plugin_list.h"
20
21 namespace content {
22
23 // A list of all the instantiated plugins.
24 static std::vector<scoped_refptr<PluginLib> >* g_loaded_libs;
25
26 PluginLib* PluginLib::CreatePluginLib(const base::FilePath& filename) {
27 // We can only have one PluginLib object per plugin as it controls the per
28 // instance function calls (i.e. NP_Initialize and NP_Shutdown). So we keep
29 // a map of PluginLib objects.
30 if (!g_loaded_libs)
31 g_loaded_libs = new std::vector<scoped_refptr<PluginLib> >;
32
33 for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
34 if ((*g_loaded_libs)[i]->plugin_info().path == filename)
35 return (*g_loaded_libs)[i].get();
36 }
37
38 WebPluginInfo info;
39 if (!PluginList::Singleton()->ReadPluginInfo(filename, &info))
40 return NULL;
41
42 return new PluginLib(info);
43 }
44
45 void PluginLib::UnloadAllPlugins() {
46 if (g_loaded_libs) {
47 // PluginLib::Unload() can remove items from the list and even delete
48 // the list when it removes the last item, so we must work with a copy
49 // of the list so that we don't get the carpet removed under our feet.
50 std::vector<scoped_refptr<PluginLib> > loaded_libs(*g_loaded_libs);
51 for (size_t i = 0; i < loaded_libs.size(); ++i)
52 loaded_libs[i]->Unload();
53
54 if (g_loaded_libs && g_loaded_libs->empty()) {
55 delete g_loaded_libs;
56 g_loaded_libs = NULL;
57 }
58 }
59 }
60
61 void PluginLib::ShutdownAllPlugins() {
62 if (g_loaded_libs) {
63 for (size_t i = 0; i < g_loaded_libs->size(); ++i)
64 (*g_loaded_libs)[i]->Shutdown();
65 }
66 }
67
68 PluginLib::PluginLib(const WebPluginInfo& info)
69 : web_plugin_info_(info),
70 library_(NULL),
71 initialized_(false),
72 saved_data_(0),
73 instance_count_(0),
74 skip_unload_(false),
75 defer_unload_(false) {
76 memset(static_cast<void*>(&plugin_funcs_), 0, sizeof(plugin_funcs_));
77 g_loaded_libs->push_back(make_scoped_refptr(this));
78
79 memset(&entry_points_, 0, sizeof(entry_points_));
80 }
81
82 PluginLib::~PluginLib() {
83 if (saved_data_ != 0) {
84 // TODO - delete the savedData object here
85 }
86 }
87
88 NPPluginFuncs* PluginLib::functions() {
89 return &plugin_funcs_;
90 }
91
92 NPError PluginLib::NP_Initialize() {
93 LOG_IF(ERROR, PluginList::DebugPluginLoading())
94 << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
95 << "): initialized=" << initialized_;
96 if (initialized_)
97 return NPERR_NO_ERROR;
98
99 if (!Load())
100 return NPERR_MODULE_LOAD_FAILED_ERROR;
101
102 PluginHost* host = PluginHost::Singleton();
103 if (host == 0)
104 return NPERR_GENERIC_ERROR;
105
106 #if defined(OS_POSIX) && !defined(OS_MACOSX)
107 NPError rv = entry_points_.np_initialize(host->host_functions(),
108 &plugin_funcs_);
109 #else
110 NPError rv = entry_points_.np_initialize(host->host_functions());
111 #if defined(OS_MACOSX)
112 // On the Mac, we need to get entry points after calling np_initialize to
113 // match the behavior of other browsers.
114 if (rv == NPERR_NO_ERROR) {
115 rv = entry_points_.np_getentrypoints(&plugin_funcs_);
116 }
117 #endif // OS_MACOSX
118 #endif
119 LOG_IF(ERROR, PluginList::DebugPluginLoading())
120 << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
121 << "): result=" << rv;
122 initialized_ = (rv == NPERR_NO_ERROR);
123 return rv;
124 }
125
126 void PluginLib::NP_Shutdown(void) {
127 DCHECK(initialized_);
128 entry_points_.np_shutdown();
129 }
130
131 NPError PluginLib::NP_ClearSiteData(const char* site,
132 uint64_t flags,
133 uint64_t max_age) {
134 DCHECK(initialized_);
135 if (plugin_funcs_.clearsitedata)
136 return plugin_funcs_.clearsitedata(site, flags, max_age);
137 return NPERR_INVALID_FUNCTABLE_ERROR;
138 }
139
140 char** PluginLib::NP_GetSitesWithData() {
141 DCHECK(initialized_);
142 if (plugin_funcs_.getsiteswithdata)
143 return plugin_funcs_.getsiteswithdata();
144 return NULL;
145 }
146
147 void PluginLib::PreventLibraryUnload() {
148 skip_unload_ = true;
149 }
150
151 PluginInstance* PluginLib::CreateInstance(const std::string& mime_type) {
152 PluginInstance* new_instance = new PluginInstance(this, mime_type);
153 instance_count_++;
154 DCHECK_NE(static_cast<PluginInstance*>(NULL), new_instance);
155 return new_instance;
156 }
157
158 void PluginLib::CloseInstance() {
159 instance_count_--;
160 // If a plugin is running in its own process it will get unloaded on process
161 // shutdown.
162 if ((instance_count_ == 0) && !defer_unload_)
163 Unload();
164 }
165
166 bool PluginLib::Load() {
167 if (library_)
168 return true;
169
170 bool rv = false;
171 base::NativeLibrary library = 0;
172 base::NativeLibraryLoadError error;
173
174 #if defined(OS_WIN)
175 // This is to work around a bug in the Real player recorder plugin which
176 // intercepts LoadLibrary calls from chrome.dll and wraps NPAPI functions
177 // provided by the plugin. It crashes if the media player plugin is being
178 // loaded. Workaround is to load the dll dynamically by getting the
179 // LoadLibrary API address from kernel32.dll which bypasses the recorder
180 // plugin.
181 if (web_plugin_info_.name.find(L"Windows Media Player") !=
182 std::wstring::npos) {
183 library = base::LoadNativeLibraryDynamically(web_plugin_info_.path);
184 } else {
185 library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
186 }
187 #else
188 library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
189 #endif
190
191 if (!library) {
192 LOG_IF(ERROR, PluginList::DebugPluginLoading())
193 << "Couldn't load plugin " << web_plugin_info_.path.value() << " "
194 << error.ToString();
195 return rv;
196 }
197
198 #if defined(OS_MACOSX)
199 // According to the WebKit source, QuickTime at least requires us to call
200 // UseResFile on the plugin resources before loading.
201 if (library->bundle_resource_ref != -1)
202 UseResFile(library->bundle_resource_ref);
203 #endif
204
205 rv = true; // assume success now
206
207 entry_points_.np_initialize =
208 (NP_InitializeFunc)base::GetFunctionPointerFromNativeLibrary(library,
209 "NP_Initialize");
210 if (entry_points_.np_initialize == 0)
211 rv = false;
212
213 #if defined(OS_WIN) || defined(OS_MACOSX)
214 entry_points_.np_getentrypoints =
215 (NP_GetEntryPointsFunc)base::GetFunctionPointerFromNativeLibrary(
216 library, "NP_GetEntryPoints");
217 if (entry_points_.np_getentrypoints == 0)
218 rv = false;
219 #endif
220
221 entry_points_.np_shutdown =
222 (NP_ShutdownFunc)base::GetFunctionPointerFromNativeLibrary(library,
223 "NP_Shutdown");
224 if (entry_points_.np_shutdown == 0)
225 rv = false;
226
227 if (rv) {
228 plugin_funcs_.size = sizeof(plugin_funcs_);
229 plugin_funcs_.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
230 #if !defined(OS_POSIX)
231 if (entry_points_.np_getentrypoints(&plugin_funcs_) != NPERR_NO_ERROR)
232 rv = false;
233 #else
234 // On Linux and Mac, we get the plugin entry points during NP_Initialize.
235 #endif
236 }
237
238 if (rv) {
239 LOG_IF(ERROR, PluginList::DebugPluginLoading())
240 << "Plugin " << web_plugin_info_.path.value()
241 << " loaded successfully.";
242 library_ = library;
243 } else {
244 LOG_IF(ERROR, PluginList::DebugPluginLoading())
245 << "Plugin " << web_plugin_info_.path.value()
246 << " failed to load, unloading.";
247 base::UnloadNativeLibrary(library);
248 }
249
250 return rv;
251 }
252
253 // This is a helper to help perform a delayed NP_Shutdown and FreeLibrary on the
254 // plugin dll.
255 void FreePluginLibraryHelper(const base::FilePath& path,
256 base::NativeLibrary library,
257 NP_ShutdownFunc shutdown_func) {
258 if (shutdown_func) {
259 // Don't call NP_Shutdown if the library has been reloaded since this task
260 // was posted.
261 bool reloaded = false;
262 if (g_loaded_libs) {
263 for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
264 if ((*g_loaded_libs)[i]->plugin_info().path == path) {
265 reloaded = true;
266 break;
267 }
268 }
269 }
270 if (!reloaded)
271 shutdown_func();
272 }
273
274 if (library) {
275 // Always call base::UnloadNativeLibrary so that the system reference
276 // count is decremented.
277 base::UnloadNativeLibrary(library);
278 }
279 }
280
281 void PluginLib::Unload() {
282 if (library_) {
283 // In case of single process mode, a plugin can delete itself
284 // by executing a script. So delay the unloading of the library
285 // so that the plugin will have a chance to unwind.
286 /* TODO(dglazkov): Revisit when re-enabling the JSC build.
287 #if USE(JSC)
288 // The plugin NPAPI instances may still be around. Delay the
289 // NP_Shutdown and FreeLibrary calls at least till the next
290 // peek message.
291 defer_unload = true;
292 #endif
293 */
294 if (!defer_unload_) {
295 LOG_IF(ERROR, PluginList::DebugPluginLoading())
296 << "Scheduling delayed unload for plugin "
297 << web_plugin_info_.path.value();
298 base::ThreadTaskRunnerHandle::Get()->PostTask(
299 FROM_HERE, base::Bind(&FreePluginLibraryHelper, web_plugin_info_.path,
300 skip_unload_ ? NULL : library_,
301 entry_points_.np_shutdown));
302 } else {
303 Shutdown();
304 if (!skip_unload_) {
305 LOG_IF(ERROR, PluginList::DebugPluginLoading())
306 << "Unloading plugin " << web_plugin_info_.path.value();
307 base::UnloadNativeLibrary(library_);
308 }
309 }
310
311 library_ = NULL;
312 }
313
314 for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
315 if ((*g_loaded_libs)[i].get() == this) {
316 g_loaded_libs->erase(g_loaded_libs->begin() + i);
317 break;
318 }
319 }
320 if (g_loaded_libs->empty()) {
321 delete g_loaded_libs;
322 g_loaded_libs = NULL;
323 }
324 }
325
326 void PluginLib::Shutdown() {
327 if (initialized_) {
328 NP_Shutdown();
329 initialized_ = false;
330 }
331 }
332
333 } // namespace content
OLDNEW
« no previous file with comments | « content/child/npapi/plugin_lib.h ('k') | content/child/npapi/plugin_lib_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698