| Index: webkit/glue/plugins/plugin_lib_mac.mm
|
| ===================================================================
|
| --- webkit/glue/plugins/plugin_lib_mac.mm (revision 69426)
|
| +++ webkit/glue/plugins/plugin_lib_mac.mm (working copy)
|
| @@ -1,348 +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.
|
| -
|
| -#import <Carbon/Carbon.h>
|
| -
|
| -#include "webkit/glue/plugins/plugin_lib.h"
|
| -
|
| -#include "base/mac/scoped_cftyperef.h"
|
| -#include "base/native_library.h"
|
| -#include "base/scoped_ptr.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"
|
| -
|
| -static const short kSTRTypeDefinitionResourceID = 128;
|
| -static const short kSTRTypeDescriptionResourceID = 127;
|
| -static const short kSTRPluginDescriptionResourceID = 126;
|
| -
|
| -using base::mac::ScopedCFTypeRef;
|
| -
|
| -namespace NPAPI {
|
| -
|
| -namespace {
|
| -
|
| -NSDictionary* GetMIMETypes(CFBundleRef bundle) {
|
| - NSString* mime_filename =
|
| - (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("WebPluginMIMETypesFilename"));
|
| -
|
| - if (mime_filename) {
|
| -
|
| - // get the file
|
| -
|
| - NSString* mime_path =
|
| - [NSString stringWithFormat:@"%@/Library/Preferences/%@",
|
| - NSHomeDirectory(), mime_filename];
|
| - NSDictionary* mime_file_dict =
|
| - [NSDictionary dictionaryWithContentsOfFile:mime_path];
|
| -
|
| - // is it valid?
|
| -
|
| - bool valid_file = false;
|
| - if (mime_file_dict) {
|
| - NSString* l10n_name =
|
| - [mime_file_dict objectForKey:@"WebPluginLocalizationName"];
|
| - NSString* preferred_l10n = [[NSLocale currentLocale] localeIdentifier];
|
| - if ([l10n_name isEqualToString:preferred_l10n])
|
| - valid_file = true;
|
| - }
|
| -
|
| - if (valid_file)
|
| - return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
|
| -
|
| - // dammit, I didn't want to have to do this
|
| -
|
| - typedef void (*CreateMIMETypesPrefsPtr)(void);
|
| - CreateMIMETypesPrefsPtr create_prefs_file =
|
| - (CreateMIMETypesPrefsPtr)CFBundleGetFunctionPointerForName(
|
| - bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
|
| - if (!create_prefs_file)
|
| - return nil;
|
| - create_prefs_file();
|
| -
|
| - // one more time
|
| -
|
| - mime_file_dict = [NSDictionary dictionaryWithContentsOfFile:mime_path];
|
| - if (mime_file_dict)
|
| - return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
|
| - else
|
| - return nil;
|
| -
|
| - } else {
|
| - return (NSDictionary*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("WebPluginMIMETypes"));
|
| - }
|
| -}
|
| -
|
| -bool ReadPlistPluginInfo(const FilePath& filename, CFBundleRef bundle,
|
| - WebPluginInfo* info) {
|
| - NSDictionary* mime_types = GetMIMETypes(bundle);
|
| - if (!mime_types)
|
| - return false; // no type info here; try elsewhere
|
| -
|
| - for (NSString* mime_type in [mime_types allKeys]) {
|
| - NSDictionary* mime_dict = [mime_types objectForKey:mime_type];
|
| - NSString* mime_desc = [mime_dict objectForKey:@"WebPluginTypeDescription"];
|
| - NSArray* mime_exts = [mime_dict objectForKey:@"WebPluginExtensions"];
|
| -
|
| - WebPluginMimeType mime;
|
| - mime.mime_type = base::SysNSStringToUTF8([mime_type lowercaseString]);
|
| - // Remove PDF from the list of types handled by QuickTime, since it provides
|
| - // a worse experience than just downloading the PDF.
|
| - if (mime.mime_type == "application/pdf" &&
|
| - StartsWithASCII(filename.BaseName().value(), "QuickTime", false)) {
|
| - continue;
|
| - }
|
| -
|
| - if (mime_desc)
|
| - mime.description = base::SysNSStringToUTF16(mime_desc);
|
| - for (NSString* ext in mime_exts)
|
| - mime.file_extensions.push_back(
|
| - base::SysNSStringToUTF8([ext lowercaseString]));
|
| -
|
| - info->mime_types.push_back(mime);
|
| - }
|
| -
|
| - NSString* plugin_name =
|
| - (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("WebPluginName"));
|
| - NSString* plugin_vers =
|
| - (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("CFBundleShortVersionString"));
|
| - NSString* plugin_desc =
|
| - (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("WebPluginDescription"));
|
| -
|
| - if (plugin_name)
|
| - info->name = base::SysNSStringToUTF16(plugin_name);
|
| - else
|
| - info->name = UTF8ToUTF16(filename.BaseName().value());
|
| - info->path = filename;
|
| - if (plugin_vers)
|
| - info->version = base::SysNSStringToUTF16(plugin_vers);
|
| - if (plugin_desc)
|
| - info->desc = base::SysNSStringToUTF16(plugin_desc);
|
| - else
|
| - info->desc = UTF8ToUTF16(filename.BaseName().value());
|
| - info->enabled = true;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -class ScopedBundleResourceFile {
|
| - public:
|
| - ScopedBundleResourceFile(CFBundleRef bundle) : bundle_(bundle) {
|
| - old_ref_num_ = CurResFile();
|
| - bundle_ref_num_ = CFBundleOpenBundleResourceMap(bundle);
|
| - UseResFile(bundle_ref_num_);
|
| - }
|
| - ~ScopedBundleResourceFile() {
|
| - UseResFile(old_ref_num_);
|
| - CFBundleCloseBundleResourceMap(bundle_, bundle_ref_num_);
|
| - }
|
| -
|
| - private:
|
| - CFBundleRef bundle_;
|
| - CFBundleRefNum bundle_ref_num_;
|
| - ResFileRefNum old_ref_num_;
|
| -};
|
| -
|
| -bool GetSTRResource(CFBundleRef bundle, short res_id,
|
| - std::vector<std::string>* contents) {
|
| - Handle res_handle = Get1Resource('STR#', res_id);
|
| - if (!res_handle || !*res_handle)
|
| - return false;
|
| -
|
| - char* pointer = *res_handle;
|
| - short num_strings = *(short*)pointer;
|
| - pointer += sizeof(short);
|
| - for (short i = 0; i < num_strings; ++i) {
|
| - // Despite being 8-bits wide, these are legacy encoded. Make a round trip.
|
| - ScopedCFTypeRef<CFStringRef> str(CFStringCreateWithPascalStringNoCopy(
|
| - kCFAllocatorDefault,
|
| - (unsigned char*)pointer,
|
| - GetApplicationTextEncoding(), // is this right?
|
| - kCFAllocatorNull)); // perhaps CFStringGetSystemEncoding?
|
| - if (!str.get())
|
| - return false;
|
| - contents->push_back(base::SysCFStringRefToUTF8(str.get()));
|
| - pointer += 1+*reinterpret_cast<unsigned char*>(pointer);
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ReadSTRPluginInfo(const FilePath& filename, CFBundleRef bundle,
|
| - WebPluginInfo* info) {
|
| - ScopedBundleResourceFile res_file(bundle);
|
| -
|
| - std::vector<std::string> type_strings;
|
| - if (!GetSTRResource(bundle, kSTRTypeDefinitionResourceID, &type_strings))
|
| - return false;
|
| -
|
| - std::vector<std::string> type_descs;
|
| - bool have_type_descs = GetSTRResource(bundle,
|
| - kSTRTypeDescriptionResourceID,
|
| - &type_descs);
|
| -
|
| - std::vector<std::string> plugin_descs;
|
| - bool have_plugin_descs = GetSTRResource(bundle,
|
| - kSTRPluginDescriptionResourceID,
|
| - &plugin_descs);
|
| -
|
| - size_t num_types = type_strings.size()/2;
|
| -
|
| - for (size_t i = 0; i < num_types; ++i) {
|
| - WebPluginMimeType mime;
|
| - mime.mime_type = StringToLowerASCII(type_strings[2*i]);
|
| - if (have_type_descs && i < type_descs.size())
|
| - mime.description = UTF8ToUTF16(type_descs[i]);
|
| - base::SplitString(
|
| - StringToLowerASCII(type_strings[2*i+1]), ',', &mime.file_extensions);
|
| -
|
| - info->mime_types.push_back(mime);
|
| - }
|
| -
|
| - NSString* plugin_vers =
|
| - (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
|
| - CFSTR("CFBundleShortVersionString"));
|
| -
|
| - if (have_plugin_descs && plugin_descs.size() > 1)
|
| - info->name = UTF8ToUTF16(plugin_descs[1]);
|
| - else
|
| - info->name = UTF8ToUTF16(filename.BaseName().value());
|
| - info->path = filename;
|
| - if (plugin_vers)
|
| - info->version = base::SysNSStringToUTF16(plugin_vers);
|
| - if (have_plugin_descs && plugin_descs.size() > 0)
|
| - info->desc = UTF8ToUTF16(plugin_descs[0]);
|
| - else
|
| - info->desc = UTF8ToUTF16(filename.BaseName().value());
|
| - info->enabled = true;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // anonymous namespace
|
| -
|
| -bool PluginLib::ReadWebPluginInfo(const FilePath &filename,
|
| - WebPluginInfo* info) {
|
| - // There are two ways to get information about plugin capabilities. One is an
|
| - // Info.plist set of keys, documented at
|
| - // http://developer.apple.com/documentation/InternetWeb/Conceptual/WebKit_PluginProgTopic/Concepts/AboutPlugins.html .
|
| - // The other is a set of STR# resources, documented at
|
| - // https://developer.mozilla.org/En/Gecko_Plugin_API_Reference/Plug-in_Development_Overview .
|
| - //
|
| - // Historically, the data was maintained in the STR# resources. Apple, with
|
| - // the introduction of WebKit, noted the weaknesses of resources and moved the
|
| - // information into the Info.plist. Mozilla had always supported a
|
| - // NP_GetMIMEDescription() entry point for Unix plugins and also supports it
|
| - // on the Mac to supplement the STR# format. WebKit does not support
|
| - // NP_GetMIMEDescription() and neither do we. (That entry point is documented
|
| - // at https://developer.mozilla.org/en/NP_GetMIMEDescription .) We prefer the
|
| - // Info.plist format because it's more extensible and has a defined encoding,
|
| - // but will fall back to the STR# format of the data if it is not present in
|
| - // the Info.plist.
|
| - //
|
| - // The parsing of the data lives in the two functions ReadSTRPluginInfo() and
|
| - // ReadPlistPluginInfo(), but a summary of the formats follows.
|
| - //
|
| - // Each data type handled by a plugin has several properties:
|
| - // - <<type0mimetype>>
|
| - // - <<type0fileextension0>>..<<type0fileextensionk>>
|
| - // - <<type0description>>
|
| - //
|
| - // Each plugin may have any number of types defined. In addition, the plugin
|
| - // itself has properties:
|
| - // - <<plugindescription>>
|
| - // - <<pluginname>>
|
| - //
|
| - // For the Info.plist version, the data is formatted as follows (in text plist
|
| - // format):
|
| - // {
|
| - // ... the usual plist keys ...
|
| - // WebPluginDescription = <<plugindescription>>;
|
| - // WebPluginMIMETypes = {
|
| - // <<type0mimetype>> = {
|
| - // WebPluginExtensions = (
|
| - // <<type0fileextension0>>,
|
| - // ...
|
| - // <<type0fileextensionk>>,
|
| - // );
|
| - // WebPluginTypeDescription = <<type0description>>;
|
| - // };
|
| - // <<type1mimetype>> = { ... };
|
| - // ...
|
| - // <<typenmimetype>> = { ... };
|
| - // };
|
| - // WebPluginName = <<pluginname>>;
|
| - // }
|
| - //
|
| - // Alternatively (and this is undocumented), rather than a WebPluginMIMETypes
|
| - // key, there may be a WebPluginMIMETypesFilename key. If it is present, then
|
| - // it is the name of a file in the user's preferences folder in which to find
|
| - // the WebPluginMIMETypes key. If the key is present but the file doesn't
|
| - // exist, we must load the plugin and call a specific function to have the
|
| - // plugin create the file.
|
| - //
|
| - // If we do not find those keys in the Info.plist, we fall back to the STR#
|
| - // resources. In them, the data is formatted as follows:
|
| - // STR# 128
|
| - // (1) <<type0mimetype>>
|
| - // (2) <<type0fileextension0>>,...,<<type0fileextensionk>>
|
| - // (3) <<type1mimetype>>
|
| - // (4) <<type1fileextension0>>,...,<<type1fileextensionk>>
|
| - // (...)
|
| - // (2n+1) <<typenmimetype>>
|
| - // (2n+2) <<typenfileextension0>>,...,<<typenfileextensionk>>
|
| - // STR# 127
|
| - // (1) <<type0description>>
|
| - // (2) <<type1description>>
|
| - // (...)
|
| - // (n+1) <<typendescription>>
|
| - // STR# 126
|
| - // (1) <<plugindescription>>
|
| - // (2) <<pluginname>>
|
| - //
|
| - // Strictly speaking, only STR# 128 is required.
|
| -
|
| - ScopedCFTypeRef<CFURLRef> bundle_url(CFURLCreateFromFileSystemRepresentation(
|
| - kCFAllocatorDefault, (const UInt8*)filename.value().c_str(),
|
| - filename.value().length(), true));
|
| - if (!bundle_url)
|
| - return false;
|
| - ScopedCFTypeRef<CFBundleRef> bundle(CFBundleCreate(kCFAllocatorDefault,
|
| - bundle_url.get()));
|
| - if (!bundle)
|
| - return false;
|
| -
|
| - // preflight
|
| -
|
| - OSType type = 0;
|
| - CFBundleGetPackageInfo(bundle.get(), &type, NULL);
|
| - if (type != FOUR_CHAR_CODE('BRPL'))
|
| - return false;
|
| -
|
| - CFErrorRef error;
|
| - Boolean would_load = CFBundlePreflightExecutable(bundle.get(), &error);
|
| - if (!would_load)
|
| - return false;
|
| -
|
| - // get the info
|
| -
|
| - if (ReadPlistPluginInfo(filename, bundle.get(), info))
|
| - return true;
|
| -
|
| - if (ReadSTRPluginInfo(filename, bundle.get(), info))
|
| - return true;
|
| -
|
| - // ... or not
|
| -
|
| - return false;
|
| -}
|
| -
|
| -} // namespace NPAPI
|
|
|