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 <Foundation/NSPrivateDecls.h>
18 #import <CoreFoundation/CFBundlePriv.h>
20 #define JavaCocoaPluginIdentifier @"com.apple.JavaPluginCocoa"
21 #define JavaCarbonPluginIdentifier @"com.apple.JavaAppletPlugin"
22 #define JavaCFMPluginFilename @"Java Applet Plugin Enabler"
24 #define QuickTimeCarbonPluginIdentifier @"com.apple.QuickTime Plugin.plugin"
25 #define QuickTimeCocoaPluginIdentifier @"com.apple.quicktime.webplugin"
27 @interface NSArray (WebPluginExtensions)
28 - (NSArray *)_web_lowercaseStrings;
31 @implementation WebBasePluginPackage
33 + (WebBasePluginPackage *)pluginWithPath:(NSString *)pluginPath
35 WebBasePluginPackage *pluginPackage = [[WebPluginPackage alloc] initWithPath:pluginPath];
38 pluginPackage = [[WebNetscapePluginPackage alloc] initWithPath:pluginPath];
41 return [pluginPackage autorelease];
44 + (NSString *)preferredLocalizationName
49 CFStringEncoding stringEncoding;
51 CFBundleGetLocalizationInfoForLocalization(NULL, &languageCode, ®ionCode, &scriptCode, &stringEncoding);
52 return WebCFAutorelease(CFBundleCopyLocalizationForLocalizationInfo(languageCode, regionCode, scriptCode, stringEncoding));
55 - (NSString *)pathByResolvingSymlinksAndAliasesInPath:(NSString *)thePath
57 NSString *newPath = [thePath stringByResolvingSymlinksInPath];
62 err = FSPathMakeRef((const UInt8 *)[thePath fileSystemRepresentation], &fref, NULL);
67 Boolean targetIsFolder;
69 err = FSResolveAliasFileWithMountFlags(&fref, TRUE, &targetIsFolder, &wasAliased, kResolveAliasFileNoUI);
75 CFURLRef URL = CFURLCreateFromFSRef(kCFAllocatorDefault, &fref);
76 newPath = [(NSURL *)URL path];
83 - initWithPath:(NSString *)pluginPath
86 extensionToMIME = [[NSMutableDictionary alloc] init];
87 path = [[self pathByResolvingSymlinksAndAliasesInPath:pluginPath] retain];
88 bundle = [[NSBundle alloc] initWithPath:path];
89 lastModifiedDate = [[[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] objectForKey:NSFileModificationDate] retain];
93 - (BOOL)getPluginInfoFromBundleAndMIMEDictionary:(NSDictionary *)MIMETypes
100 MIMETypes = [bundle objectForInfoDictionaryKey:WebPluginMIMETypesKey];
106 NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary];
107 NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary];
108 NSEnumerator *keyEnumerator = [MIMETypes keyEnumerator];
109 NSDictionary *MIMEDictionary;
110 NSString *MIME, *description;
113 while ((MIME = [keyEnumerator nextObject]) != nil) {
114 MIMEDictionary = [MIMETypes objectForKey:MIME];
116 // FIXME: Consider storing disabled MIME types.
117 NSNumber *isEnabled = [MIMEDictionary objectForKey:WebPluginTypeEnabledKey];
118 if (isEnabled && [isEnabled boolValue] == NO) {
122 extensions = [[MIMEDictionary objectForKey:WebPluginExtensionsKey] _web_lowercaseStrings];
123 if ([extensions count] == 0) {
124 extensions = [NSArray arrayWithObject:@""];
127 MIME = [MIME lowercaseString];
129 [MIMEToExtensionsDictionary setObject:extensions forKey:MIME];
131 description = [MIMEDictionary objectForKey:WebPluginTypeDescriptionKey];
136 [MIMEToDescriptionDictionary setObject:description forKey:MIME];
139 [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary];
140 [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary];
142 NSString *filename = [self filename];
144 NSString *theName = [bundle objectForInfoDictionaryKey:WebPluginNameKey];
148 [self setName:theName];
150 description = [bundle objectForInfoDictionaryKey:WebPluginDescriptionKey];
152 description = filename;
154 [self setPluginDescription:description];
159 - (NSDictionary *)pListForPath:(NSString *)pListPath createFile:(BOOL)createFile
161 if (createFile && [self load] && BP_CreatePluginMIMETypesPreferences) {
162 BP_CreatePluginMIMETypesPreferences();
165 NSDictionary *pList = nil;
166 NSData *data = [NSData dataWithContentsOfFile:pListPath];
168 pList = [NSPropertyListSerialization propertyListFromData:data
169 mutabilityOption:NSPropertyListImmutable
171 errorDescription:nil];
177 - (BOOL)getPluginInfoFromPLists
183 NSDictionary *MIMETypes = nil;
184 NSString *pListFilename = [bundle objectForInfoDictionaryKey:WebPluginMIMETypesFilenameKey];
186 // Check if the MIME types are claimed in a plist in the user's preferences directory.
188 NSString *pListPath = [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), pListFilename];
189 NSDictionary *pList = [self pListForPath:pListPath createFile:NO];
191 // If the plist isn't localized, have the plug-in recreate it in the preferred language.
192 NSString *localizationName = [pList objectForKey:WebPluginLocalizationNameKey];
193 if (![localizationName isEqualToString:[[self class] preferredLocalizationName]]) {
194 pList = [self pListForPath:pListPath createFile:YES];
196 MIMETypes = [pList objectForKey:WebPluginMIMETypesKey];
198 // Plist doesn't exist, ask the plug-in to create it.
199 MIMETypes = [[self pListForPath:pListPath createFile:YES] objectForKey:WebPluginMIMETypesKey];
203 // Pass the MIME dictionary to the superclass to parse it.
204 return [self getPluginInfoFromBundleAndMIMEDictionary:MIMETypes];
214 if (isLoaded && bundle != nil && BP_CreatePluginMIMETypesPreferences == NULL) {
215 BP_CreatePluginMIMETypesPreferences = (BP_CreatePluginMIMETypesPreferencesFuncPtr)CFBundleGetFunctionPointerForName([bundle _cfBundle], CFSTR("BP_CreatePluginMIMETypesPreferences"));
230 [pluginDescription release];
232 [MIMEToDescription release];
233 [MIMEToExtensions release];
234 [extensionToMIME release];
238 [lastModifiedDate release];
245 // FIXME: Bad design to unload at dealloc/finalize time.
246 // Must be fixed for GC.
261 - (NSString *)filename
263 return [path lastPathComponent];
266 - (NSString *)pluginDescription
268 return pluginDescription;
271 - (NSEnumerator *)extensionEnumerator
273 return [extensionToMIME keyEnumerator];
276 - (NSEnumerator *)MIMETypeEnumerator
278 return [MIMEToExtensions keyEnumerator];
281 - (NSString *)descriptionForMIMEType:(NSString *)MIMEType
283 return [MIMEToDescription objectForKey:MIMEType];
286 - (NSString *)MIMETypeForExtension:(NSString *)extension
288 return [extensionToMIME objectForKey:extension];
291 - (NSArray *)extensionsForMIMEType:(NSString *)MIMEType
293 return [MIMEToExtensions objectForKey:MIMEType];
301 - (NSDate *)lastModifiedDate
303 return lastModifiedDate;
306 - (void)setName:(NSString *)theName
309 name = [theName retain];
312 - (void)setPath:(NSString *)thePath
315 path = [thePath retain];
318 - (void)setPluginDescription:(NSString *)description
320 [pluginDescription release];
321 pluginDescription = [description retain];
324 - (void)setMIMEToDescriptionDictionary:(NSDictionary *)MIMEToDescriptionDictionary
326 [MIMEToDescription release];
327 MIMEToDescription = [MIMEToDescriptionDictionary retain];
330 - (void)setMIMEToExtensionsDictionary:(NSDictionary *)MIMEToExtensionsDictionary
332 [MIMEToExtensions release];
333 MIMEToExtensions = [MIMEToExtensionsDictionary retain];
335 // Reverse the mapping
336 [extensionToMIME removeAllObjects];
338 NSEnumerator *MIMEEnumerator = [MIMEToExtensions keyEnumerator], *extensionEnumerator;
339 NSString *MIME, *extension;
342 while ((MIME = [MIMEEnumerator nextObject]) != nil) {
343 extensions = [MIMEToExtensions objectForKey:MIME];
344 extensionEnumerator = [extensions objectEnumerator];
346 while ((extension = [extensionEnumerator nextObject]) != nil) {
347 if (![extension isEqualToString:@""]) {
348 [extensionToMIME setObject:MIME forKey:extension];
354 - (NSString *)description
356 return [NSString stringWithFormat:@"name: %@\npath: %@\nmimeTypes:\n%@\npluginDescription:%@",
357 name, path, [MIMEToExtensions description], [MIMEToDescription description], pluginDescription];
360 - (BOOL)isEqual:(id)object
362 return ([object isKindOfClass:[WebBasePluginPackage class]] &&
363 [[object name] isEqualToString:name] &&
364 [[object lastModifiedDate] isEqual:lastModifiedDate]);
369 return [[name stringByAppendingString:[lastModifiedDate description]] hash];
372 - (BOOL)isQuickTimePlugIn
374 NSString *bundleIdentifier = [[self bundle] bundleIdentifier];
375 return [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:QuickTimeCarbonPluginIdentifier] ||
376 [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:QuickTimeCocoaPluginIdentifier];
381 NSString *bundleIdentifier = [[self bundle] bundleIdentifier];
382 return [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:JavaCocoaPluginIdentifier] ||
383 [bundleIdentifier _webkit_isCaseInsensitiveEqualToString:JavaCarbonPluginIdentifier] ||
384 [[path lastPathComponent] _webkit_isCaseInsensitiveEqualToString:JavaCFMPluginFilename];
389 @implementation NSArray (WebPluginExtensions)
391 - (NSArray *)_web_lowercaseStrings
393 NSMutableArray *lowercaseStrings = [NSMutableArray arrayWithCapacity:[self count]];
394 NSEnumerator *strings = [self objectEnumerator];
397 while ((string = [strings nextObject]) != nil) {
398 if ([string isKindOfClass:[NSString class]]) {
399 [lowercaseStrings addObject:[string lowercaseString]];
403 return lowercaseStrings;