Index: webkit/glue/plugins/plugin_lib_posix.cc |
=================================================================== |
--- webkit/glue/plugins/plugin_lib_posix.cc (revision 69426) |
+++ webkit/glue/plugins/plugin_lib_posix.cc (working copy) |
@@ -1,256 +0,0 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "webkit/glue/plugins/plugin_lib.h" |
- |
-#include <dlfcn.h> |
-#if defined(OS_OPENBSD) |
-#include <sys/exec_elf.h> |
-#else |
-#include <elf.h> |
-#include <fcntl.h> |
-#endif |
-#include <sys/stat.h> |
-#include <sys/types.h> |
-#include <unistd.h> |
- |
-#include "base/eintr_wrapper.h" |
-#include "base/file_util.h" |
-#include "base/string_split.h" |
-#include "base/string_util.h" |
-#include "base/sys_string_conversions.h" |
-#include "base/utf_string_conversions.h" |
-#include "webkit/glue/plugins/plugin_list.h" |
- |
-// These headers must be included in this order to make the declaration gods |
-// happy. |
-#include "base/third_party/nspr/prcpucfg_linux.h" |
- |
-namespace { |
- |
-using NPAPI::PluginList; |
- |
-// Copied from nsplugindefs.h instead of including the file since it has a bunch |
-// of dependencies. |
-enum nsPluginVariable { |
- nsPluginVariable_NameString = 1, |
- nsPluginVariable_DescriptionString = 2 |
-}; |
- |
-// Read the ELF header and return true if it is usable on |
-// the current architecture (e.g. 32-bit ELF on 32-bit build). |
-// Returns false on other errors as well. |
-bool ELFMatchesCurrentArchitecture(const FilePath& filename) { |
- // First make sure we can open the file and it is in fact, a regular file. |
- struct stat stat_buf; |
- // Open with O_NONBLOCK so we don't block on pipes. |
- int fd = open(filename.value().c_str(), O_RDONLY|O_NONBLOCK); |
- if (fd < 0) |
- return false; |
- bool ret = (fstat(fd, &stat_buf) >= 0 && S_ISREG(stat_buf.st_mode)); |
- if (HANDLE_EINTR(close(fd)) < 0) |
- return false; |
- if (!ret) |
- return false; |
- |
- const size_t kELFBufferSize = 5; |
- char buffer[kELFBufferSize]; |
- if (!file_util::ReadFile(filename, buffer, kELFBufferSize)) |
- return false; |
- |
- if (buffer[0] != ELFMAG0 || |
- buffer[1] != ELFMAG1 || |
- buffer[2] != ELFMAG2 || |
- buffer[3] != ELFMAG3) { |
- // Not an ELF file, perhaps? |
- return false; |
- } |
- |
- int elf_class = buffer[EI_CLASS]; |
-#if defined(ARCH_CPU_32_BITS) |
- if (elf_class == ELFCLASS32) |
- return true; |
-#elif defined(ARCH_CPU_64_BITS) |
- if (elf_class == ELFCLASS64) |
- return true; |
-#endif |
- |
- return false; |
-} |
- |
-// This structure matches enough of nspluginwrapper's NPW_PluginInfo |
-// for us to extract the real plugin path. |
-struct __attribute__((packed)) NSPluginWrapperInfo { |
- char ident[32]; // NSPluginWrapper magic identifier (includes version). |
- char path[PATH_MAX]; // Path to wrapped plugin. |
-}; |
- |
-// Test a plugin for whether it's been wrapped by NSPluginWrapper, and |
-// if so attempt to unwrap it. Pass in an opened plugin handle; on |
-// success, |dl| and |unwrapped_path| will be filled in with the newly |
-// opened plugin. On failure, params are left unmodified. |
-void UnwrapNSPluginWrapper(void **dl, FilePath* unwrapped_path) { |
- NSPluginWrapperInfo* info = |
- reinterpret_cast<NSPluginWrapperInfo*>(dlsym(*dl, "NPW_Plugin")); |
- if (!info) |
- return; // Not a NSPW plugin. |
- |
- // Here we could check the NSPW ident field for the versioning |
- // information, but the path field is available in all versions |
- // anyway. |
- |
- // Grab the path to the wrapped plugin. Just in case the structure |
- // format changes, protect against the path not being null-terminated. |
- char* path_end = static_cast<char*>(memchr(info->path, '\0', |
- sizeof(info->path))); |
- if (!path_end) |
- path_end = info->path + sizeof(info->path); |
- FilePath path = FilePath(std::string(info->path, path_end - info->path)); |
- |
- if (!ELFMatchesCurrentArchitecture(path)) { |
- LOG(WARNING) << path.value() << " is nspluginwrapper wrapping a " |
- << "plugin for a different architecture; it will " |
- << "work better if you instead use a native plugin."; |
- return; |
- } |
- |
- void* newdl = base::LoadNativeLibrary(path); |
- if (!newdl) { |
- // We couldn't load the unwrapped plugin for some reason, despite |
- // being able to load the wrapped one. Just use the wrapped one. |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "Could not use unwrapped nspluginwrapper plugin " |
- << unwrapped_path->value() << ", using the wrapped one."; |
- return; |
- } |
- |
- // Unload the wrapped plugin, and use the wrapped plugin instead. |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "Using unwrapped version " << unwrapped_path->value() |
- << " of nspluginwrapper-wrapped plugin."; |
- base::UnloadNativeLibrary(*dl); |
- *dl = newdl; |
- *unwrapped_path = path; |
-} |
- |
-} // anonymous namespace |
- |
-namespace NPAPI { |
- |
-bool PluginLib::ReadWebPluginInfo(const FilePath& filename, |
- WebPluginInfo* info) { |
- // The file to reference is: |
- // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp |
- |
- // Skip files that aren't appropriate for our architecture. |
- if (!ELFMatchesCurrentArchitecture(filename)) { |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "Skipping plugin " << filename.value() |
- << " because it doesn't match the current architecture."; |
- return false; |
- } |
- |
- void* dl = base::LoadNativeLibrary(filename); |
- if (!dl) { |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "While reading plugin info, unable to load library " |
- << filename.value() << ", skipping."; |
- return false; |
- } |
- |
- info->path = filename; |
- info->enabled = true; |
- |
- // Attempt to swap in the wrapped plugin if this is nspluginwrapper. |
- UnwrapNSPluginWrapper(&dl, &info->path); |
- |
- // See comments in plugin_lib_mac regarding this symbol. |
- typedef const char* (*NP_GetMimeDescriptionType)(); |
- NP_GetMimeDescriptionType NP_GetMIMEDescription = |
- reinterpret_cast<NP_GetMimeDescriptionType>( |
- dlsym(dl, "NP_GetMIMEDescription")); |
- const char* mime_description = NULL; |
- if (NP_GetMIMEDescription) |
- mime_description = NP_GetMIMEDescription(); |
- |
- if (mime_description) |
- ParseMIMEDescription(mime_description, &info->mime_types); |
- |
- // The plugin name and description live behind NP_GetValue calls. |
- typedef NPError (*NP_GetValueType)(void* unused, |
- nsPluginVariable variable, |
- void* value_out); |
- NP_GetValueType NP_GetValue = |
- reinterpret_cast<NP_GetValueType>(dlsym(dl, "NP_GetValue")); |
- if (NP_GetValue) { |
- const char* name = NULL; |
- NP_GetValue(NULL, nsPluginVariable_NameString, &name); |
- if (name) |
- info->name = UTF8ToUTF16(name); |
- |
- const char* description = NULL; |
- NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description); |
- if (description) |
- info->desc = UTF8ToUTF16(description); |
- |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "Got info for plugin " << filename.value() |
- << " Name = \"" << UTF16ToUTF8(info->name) |
- << "\", Description = \"" << UTF16ToUTF8(info->desc) << "\"."; |
- } else { |
- LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
- << "Plugin " << filename.value() |
- << " has no GetValue() and probably won't work."; |
- } |
- |
- // Intentionally not unloading the plugin here, it can lead to crashes. |
- |
- return true; |
-} |
- |
-// static |
-void PluginLib::ParseMIMEDescription( |
- const std::string& description, |
- std::vector<WebPluginMimeType>* mime_types) { |
- // We parse the description here into WebPluginMimeType structures. |
- // Naively from the NPAPI docs you'd think you could use |
- // string-splitting, but the Firefox parser turns out to do something |
- // different: find the first colon, then the second, then a semi. |
- // |
- // See ParsePluginMimeDescription near |
- // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53 |
- |
- std::string::size_type ofs = 0; |
- for (;;) { |
- WebPluginMimeType mime_type; |
- |
- std::string::size_type end = description.find(':', ofs); |
- if (end == std::string::npos) |
- break; |
- mime_type.mime_type = description.substr(ofs, end - ofs); |
- ofs = end + 1; |
- |
- end = description.find(':', ofs); |
- if (end == std::string::npos) |
- break; |
- const std::string extensions = description.substr(ofs, end - ofs); |
- base::SplitString(extensions, ',', &mime_type.file_extensions); |
- ofs = end + 1; |
- |
- end = description.find(';', ofs); |
- // It's ok for end to run off the string here. If there's no |
- // trailing semicolon we consume the remainder of the string. |
- if (end != std::string::npos) { |
- mime_type.description = UTF8ToUTF16(description.substr(ofs, end - ofs)); |
- } else { |
- mime_type.description = UTF8ToUTF16(description.substr(ofs)); |
- } |
- mime_types->push_back(mime_type); |
- if (end == std::string::npos) |
- break; |
- ofs = end + 1; |
- } |
-} |
- |
-} // namespace NPAPI |