| 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/common/pepper_plugin_registry.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/native_library.h" | 9 #include "base/native_library.h" |
| 10 #include "base/string_split.h" | 10 #include "base/string_split.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "content/public/common/content_client.h" | 13 #include "content/public/common/content_client.h" |
| 14 #include "content/public/common/content_switches.h" | 14 #include "content/public/common/content_switches.h" |
| 15 #include "ppapi/shared_impl/ppapi_permissions.h" | 15 #include "ppapi/shared_impl/ppapi_permissions.h" |
| 16 #include "webkit/plugins/npapi/plugin_list.h" | 16 #include "webkit/plugins/npapi/plugin_list.h" |
| 17 | 17 |
| 18 namespace content { |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 // Appends any plugins from the command line to the given vector. | 21 // Appends any plugins from the command line to the given vector. |
| 21 void ComputePluginsFromCommandLine( | 22 void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) { |
| 22 std::vector<content::PepperPluginInfo>* plugins) { | |
| 23 bool out_of_process = | 23 bool out_of_process = |
| 24 CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess); | 24 CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess); |
| 25 const std::string value = | 25 const std::string value = |
| 26 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 26 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 27 switches::kRegisterPepperPlugins); | 27 switches::kRegisterPepperPlugins); |
| 28 if (value.empty()) | 28 if (value.empty()) |
| 29 return; | 29 return; |
| 30 | 30 |
| 31 // FORMAT: | 31 // FORMAT: |
| 32 // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> ) | 32 // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> ) |
| 33 // plugin-entry = | 33 // plugin-entry = |
| 34 // <file-path> + | 34 // <file-path> + |
| 35 // ["#" + <name> + ["#" + <description> + ["#" + <version>]]] + | 35 // ["#" + <name> + ["#" + <description> + ["#" + <version>]]] + |
| 36 // *1( LWS + ";" + LWS + <mime-type> ) | 36 // *1( LWS + ";" + LWS + <mime-type> ) |
| 37 std::vector<std::string> modules; | 37 std::vector<std::string> modules; |
| 38 base::SplitString(value, ',', &modules); | 38 base::SplitString(value, ',', &modules); |
| 39 for (size_t i = 0; i < modules.size(); ++i) { | 39 for (size_t i = 0; i < modules.size(); ++i) { |
| 40 std::vector<std::string> parts; | 40 std::vector<std::string> parts; |
| 41 base::SplitString(modules[i], ';', &parts); | 41 base::SplitString(modules[i], ';', &parts); |
| 42 if (parts.size() < 2) { | 42 if (parts.size() < 2) { |
| 43 DLOG(ERROR) << "Required mime-type not found"; | 43 DLOG(ERROR) << "Required mime-type not found"; |
| 44 continue; | 44 continue; |
| 45 } | 45 } |
| 46 | 46 |
| 47 std::vector<std::string> name_parts; | 47 std::vector<std::string> name_parts; |
| 48 base::SplitString(parts[0], '#', &name_parts); | 48 base::SplitString(parts[0], '#', &name_parts); |
| 49 | 49 |
| 50 content::PepperPluginInfo plugin; | 50 PepperPluginInfo plugin; |
| 51 plugin.is_out_of_process = out_of_process; | 51 plugin.is_out_of_process = out_of_process; |
| 52 #if defined(OS_WIN) | 52 #if defined(OS_WIN) |
| 53 // This means we can't provide plugins from non-ASCII paths, but | 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 | 54 // since this switch is only for development I don't think that's |
| 55 // too awful. | 55 // too awful. |
| 56 plugin.path = FilePath(ASCIIToUTF16(name_parts[0])); | 56 plugin.path = FilePath(ASCIIToUTF16(name_parts[0])); |
| 57 #else | 57 #else |
| 58 plugin.path = FilePath(name_parts[0]); | 58 plugin.path = FilePath(name_parts[0]); |
| 59 #endif | 59 #endif |
| 60 if (name_parts.size() > 1) | 60 if (name_parts.size() > 1) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 72 | 72 |
| 73 // Command-line plugins get full permissions. | 73 // Command-line plugins get full permissions. |
| 74 plugin.permissions = ppapi::PERMISSION_ALL_BITS; | 74 plugin.permissions = ppapi::PERMISSION_ALL_BITS; |
| 75 | 75 |
| 76 plugins->push_back(plugin); | 76 plugins->push_back(plugin); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 } // namespace | 80 } // namespace |
| 81 | 81 |
| 82 webkit::WebPluginInfo content::PepperPluginInfo::ToWebPluginInfo() const { | 82 webkit::WebPluginInfo PepperPluginInfo::ToWebPluginInfo() const { |
| 83 webkit::WebPluginInfo info; | 83 webkit::WebPluginInfo info; |
| 84 | 84 |
| 85 info.type = is_out_of_process ? | 85 info.type = is_out_of_process ? |
| 86 (is_sandboxed ? | 86 (is_sandboxed ? |
| 87 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS : | 87 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS : |
| 88 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED) : | 88 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED) : |
| 89 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS; | 89 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS; |
| 90 | 90 |
| 91 info.name = name.empty() ? | 91 info.name = name.empty() ? |
| 92 path.BaseName().LossyDisplayName() : UTF8ToUTF16(name); | 92 path.BaseName().LossyDisplayName() : UTF8ToUTF16(name); |
| 93 info.path = path; | 93 info.path = path; |
| 94 info.version = ASCIIToUTF16(version); | 94 info.version = ASCIIToUTF16(version); |
| 95 info.desc = ASCIIToUTF16(description); | 95 info.desc = ASCIIToUTF16(description); |
| 96 info.mime_types = mime_types; | 96 info.mime_types = mime_types; |
| 97 info.pepper_permissions = permissions; | 97 info.pepper_permissions = permissions; |
| 98 | 98 |
| 99 return info; | 99 return info; |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool MakePepperPluginInfo(const webkit::WebPluginInfo& webplugin_info, | 102 bool MakePepperPluginInfo(const webkit::WebPluginInfo& webplugin_info, |
| 103 content::PepperPluginInfo* pepper_info) { | 103 PepperPluginInfo* pepper_info) { |
| 104 if (!webkit::IsPepperPlugin(webplugin_info)) | 104 if (!webkit::IsPepperPlugin(webplugin_info)) |
| 105 return false; | 105 return false; |
| 106 | 106 |
| 107 pepper_info->is_out_of_process = webkit::IsOutOfProcessPlugin(webplugin_info); | 107 pepper_info->is_out_of_process = webkit::IsOutOfProcessPlugin(webplugin_info); |
| 108 pepper_info->is_sandboxed = webplugin_info.type != | 108 pepper_info->is_sandboxed = webplugin_info.type != |
| 109 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED; | 109 webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED; |
| 110 | 110 |
| 111 pepper_info->path = FilePath(webplugin_info.path); | 111 pepper_info->path = FilePath(webplugin_info.path); |
| 112 pepper_info->name = UTF16ToASCII(webplugin_info.name); | 112 pepper_info->name = UTF16ToASCII(webplugin_info.name); |
| 113 pepper_info->description = UTF16ToASCII(webplugin_info.desc); | 113 pepper_info->description = UTF16ToASCII(webplugin_info.desc); |
| 114 pepper_info->version = UTF16ToASCII(webplugin_info.version); | 114 pepper_info->version = UTF16ToASCII(webplugin_info.version); |
| 115 pepper_info->mime_types = webplugin_info.mime_types; | 115 pepper_info->mime_types = webplugin_info.mime_types; |
| 116 pepper_info->permissions = webplugin_info.pepper_permissions; | 116 pepper_info->permissions = webplugin_info.pepper_permissions; |
| 117 | 117 |
| 118 return true; | 118 return true; |
| 119 } | 119 } |
| 120 | 120 |
| 121 // static | 121 // static |
| 122 PepperPluginRegistry* PepperPluginRegistry::GetInstance() { | 122 PepperPluginRegistry* PepperPluginRegistry::GetInstance() { |
| 123 static PepperPluginRegistry* registry = NULL; | 123 static PepperPluginRegistry* registry = NULL; |
| 124 // This object leaks. It is a temporary hack to work around a crash. | 124 // This object leaks. It is a temporary hack to work around a crash. |
| 125 // http://code.google.com/p/chromium/issues/detail?id=63234 | 125 // http://code.google.com/p/chromium/issues/detail?id=63234 |
| 126 if (!registry) | 126 if (!registry) |
| 127 registry = new PepperPluginRegistry; | 127 registry = new PepperPluginRegistry; |
| 128 return registry; | 128 return registry; |
| 129 } | 129 } |
| 130 | 130 |
| 131 // static | 131 // static |
| 132 void PepperPluginRegistry::ComputeList( | 132 void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) { |
| 133 std::vector<content::PepperPluginInfo>* plugins) { | 133 GetContentClient()->AddPepperPlugins(plugins); |
| 134 content::GetContentClient()->AddPepperPlugins(plugins); | |
| 135 ComputePluginsFromCommandLine(plugins); | 134 ComputePluginsFromCommandLine(plugins); |
| 136 } | 135 } |
| 137 | 136 |
| 138 // static | 137 // static |
| 139 void PepperPluginRegistry::PreloadModules() { | 138 void PepperPluginRegistry::PreloadModules() { |
| 140 std::vector<content::PepperPluginInfo> plugins; | 139 std::vector<PepperPluginInfo> plugins; |
| 141 ComputeList(&plugins); | 140 ComputeList(&plugins); |
| 142 for (size_t i = 0; i < plugins.size(); ++i) { | 141 for (size_t i = 0; i < plugins.size(); ++i) { |
| 143 if (!plugins[i].is_internal && plugins[i].is_sandboxed) { | 142 if (!plugins[i].is_internal && plugins[i].is_sandboxed) { |
| 144 std::string error; | 143 std::string error; |
| 145 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path, | 144 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path, |
| 146 &error); | 145 &error); |
| 147 DLOG_IF(WARNING, !library) << "Unable to load plugin " | 146 DLOG_IF(WARNING, !library) << "Unable to load plugin " |
| 148 << plugins[i].path.value() << " " | 147 << plugins[i].path.value() << " " |
| 149 << error; | 148 << error; |
| 150 (void)library; // Prevent release-mode warning. | 149 (void)library; // Prevent release-mode warning. |
| 151 } | 150 } |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 | 153 |
| 155 const content::PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( | 154 const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( |
| 156 const webkit::WebPluginInfo& info) { | 155 const webkit::WebPluginInfo& info) { |
| 157 for (size_t i = 0; i < plugin_list_.size(); ++i) { | 156 for (size_t i = 0; i < plugin_list_.size(); ++i) { |
| 158 if (info.path == plugin_list_[i].path) | 157 if (info.path == plugin_list_[i].path) |
| 159 return &plugin_list_[i]; | 158 return &plugin_list_[i]; |
| 160 } | 159 } |
| 161 // We did not find the plugin in our list. But wait! the plugin can also | 160 // We did not find the plugin in our list. But wait! the plugin can also |
| 162 // be a latecomer, as it happens with pepper flash. This information | 161 // be a latecomer, as it happens with pepper flash. This information |
| 163 // is actually in |info| and we can use it to construct it and add it to | 162 // is actually in |info| and we can use it to construct it and add it to |
| 164 // the list. This same deal needs to be done in the browser side in | 163 // the list. This same deal needs to be done in the browser side in |
| 165 // PluginService. | 164 // PluginService. |
| 166 content::PepperPluginInfo plugin; | 165 PepperPluginInfo plugin; |
| 167 if (!MakePepperPluginInfo(info, &plugin)) | 166 if (!MakePepperPluginInfo(info, &plugin)) |
| 168 return NULL; | 167 return NULL; |
| 169 | 168 |
| 170 plugin_list_.push_back(plugin); | 169 plugin_list_.push_back(plugin); |
| 171 return &plugin_list_[plugin_list_.size() - 1]; | 170 return &plugin_list_[plugin_list_.size() - 1]; |
| 172 } | 171 } |
| 173 | 172 |
| 174 webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule( | 173 webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule( |
| 175 const FilePath& path) { | 174 const FilePath& path) { |
| 176 NonOwningModuleMap::iterator it = live_modules_.find(path); | 175 NonOwningModuleMap::iterator it = live_modules_.find(path); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 } | 211 } |
| 213 | 212 |
| 214 PepperPluginRegistry::PepperPluginRegistry() { | 213 PepperPluginRegistry::PepperPluginRegistry() { |
| 215 ComputeList(&plugin_list_); | 214 ComputeList(&plugin_list_); |
| 216 | 215 |
| 217 // Note that in each case, AddLiveModule must be called before completing | 216 // Note that in each case, AddLiveModule must be called before completing |
| 218 // initialization. If we bail out (in the continue clauses) before saving | 217 // initialization. If we bail out (in the continue clauses) before saving |
| 219 // the initialized module, it will still try to unregister itself in its | 218 // the initialized module, it will still try to unregister itself in its |
| 220 // destructor. | 219 // destructor. |
| 221 for (size_t i = 0; i < plugin_list_.size(); i++) { | 220 for (size_t i = 0; i < plugin_list_.size(); i++) { |
| 222 const content::PepperPluginInfo& current = plugin_list_[i]; | 221 const PepperPluginInfo& current = plugin_list_[i]; |
| 223 if (current.is_out_of_process) | 222 if (current.is_out_of_process) |
| 224 continue; // Out of process plugins need no special pre-initialization. | 223 continue; // Out of process plugins need no special pre-initialization. |
| 225 | 224 |
| 226 scoped_refptr<webkit::ppapi::PluginModule> module = | 225 scoped_refptr<webkit::ppapi::PluginModule> module = |
| 227 new webkit::ppapi::PluginModule(current.name, current.path, this, | 226 new webkit::ppapi::PluginModule(current.name, current.path, this, |
| 228 ppapi::PpapiPermissions(current.permissions)); | 227 ppapi::PpapiPermissions(current.permissions)); |
| 229 AddLiveModule(current.path, module); | 228 AddLiveModule(current.path, module); |
| 230 if (current.is_internal) { | 229 if (current.is_internal) { |
| 231 if (!module->InitAsInternalPlugin(current.internal_entry_points)) { | 230 if (!module->InitAsInternalPlugin(current.internal_entry_points)) { |
| 232 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); | 231 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); |
| 233 continue; | 232 continue; |
| 234 } | 233 } |
| 235 } else { | 234 } else { |
| 236 // Preload all external plugins we're not running out of process. | 235 // Preload all external plugins we're not running out of process. |
| 237 if (!module->InitAsLibrary(current.path)) { | 236 if (!module->InitAsLibrary(current.path)) { |
| 238 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); | 237 DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); |
| 239 continue; | 238 continue; |
| 240 } | 239 } |
| 241 } | 240 } |
| 242 preloaded_modules_[current.path] = module; | 241 preloaded_modules_[current.path] = module; |
| 243 } | 242 } |
| 244 } | 243 } |
| 245 | 244 |
| 245 } // namespace content |
| OLD | NEW |