2 // WebBasePluginPackage.m
5 // Created by Chris Blumenberg on Tue Oct 22 2002.
6 // Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
9 #import <WebKit/WebBasePluginPackage.h>
11 #import <WebKit/WebKitNSStringExtras.h>
12 #import <WebKit/WebNetscapePluginPackage.h>
13 #import <WebKit/WebNSObjectExtras.h>
14 #import <WebKit/WebPluginPackage.h>
16 #import <WebKitSystemInterface.h>
18 #define JavaCocoaPluginIdentifier @"com.apple.JavaPluginCocoa"
19 #define JavaCarbonPluginIdentifier @"com.apple.JavaAppletPlugin"
20 #define JavaCFMPluginFilename @"Java Applet Plugin Enabler"
22 #define QuickTimeCarbonPluginIdentifier @"com.apple.QuickTime Plugin.plugin"
23 #define QuickTimeCocoaPluginIdentifier @"com.apple.quicktime.webplugin"
25 @interface NSArray (WebPluginExtensions)
26 - (NSArray *)_web_lowercaseStrings;
29 @implementation WebBasePluginPackage
31 + (WebBasePluginPackage *)pluginWithPath:(NSString *)pluginPath
33 WebBasePluginPackage *pluginPackage = [[WebPluginPackage alloc] initWithPath:pluginPath];
36 pluginPackage = [[WebNetscapePluginPackage alloc] initWithPath:pluginPath];
39 return [pluginPackage autorelease];
42 + (NSString *)preferredLocalizationName
44 return WebCFAutorelease(WKCopyCFLocalizationPreferredName(NULL));
47 - (NSString *)pathByResolvingSymlinksAndAliasesInPath:(NSString *)thePath
49 NSString *newPath = [thePath stringByResolvingSymlinksInPath];
54 err = FSPathMakeRef((const UInt8 *)[thePath fileSystemRepresentation], &fref, NULL);
59 Boolean targetIsFolder;
61 err = FSResolveAliasFileWithMountFlags(&fref, TRUE, &targetIsFolder, &wasAliased, kResolveAliasFileNoUI);
67 CFURLRef URL = CFURLCreateFromFSRef(kCFAllocatorDefault, &fref);
68 newPath = [(NSURL *)URL path];
75 - initWithPath:(NSString *)pluginPath
78 extensionToMIME = [[NSMutableDictionary alloc] init];
79 path = [[self pathByResolvingSymlinksAndAliasesInPath:pluginPath] retain];
80 bundle = [[NSBundle alloc] initWithPath:path];
81 cfBundle = CFBundleCreate(NULL, (CFURLRef)[NSURL fileURLWithPath:path]);
82 lastModifiedDate = [[[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] objectForKey:NSFileModificationDate] retain];
86 - (BOOL)getPluginInfoFromBundleAndMIMEDictionary:(NSDictionary *)MIMETypes
93 MIMETypes = [bundle objectForInfoDictionaryKey:WebPluginMIMETypesKey];
99 NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary];
100 NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary];
101 NSEnumerator *keyEnumerator = [MIMETypes keyEnumerator];
102 NSDictionary *MIMEDictionary;
103 NSString *MIME, *description;
106 while ((MIME = [keyEnumerator nextObject]) != nil) {
107 MIMEDictionary = [MIMETypes objectForKey:MIME];
109 // FIXME: Consider storing disabled MIME types.
110 NSNumber *isEnabled = [MIMEDictionary objectForKey:WebPluginTypeEnabledKey];
111 if (isEnabled && [isEnabled boolValue] == NO) {
115 extensions = [[MIMEDictionary objectForKey:WebPluginExtensionsKey] _web_lowercaseStrings];
116 if ([extensions count] == 0) {
117 extensions = [NSArray arrayWithObject:@""];
120 MIME = [MIME lowercaseString];
122 [MIMEToExtensionsDictionary setObject:extensions forKey:MIME];
124 description = [MIMEDictionary objectForKey:WebPluginTypeDescriptionKey];
129 [MIMEToDescriptionDictionary setObject:description forKey:MIME];
132 [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary];
133 [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary];
135 NSString *filename = [self filename];
137 NSString *theName = [bundle objectForInfoDictionaryKey:WebPluginNameKey];
141 [self setName:theName];
143 description = [bundle objectForInfoDictionaryKey:WebPluginDescriptionKey];
145 description = filename;
147 [self setPluginDescription:description];
152 - (NSDictionary *)pListForPath:(NSString *)pListPath createFile:(BOOL)createFile
154 if (createFile && [self load] && BP_CreatePluginMIMETypesPreferences) {
155 BP_CreatePluginMIMETypesPreferences();
158 NSDictionary *pList = nil;
159 NSData *data = [NSData dataWithContentsOfFile:pListPath];
161 pList = [NSPropertyListSerialization propertyListFromData:data
162 mutabilityOption:NSPropertyListImmutable
164 errorDescription:nil];
170 - (BOOL)getPluginInfoFromPLists
176 NSDictionary *MIMETypes = nil;
177 NSString *pListFilename = [bundle objectForInfoDictionaryKey:WebPluginMIMETypesFilenameKey];
179 // Check if the MIME types are claimed in a plist in the user's preferences directory.
181 NSString *pListPath = [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), pListFilename];
182 NSDictionary *pList = [self pListForPath:pListPath createFile:NO];
184 // If the plist isn't localized, have the plug-in recreate it in the preferred language.
185 NSString *localizationName = [pList objectForKey:WebPluginLocalizationNameKey];
186 if (![localizationName isEqualToString:[[self class] preferredLocalizationName]]) {
187 pList = [self pListForPath:pListPath createFile:YES];
189 MIMETypes = [pList objectForKey:WebPluginMIMETypesKey];
191 // Plist doesn't exist, ask the plug-in to create it.
192 MIMETypes = [[self pListForPath:pListPath createFile:YES] objectForKey:WebPluginMIMETypesKey];
196 // Pass the MIME dictionary to the superclass to parse it.
197 return [self getPluginInfoFromBundleAndMIMEDictionary:MIMETypes];
207 if (isLoaded && bundle != nil && BP_CreatePluginMIMETypesPreferences == NULL) {
208 BP_CreatePluginMIMETypesPreferences = (BP_CreatePluginMIMETypesPreferencesFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
223 [pluginDescription release];
225 [MIMEToDescription release];
226 [MIMEToExtensions release];
227 [extensionToMIME release];
232 [lastModifiedDate release];
239 // FIXME: Bad design to unload at dealloc/finalize time.
240 // Must be fixed for GC.
255 - (NSString *)filename
257 return [path lastPathComponent];
260 - (NSString *)pluginDescription
262 return pluginDescription;
265 - (NSEnumerator *)extensionEnumerator
267 return [extensionToMIME keyEnumerator];
270 - (NSEnumerator *)MIMETypeEnumerator
272 return [MIMEToExtensions keyEnumerator];
275 - (NSString *)descriptionForMIMEType:(NSString *)MIMEType
277 return [MIMEToDescription objectForKey:MIMEType];
280 - (NSString *)MIMETypeForExtension:(NSString *)extension
282 return [extensionToMIME objectForKey:extension];
285 - (NSArray *)extensionsForMIMEType:(NSString *)MIMEType
287 return [MIMEToExtensions objectForKey:MIMEType];
295 - (NSDate *)lastModifiedDate
297 return lastModifiedDate;
300 - (void)setName:(NSString *)theName
303 name = [theName retain];
306 - (void)setPath:(NSString *)thePath
309 path = [thePath retain];
312 - (void)setPluginDescription:(NSString *)description
314 [pluginDescription release];
315 pluginDescription = [description retain];
318 - (void)setMIMEToDescriptionDictionary:(NSDictionary *)MIMEToDescriptionDictionary
320 [MIMEToDescription release];
321 MIMEToDescription = [MIMEToDescriptionDictionary retain];
324 - (void)setMIMEToExtensionsDictionary:(NSDictionary *)MIMEToExtensionsDictionary
326 [MIMEToExtensions release];
327 MIMEToExtensions = [MIMEToExtensionsDictionary retain];
329 // Reverse the mapping
330 [extensionToMIME removeAllObjects];
332 NSEnumerator *MIMEEnumerator = [MIMEToExtensions keyEnumerator], *extensionEnumerator;
333 NSString *MIME, *extension;
336 while ((MIME = [MIMEEnumerator nextObject]) != nil) {
337 extensions = [MIMEToExtensions objectForKey:MIME];
338 extensionEnumerator = [extensions objectEnumerator];
340 while ((extension = [extensionEnumerator nextObject]) != nil) {
341 if (![extension isEqualToString:@""]) {
342 [extensionToMIME setObject:MIME forKey:extension];
348 - (NSString *)description
350 return [NSString stringWithFormat:@"name: %@\npath: %@\nmimeTypes:\n%@\npluginDescription:%@",
351 name, path, [MIMEToExtensions description], [MIMEToDescription description], pluginDescription];
354 - (BOOL)isEqual:(id)object
356 return ([object isKindOfClass:[WebBasePluginPackage class]] &&
357 [[object name] isEqualToString:name] &&
358 [[object lastModifiedDate] isEqual:lastModifiedDate]);
363 return [[name stringByAppendingString:[lastModifiedDate description]] hash];
366 - (BOOL)isQuickTimePlugIn
368 NSString *bundleIdentifier = [[self bundle] bundleIdentifier];
369 return [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:QuickTimeCarbonPluginIdentifier] ||
370 [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:QuickTimeCocoaPluginIdentifier];
375 NSString *bundleIdentifier = [[self bundle] bundleIdentifier];
376 return [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:JavaCocoaPluginIdentifier] ||
377 [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:JavaCarbonPluginIdentifier] ||
378 [[path lastPathComponent] _webkit_isCaseInsensitiveEqualToString:JavaCFMPluginFilename];
383 @implementation NSArray (WebPluginExtensions)
385 - (NSArray *)_web_lowercaseStrings
387 NSMutableArray *lowercaseStrings = [NSMutableArray arrayWithCapacity:[self count]];
388 NSEnumerator *strings = [self objectEnumerator];
391 while ((string = [strings nextObject]) != nil) {
392 if ([string isKindOfClass:[NSString class]]) {
393 [lowercaseStrings addObject:[string lowercaseString]];
397 return lowercaseStrings;