OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/pepper_plugin_registry.h" | 5 #include "content/renderer/pepper/pepper_plugin_registry.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/logging.h" |
8 #include "base/native_library.h" | 8 #include "content/common/pepper_plugin_list.h" |
9 #include "base/strings/string_split.h" | 9 #include "content/renderer/pepper/plugin_module.h" |
10 #include "base/strings/string_util.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "content/public/common/content_client.h" | |
13 #include "content/public/common/content_switches.h" | |
14 #include "ppapi/shared_impl/ppapi_permissions.h" | 10 #include "ppapi/shared_impl/ppapi_permissions.h" |
15 | 11 |
16 namespace content { | 12 namespace content { |
17 namespace { | |
18 | |
19 // Appends any plugins from the command line to the given vector. | |
20 void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) { | |
21 bool out_of_process = true; | |
22 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiInProcess)) | |
23 out_of_process = false; | |
24 | |
25 const std::string value = | |
26 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
27 switches::kRegisterPepperPlugins); | |
28 if (value.empty()) | |
29 return; | |
30 | |
31 // FORMAT: | |
32 // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> ) | |
33 // plugin-entry = | |
34 // <file-path> + | |
35 // ["#" + <name> + ["#" + <description> + ["#" + <version>]]] + | |
36 // *1( LWS + ";" + LWS + <mime-type> ) | |
37 std::vector<std::string> modules; | |
38 base::SplitString(value, ',', &modules); | |
39 for (size_t i = 0; i < modules.size(); ++i) { | |
40 std::vector<std::string> parts; | |
41 base::SplitString(modules[i], ';', &parts); | |
42 if (parts.size() < 2) { | |
43 DLOG(ERROR) << "Required mime-type not found"; | |
44 continue; | |
45 } | |
46 | |
47 std::vector<std::string> name_parts; | |
48 base::SplitString(parts[0], '#', &name_parts); | |
49 | |
50 PepperPluginInfo plugin; | |
51 plugin.is_out_of_process = out_of_process; | |
52 #if defined(OS_WIN) | |
53 // This means we can't provide plugins from non-ASCII paths, but | |
54 // since this switch is only for development I don't think that's | |
55 // too awful. | |
56 plugin.path = base::FilePath(ASCIIToUTF16(name_parts[0])); | |
57 #else | |
58 plugin.path = base::FilePath(name_parts[0]); | |
59 #endif | |
60 if (name_parts.size() > 1) | |
61 plugin.name = name_parts[1]; | |
62 if (name_parts.size() > 2) | |
63 plugin.description = name_parts[2]; | |
64 if (name_parts.size() > 3) | |
65 plugin.version = name_parts[3]; | |
66 for (size_t j = 1; j < parts.size(); ++j) { | |
67 WebPluginMimeType mime_type(parts[j], | |
68 std::string(), | |
69 plugin.description); | |
70 plugin.mime_types.push_back(mime_type); | |
71 } | |
72 | |
73 // If the plugin name is empty, use the filename. | |
74 if (plugin.name.empty()) | |
75 plugin.name = UTF16ToUTF8(plugin.path.BaseName().LossyDisplayName()); | |
76 | |
77 // Command-line plugins get full permissions. | |
78 plugin.permissions = ppapi::PERMISSION_ALL_BITS; | |
79 | |
80 plugins->push_back(plugin); | |
81 } | |
82 } | |
83 | |
84 } // namespace | |
85 | |
86 bool MakePepperPluginInfo(const WebPluginInfo& webplugin_info, | |
87 PepperPluginInfo* pepper_info) { | |
88 if (!webplugin_info.is_pepper_plugin()) | |
89 return false; | |
90 | |
91 pepper_info->is_out_of_process = | |
92 webplugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS || | |
93 webplugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED; | |
94 pepper_info->is_sandboxed = webplugin_info.type != | |
95 WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED; | |
96 | |
97 pepper_info->path = base::FilePath(webplugin_info.path); | |
98 pepper_info->name = UTF16ToASCII(webplugin_info.name); | |
99 pepper_info->description = UTF16ToASCII(webplugin_info.desc); | |
100 pepper_info->version = UTF16ToASCII(webplugin_info.version); | |
101 pepper_info->mime_types = webplugin_info.mime_types; | |
102 pepper_info->permissions = webplugin_info.pepper_permissions; | |
103 | |
104 return true; | |
105 } | |
106 | 13 |
107 // static | 14 // static |
108 PepperPluginRegistry* PepperPluginRegistry::GetInstance() { | 15 PepperPluginRegistry* PepperPluginRegistry::GetInstance() { |
109 static PepperPluginRegistry* registry = NULL; | 16 static PepperPluginRegistry* registry = NULL; |
110 // This object leaks. It is a temporary hack to work around a crash. | 17 // This object leaks. It is a temporary hack to work around a crash. |
111 // http://code.google.com/p/chromium/issues/detail?id=63234 | 18 // http://code.google.com/p/chromium/issues/detail?id=63234 |
112 if (!registry) | 19 if (!registry) |
113 registry = new PepperPluginRegistry; | 20 registry = new PepperPluginRegistry; |
114 return registry; | 21 return registry; |
115 } | 22 } |
116 | 23 |
117 // static | |
118 void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) { | |
119 GetContentClient()->AddPepperPlugins(plugins); | |
120 ComputePluginsFromCommandLine(plugins); | |
121 } | |
122 | |
123 // static | |
124 void PepperPluginRegistry::PreloadModules() { | |
125 std::vector<PepperPluginInfo> plugins; | |
126 ComputeList(&plugins); | |
127 for (size_t i = 0; i < plugins.size(); ++i) { | |
128 if (!plugins[i].is_internal && plugins[i].is_sandboxed) { | |
129 std::string error; | |
130 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path, | |
131 &error); | |
132 DLOG_IF(WARNING, !library) << "Unable to load plugin " | |
133 << plugins[i].path.value() << " " | |
134 << error; | |
135 (void)library; // Prevent release-mode warning. | |
136 } | |
137 } | |
138 } | |
139 | |
140 const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( | 24 const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( |
141 const WebPluginInfo& info) { | 25 const WebPluginInfo& info) { |
142 for (size_t i = 0; i < plugin_list_.size(); ++i) { | 26 for (size_t i = 0; i < plugin_list_.size(); ++i) { |
143 if (info.path == plugin_list_[i].path) | 27 if (info.path == plugin_list_[i].path) |
144 return &plugin_list_[i]; | 28 return &plugin_list_[i]; |
145 } | 29 } |
146 // We did not find the plugin in our list. But wait! the plugin can also | 30 // We did not find the plugin in our list. But wait! the plugin can also |
147 // be a latecomer, as it happens with pepper flash. This information | 31 // be a latecomer, as it happens with pepper flash. This information |
148 // is actually in |info| and we can use it to construct it and add it to | 32 // is actually in |info| and we can use it to construct it and add it to |
149 // the list. This same deal needs to be done in the browser side in | 33 // the list. This same deal needs to be done in the browser side in |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 PepperPluginRegistry::~PepperPluginRegistry() { | 74 PepperPluginRegistry::~PepperPluginRegistry() { |
191 // Explicitly clear all preloaded modules first. This will cause callbacks | 75 // Explicitly clear all preloaded modules first. This will cause callbacks |
192 // to erase these modules from the live_modules_ list, and we don't want | 76 // to erase these modules from the live_modules_ list, and we don't want |
193 // that to happen implicitly out-of-order. | 77 // that to happen implicitly out-of-order. |
194 preloaded_modules_.clear(); | 78 preloaded_modules_.clear(); |
195 | 79 |
196 DCHECK(live_modules_.empty()); | 80 DCHECK(live_modules_.empty()); |
197 } | 81 } |
198 | 82 |
199 PepperPluginRegistry::PepperPluginRegistry() { | 83 PepperPluginRegistry::PepperPluginRegistry() { |
200 ComputeList(&plugin_list_); | 84 ComputePepperPluginList(&plugin_list_); |
201 | 85 |
202 // Note that in each case, AddLiveModule must be called before completing | 86 // Note that in each case, AddLiveModule must be called before completing |
203 // initialization. If we bail out (in the continue clauses) before saving | 87 // initialization. If we bail out (in the continue clauses) before saving |
204 // the initialized module, it will still try to unregister itself in its | 88 // the initialized module, it will still try to unregister itself in its |
205 // destructor. | 89 // destructor. |
206 for (size_t i = 0; i < plugin_list_.size(); i++) { | 90 for (size_t i = 0; i < plugin_list_.size(); i++) { |
207 const PepperPluginInfo& current = plugin_list_[i]; | 91 const PepperPluginInfo& current = plugin_list_[i]; |
208 if (current.is_out_of_process) | 92 if (current.is_out_of_process) |
209 continue; // Out of process plugins need no special pre-initialization. | 93 continue; // Out of process plugins need no special pre-initialization. |
210 | 94 |
(...skipping 11 matching lines...) Expand all Loading... |
222 if (!module->InitAsLibrary(current.path)) { | 106 if (!module->InitAsLibrary(current.path)) { |
223 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); | 107 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); |
224 continue; | 108 continue; |
225 } | 109 } |
226 } | 110 } |
227 preloaded_modules_[current.path] = module; | 111 preloaded_modules_[current.path] = module; |
228 } | 112 } |
229 } | 113 } |
230 | 114 |
231 } // namespace content | 115 } // namespace content |
OLD | NEW |