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

Side by Side Diff: webkit/glue/plugins/plugin_lib_mac.mm

Issue 6012002: Move the NPAPI files from webkit/glue/plugins to webkit/plugins/npapi and put... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/plugin_lib.cc ('k') | webkit/glue/plugins/plugin_lib_posix.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) 2010 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 #import <Carbon/Carbon.h>
6
7 #include "webkit/glue/plugins/plugin_lib.h"
8
9 #include "base/mac/scoped_cftyperef.h"
10 #include "base/native_library.h"
11 #include "base/scoped_ptr.h"
12 #include "base/string_split.h"
13 #include "base/string_util.h"
14 #include "base/sys_string_conversions.h"
15 #include "base/utf_string_conversions.h"
16 #include "webkit/glue/plugins/plugin_list.h"
17
18 static const short kSTRTypeDefinitionResourceID = 128;
19 static const short kSTRTypeDescriptionResourceID = 127;
20 static const short kSTRPluginDescriptionResourceID = 126;
21
22 using base::mac::ScopedCFTypeRef;
23
24 namespace NPAPI {
25
26 namespace {
27
28 NSDictionary* GetMIMETypes(CFBundleRef bundle) {
29 NSString* mime_filename =
30 (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
31 CFSTR("WebPluginMIMETypesFilename"));
32
33 if (mime_filename) {
34
35 // get the file
36
37 NSString* mime_path =
38 [NSString stringWithFormat:@"%@/Library/Preferences/%@",
39 NSHomeDirectory(), mime_filename];
40 NSDictionary* mime_file_dict =
41 [NSDictionary dictionaryWithContentsOfFile:mime_path];
42
43 // is it valid?
44
45 bool valid_file = false;
46 if (mime_file_dict) {
47 NSString* l10n_name =
48 [mime_file_dict objectForKey:@"WebPluginLocalizationName"];
49 NSString* preferred_l10n = [[NSLocale currentLocale] localeIdentifier];
50 if ([l10n_name isEqualToString:preferred_l10n])
51 valid_file = true;
52 }
53
54 if (valid_file)
55 return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
56
57 // dammit, I didn't want to have to do this
58
59 typedef void (*CreateMIMETypesPrefsPtr)(void);
60 CreateMIMETypesPrefsPtr create_prefs_file =
61 (CreateMIMETypesPrefsPtr)CFBundleGetFunctionPointerForName(
62 bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
63 if (!create_prefs_file)
64 return nil;
65 create_prefs_file();
66
67 // one more time
68
69 mime_file_dict = [NSDictionary dictionaryWithContentsOfFile:mime_path];
70 if (mime_file_dict)
71 return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
72 else
73 return nil;
74
75 } else {
76 return (NSDictionary*)CFBundleGetValueForInfoDictionaryKey(bundle,
77 CFSTR("WebPluginMIMETypes"));
78 }
79 }
80
81 bool ReadPlistPluginInfo(const FilePath& filename, CFBundleRef bundle,
82 WebPluginInfo* info) {
83 NSDictionary* mime_types = GetMIMETypes(bundle);
84 if (!mime_types)
85 return false; // no type info here; try elsewhere
86
87 for (NSString* mime_type in [mime_types allKeys]) {
88 NSDictionary* mime_dict = [mime_types objectForKey:mime_type];
89 NSString* mime_desc = [mime_dict objectForKey:@"WebPluginTypeDescription"];
90 NSArray* mime_exts = [mime_dict objectForKey:@"WebPluginExtensions"];
91
92 WebPluginMimeType mime;
93 mime.mime_type = base::SysNSStringToUTF8([mime_type lowercaseString]);
94 // Remove PDF from the list of types handled by QuickTime, since it provides
95 // a worse experience than just downloading the PDF.
96 if (mime.mime_type == "application/pdf" &&
97 StartsWithASCII(filename.BaseName().value(), "QuickTime", false)) {
98 continue;
99 }
100
101 if (mime_desc)
102 mime.description = base::SysNSStringToUTF16(mime_desc);
103 for (NSString* ext in mime_exts)
104 mime.file_extensions.push_back(
105 base::SysNSStringToUTF8([ext lowercaseString]));
106
107 info->mime_types.push_back(mime);
108 }
109
110 NSString* plugin_name =
111 (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
112 CFSTR("WebPluginName"));
113 NSString* plugin_vers =
114 (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
115 CFSTR("CFBundleShortVersionString"));
116 NSString* plugin_desc =
117 (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
118 CFSTR("WebPluginDescription"));
119
120 if (plugin_name)
121 info->name = base::SysNSStringToUTF16(plugin_name);
122 else
123 info->name = UTF8ToUTF16(filename.BaseName().value());
124 info->path = filename;
125 if (plugin_vers)
126 info->version = base::SysNSStringToUTF16(plugin_vers);
127 if (plugin_desc)
128 info->desc = base::SysNSStringToUTF16(plugin_desc);
129 else
130 info->desc = UTF8ToUTF16(filename.BaseName().value());
131 info->enabled = true;
132
133 return true;
134 }
135
136 class ScopedBundleResourceFile {
137 public:
138 ScopedBundleResourceFile(CFBundleRef bundle) : bundle_(bundle) {
139 old_ref_num_ = CurResFile();
140 bundle_ref_num_ = CFBundleOpenBundleResourceMap(bundle);
141 UseResFile(bundle_ref_num_);
142 }
143 ~ScopedBundleResourceFile() {
144 UseResFile(old_ref_num_);
145 CFBundleCloseBundleResourceMap(bundle_, bundle_ref_num_);
146 }
147
148 private:
149 CFBundleRef bundle_;
150 CFBundleRefNum bundle_ref_num_;
151 ResFileRefNum old_ref_num_;
152 };
153
154 bool GetSTRResource(CFBundleRef bundle, short res_id,
155 std::vector<std::string>* contents) {
156 Handle res_handle = Get1Resource('STR#', res_id);
157 if (!res_handle || !*res_handle)
158 return false;
159
160 char* pointer = *res_handle;
161 short num_strings = *(short*)pointer;
162 pointer += sizeof(short);
163 for (short i = 0; i < num_strings; ++i) {
164 // Despite being 8-bits wide, these are legacy encoded. Make a round trip.
165 ScopedCFTypeRef<CFStringRef> str(CFStringCreateWithPascalStringNoCopy(
166 kCFAllocatorDefault,
167 (unsigned char*)pointer,
168 GetApplicationTextEncoding(), // is this right?
169 kCFAllocatorNull)); // perhaps CFStringGetSystemEncoding?
170 if (!str.get())
171 return false;
172 contents->push_back(base::SysCFStringRefToUTF8(str.get()));
173 pointer += 1+*reinterpret_cast<unsigned char*>(pointer);
174 }
175
176 return true;
177 }
178
179 bool ReadSTRPluginInfo(const FilePath& filename, CFBundleRef bundle,
180 WebPluginInfo* info) {
181 ScopedBundleResourceFile res_file(bundle);
182
183 std::vector<std::string> type_strings;
184 if (!GetSTRResource(bundle, kSTRTypeDefinitionResourceID, &type_strings))
185 return false;
186
187 std::vector<std::string> type_descs;
188 bool have_type_descs = GetSTRResource(bundle,
189 kSTRTypeDescriptionResourceID,
190 &type_descs);
191
192 std::vector<std::string> plugin_descs;
193 bool have_plugin_descs = GetSTRResource(bundle,
194 kSTRPluginDescriptionResourceID,
195 &plugin_descs);
196
197 size_t num_types = type_strings.size()/2;
198
199 for (size_t i = 0; i < num_types; ++i) {
200 WebPluginMimeType mime;
201 mime.mime_type = StringToLowerASCII(type_strings[2*i]);
202 if (have_type_descs && i < type_descs.size())
203 mime.description = UTF8ToUTF16(type_descs[i]);
204 base::SplitString(
205 StringToLowerASCII(type_strings[2*i+1]), ',', &mime.file_extensions);
206
207 info->mime_types.push_back(mime);
208 }
209
210 NSString* plugin_vers =
211 (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
212 CFSTR("CFBundleShortVersionString"));
213
214 if (have_plugin_descs && plugin_descs.size() > 1)
215 info->name = UTF8ToUTF16(plugin_descs[1]);
216 else
217 info->name = UTF8ToUTF16(filename.BaseName().value());
218 info->path = filename;
219 if (plugin_vers)
220 info->version = base::SysNSStringToUTF16(plugin_vers);
221 if (have_plugin_descs && plugin_descs.size() > 0)
222 info->desc = UTF8ToUTF16(plugin_descs[0]);
223 else
224 info->desc = UTF8ToUTF16(filename.BaseName().value());
225 info->enabled = true;
226
227 return true;
228 }
229
230 } // anonymous namespace
231
232 bool PluginLib::ReadWebPluginInfo(const FilePath &filename,
233 WebPluginInfo* info) {
234 // There are two ways to get information about plugin capabilities. One is an
235 // Info.plist set of keys, documented at
236 // http://developer.apple.com/documentation/InternetWeb/Conceptual/WebKit_Plug inProgTopic/Concepts/AboutPlugins.html .
237 // The other is a set of STR# resources, documented at
238 // https://developer.mozilla.org/En/Gecko_Plugin_API_Reference/Plug-in_Develop ment_Overview .
239 //
240 // Historically, the data was maintained in the STR# resources. Apple, with
241 // the introduction of WebKit, noted the weaknesses of resources and moved the
242 // information into the Info.plist. Mozilla had always supported a
243 // NP_GetMIMEDescription() entry point for Unix plugins and also supports it
244 // on the Mac to supplement the STR# format. WebKit does not support
245 // NP_GetMIMEDescription() and neither do we. (That entry point is documented
246 // at https://developer.mozilla.org/en/NP_GetMIMEDescription .) We prefer the
247 // Info.plist format because it's more extensible and has a defined encoding,
248 // but will fall back to the STR# format of the data if it is not present in
249 // the Info.plist.
250 //
251 // The parsing of the data lives in the two functions ReadSTRPluginInfo() and
252 // ReadPlistPluginInfo(), but a summary of the formats follows.
253 //
254 // Each data type handled by a plugin has several properties:
255 // - <<type0mimetype>>
256 // - <<type0fileextension0>>..<<type0fileextensionk>>
257 // - <<type0description>>
258 //
259 // Each plugin may have any number of types defined. In addition, the plugin
260 // itself has properties:
261 // - <<plugindescription>>
262 // - <<pluginname>>
263 //
264 // For the Info.plist version, the data is formatted as follows (in text plist
265 // format):
266 // {
267 // ... the usual plist keys ...
268 // WebPluginDescription = <<plugindescription>>;
269 // WebPluginMIMETypes = {
270 // <<type0mimetype>> = {
271 // WebPluginExtensions = (
272 // <<type0fileextension0>>,
273 // ...
274 // <<type0fileextensionk>>,
275 // );
276 // WebPluginTypeDescription = <<type0description>>;
277 // };
278 // <<type1mimetype>> = { ... };
279 // ...
280 // <<typenmimetype>> = { ... };
281 // };
282 // WebPluginName = <<pluginname>>;
283 // }
284 //
285 // Alternatively (and this is undocumented), rather than a WebPluginMIMETypes
286 // key, there may be a WebPluginMIMETypesFilename key. If it is present, then
287 // it is the name of a file in the user's preferences folder in which to find
288 // the WebPluginMIMETypes key. If the key is present but the file doesn't
289 // exist, we must load the plugin and call a specific function to have the
290 // plugin create the file.
291 //
292 // If we do not find those keys in the Info.plist, we fall back to the STR#
293 // resources. In them, the data is formatted as follows:
294 // STR# 128
295 // (1) <<type0mimetype>>
296 // (2) <<type0fileextension0>>,...,<<type0fileextensionk>>
297 // (3) <<type1mimetype>>
298 // (4) <<type1fileextension0>>,...,<<type1fileextensionk>>
299 // (...)
300 // (2n+1) <<typenmimetype>>
301 // (2n+2) <<typenfileextension0>>,...,<<typenfileextensionk>>
302 // STR# 127
303 // (1) <<type0description>>
304 // (2) <<type1description>>
305 // (...)
306 // (n+1) <<typendescription>>
307 // STR# 126
308 // (1) <<plugindescription>>
309 // (2) <<pluginname>>
310 //
311 // Strictly speaking, only STR# 128 is required.
312
313 ScopedCFTypeRef<CFURLRef> bundle_url(CFURLCreateFromFileSystemRepresentation(
314 kCFAllocatorDefault, (const UInt8*)filename.value().c_str(),
315 filename.value().length(), true));
316 if (!bundle_url)
317 return false;
318 ScopedCFTypeRef<CFBundleRef> bundle(CFBundleCreate(kCFAllocatorDefault,
319 bundle_url.get()));
320 if (!bundle)
321 return false;
322
323 // preflight
324
325 OSType type = 0;
326 CFBundleGetPackageInfo(bundle.get(), &type, NULL);
327 if (type != FOUR_CHAR_CODE('BRPL'))
328 return false;
329
330 CFErrorRef error;
331 Boolean would_load = CFBundlePreflightExecutable(bundle.get(), &error);
332 if (!would_load)
333 return false;
334
335 // get the info
336
337 if (ReadPlistPluginInfo(filename, bundle.get(), info))
338 return true;
339
340 if (ReadSTRPluginInfo(filename, bundle.get(), info))
341 return true;
342
343 // ... or not
344
345 return false;
346 }
347
348 } // namespace NPAPI
OLDNEW
« no previous file with comments | « webkit/glue/plugins/plugin_lib.cc ('k') | webkit/glue/plugins/plugin_lib_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698