822573b599fa38d82a954826b915a67c43cc8758
[WebKit-https.git] / WebKit / Plugins / WebNetscapePluginPackage.m
1 /*
2  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import <WebKit/WebNetscapePluginPackage.h>
30
31 #import <WebKit/WebKitLogging.h>
32 #import <WebKit/WebKitNSStringExtras.h>
33 #import <WebKit/WebNSObjectExtras.h>
34
35 #import "WebNetscapeDeprecatedFunctions.h"
36
37 #import <JavaScriptCore/npruntime_impl.h>
38
39 typedef void (* FunctionPointer) (void);
40 typedef void (* TransitionVector) (void);
41 static FunctionPointer functionPointerForTVector(TransitionVector);
42 static TransitionVector tVectorForFunctionPointer(FunctionPointer);
43
44 #define PluginNameOrDescriptionStringNumber     126
45 #define MIMEDescriptionStringNumber             127
46 #define MIMEListStringStringNumber              128
47
48 #define RealPlayerAppIndentifier                @"com.RealNetworks.RealOne Player"
49 #define RealPlayerPluginFilename                @"RealPlayer Plugin"
50
51 @implementation WebNetscapePluginPackage
52
53 #if !__LP64__
54 + (void)initialize
55 {
56     // The Shockwave plugin requires a valid file in CurApRefNum.
57     // But it doesn't seem to matter what file it is.
58     // If we're called inside a Cocoa application which won't have a
59     // CurApRefNum, we set it to point to the system resource file.
60     if (WebLMGetCurApRefNum() == -1) {
61         // To get the refNum for the system resource file, we have to do
62         // UseResFile(kSystemResFile) and then look at CurResFile().
63         short savedCurResFile = CurResFile();
64         UseResFile(kSystemResFile);
65         WebLMSetCurApRefNum(CurResFile());
66         UseResFile(savedCurResFile);
67     }
68 }
69 #endif
70
71 - (SInt16)openResourceFile
72 {
73     FSRef fref;
74     OSErr err;
75     
76     if (isBundle) {
77         return CFBundleOpenBundleResourceMap(cfBundle);
78     } else {
79         err = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &fref, NULL);
80         if (err != noErr) {
81             return -1;
82         }
83         
84         return FSOpenResFile(&fref, fsRdPerm);
85     }
86 }
87
88 - (void)closeResourceFile:(SInt16)resRef
89 {
90     if (isBundle) {
91         CFBundleCloseBundleResourceMap(cfBundle, resRef);
92     } else {
93         CloseResFile(resRef);
94     }
95 }
96
97 - (NSString *)stringForStringListID:(SInt16)stringListID andIndex:(SInt16)index
98 {
99     // Get resource, and dereference the handle.
100     Handle stringHandle = Get1Resource('STR#', stringListID);
101     if (stringHandle == NULL) {
102         return nil;
103     }
104     unsigned char *p = (unsigned char *)*stringHandle;
105     if (p == NULL) {
106         return nil;
107     }
108     
109     // Check the index against the length of the string list, then skip the length.
110     if (index < 1 || index > *(SInt16 *)p) {
111         return nil;
112     }
113     p += sizeof(SInt16);
114     
115     // Skip any strings that come before the one we are looking for.
116     while (--index)
117         p += 1 + *p;
118     
119     // Convert the one we found into an NSString.
120     return [[[NSString alloc] initWithBytes:(p + 1) length:*p encoding:[NSString _web_encodingForResource:stringHandle]] autorelease];
121 }
122
123 - (BOOL)getPluginInfoFromResources
124 {
125     SInt16 resRef = [self openResourceFile];
126     if (resRef == -1) {
127         return NO;
128     }
129     
130     UseResFile(resRef);
131     if (ResError() != noErr) {
132         return NO;
133     }
134
135     NSString *MIME, *extensionsList, *description;
136     NSArray *extensions;
137     NSRange r;
138     uint i;
139     
140     NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary];
141     NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary];
142
143     for (i=1; 1; i+=2) {
144         MIME = [[self stringForStringListID:MIMEListStringStringNumber
145                                    andIndex:i] lowercaseString];
146         if (!MIME) {
147             break;
148         }
149
150         // FIXME: Avoid mime types with semi-colons because KJS can't properly parse them using KWQKConfigBase
151         r = [MIME rangeOfString:@";"];
152         if (r.length > 0) {
153             continue;
154         }
155
156         extensionsList = [[self stringForStringListID:MIMEListStringStringNumber
157                                              andIndex:i+1] lowercaseString];
158         if (extensionsList) {
159             extensions = [extensionsList componentsSeparatedByString:@","];
160             [MIMEToExtensionsDictionary setObject:extensions forKey:MIME];
161         } else {
162             // DRM and WMP claim MIMEs without extensions. Use a @"" extension in this case.
163             [MIMEToExtensionsDictionary setObject:[NSArray arrayWithObject:@""] forKey:MIME];
164         }
165         
166         description = [self stringForStringListID:MIMEDescriptionStringNumber
167                                          andIndex:[MIMEToExtensionsDictionary count]];
168         if (description) {
169             [MIMEToDescriptionDictionary setObject:description forKey:MIME];
170         } else {
171             [MIMEToDescriptionDictionary setObject:@"" forKey:MIME];
172         }
173     }
174
175     [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary];
176     [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary];
177
178     NSString *filename = [self filename];
179     
180     description = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:1];
181     if (!description) {
182         description = filename;
183     }
184     [self setPluginDescription:description];
185     
186     
187     NSString *theName = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:2];
188     if (!theName) {
189         theName = filename;
190     }
191     [self setName:theName];
192     
193     [self closeResourceFile:resRef];
194     
195     return YES;
196 }
197
198 - initWithPath:(NSString *)pluginPath
199 {
200     [super initWithPath:pluginPath];
201
202     resourceRef = -1;
203     
204     OSType type = 0;
205
206     // Bundle
207     if (bundle) {
208         isBundle = YES;
209         CFBundleGetPackageInfo(cfBundle, &type, NULL);
210     }
211     // Single-file plug-in with resource fork
212     else {
213 #ifdef __ppc__
214         type = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileHFSTypeCode];
215         isBundle = NO;
216         isCFM = YES;
217 #else
218         [self release];
219         return nil;
220 #endif
221     }
222     
223     if (type != FOUR_CHAR_CODE('BRPL')) {
224         [self release];
225         return nil;
226     }
227
228     // Check if the executable is Mach-O or CFM.
229     if (bundle) {
230         NSFileHandle *executableFile = [NSFileHandle fileHandleForReadingAtPath:[bundle executablePath]];
231         NSData *data = [executableFile readDataOfLength:512];
232         [executableFile closeFile];
233         // Check the length of the data before calling memcmp. We think this fixes 3782543.
234         if (data == nil || [data length] < 8) {
235             [self release];
236             return nil;
237         }
238         isCFM = memcmp([data bytes], "Joy!peff", 8) == 0;
239 #ifndef __ppc__
240         // CFM is PPC-only.
241         if (isCFM) {
242             [self release];
243             return nil;
244         }
245 #endif
246         if (![self isNativeLibraryData:data]) {
247             [self release];
248             return nil;
249         }
250     }
251
252     if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources]) {
253         [self release];
254         return nil;
255     }
256
257     return self;
258 }
259
260 - (WebExecutableType)executableType
261 {
262     if (isCFM) {
263         return WebCFMExecutableType;
264     } else {
265         return WebMachOExecutableType;
266     }
267 }
268
269 - (BOOL)isLoaded
270 {
271     return isLoaded;
272 }
273
274 - (void)unloadWithoutShutdown
275 {
276     if (!isLoaded) {
277         return;
278     }
279
280     if (resourceRef != -1) {
281         [self closeResourceFile:resourceRef];
282     }
283
284     if (isBundle) {
285         CFBundleUnloadExecutable(cfBundle);
286     } else {
287 #if !__LP64__
288         // CFM is not supported in 64-bit
289         WebCloseConnection(&connID);
290 #endif
291     }
292
293     LOG(Plugins, "Plugin Unloaded");
294     isLoaded = NO;
295 }
296
297
298 - (void)launchRealPlayer
299 {
300     CFURLRef appURL = NULL;
301     OSStatus error = LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)RealPlayerAppIndentifier, NULL, NULL, &appURL);
302     if (!error) {
303         LSLaunchURLSpec URLSpec;
304         bzero(&URLSpec, sizeof(URLSpec));
305         URLSpec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch;
306         URLSpec.appURL = appURL;
307         LSOpenFromURLSpec(&URLSpec, NULL);
308         CFRelease(appURL);
309     }
310 }
311
312 - (BOOL)load
313 {    
314     NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL;
315     NP_InitializeFuncPtr NP_Initialize = NULL;
316     MainFuncPtr pluginMainFunc;
317     NPError npErr;
318
319 #if !LOG_DISABLED
320     CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
321 #endif
322     LOG(Plugins, "%f Load timing started for: %@", start, [self name]);
323
324     if (isLoaded) {
325         return YES;
326     }
327     
328     if (isBundle) {
329         if (!CFBundleLoadExecutable(cfBundle)) {
330             goto abort;
331         }
332 #if !LOG_DISABLED
333         CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
334         CFAbsoluteTime duration = currentTime - start;
335 #endif
336         LOG(Plugins, "%f CFBundleLoadExecutable took %f seconds", currentTime, duration);
337         isLoaded = YES;
338         
339         if (isCFM) {
340             pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") );
341             if (!pluginMainFunc) {
342                 goto abort;
343             }
344         } else {
345             NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize"));
346             NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints"));
347             NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
348             if (!NP_Initialize || !NP_GetEntryPoints || !NPP_Shutdown) {
349                 goto abort;
350             }
351         }
352     } else {
353 #if __LP64__
354         // CFM is not supported in 64-bit
355         goto abort;
356 #else
357         // single CFM file
358         FSSpec spec;
359         FSRef fref;
360         OSErr err;
361         
362         err = FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], &fref, NULL);
363         if (err != noErr) {
364             LOG_ERROR("FSPathMakeRef failed. Error=%d", err);
365             goto abort;
366         }
367         err = FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
368         if (err != noErr) {
369             LOG_ERROR("FSGetCatalogInfo failed. Error=%d", err);
370             goto abort;
371         }
372         err = WebGetDiskFragment(&spec, 0, kCFragGoesToEOF, nil, kPrivateCFragCopy, &connID, (Ptr *)&pluginMainFunc, nil);
373         if (err != noErr) {
374             LOG_ERROR("WebGetDiskFragment failed. Error=%d", err);
375             goto abort;
376         }
377 #if !LOG_DISABLED
378         CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
379         CFAbsoluteTime duration = currentTime - start;
380 #endif
381         LOG(Plugins, "%f WebGetDiskFragment took %f seconds", currentTime, duration);
382         isLoaded = YES;
383         
384         pluginMainFunc = (MainFuncPtr)functionPointerForTVector((TransitionVector)pluginMainFunc);
385         if (!pluginMainFunc) {
386             goto abort;
387         }
388
389         // NOTE: pluginMainFunc is freed after it is called. Be sure not to return before that.
390         
391         isCFM = TRUE;
392 #endif /* __LP64__ */
393     }
394     
395     // Plugins (at least QT) require that you call UseResFile on the resource file before loading it.
396     resourceRef = [self openResourceFile];
397     if (resourceRef != -1) {
398         UseResFile(resourceRef);
399     }
400     
401     // swap function tables
402     if (isCFM) {
403         browserFuncs.version = NP_VERSION_MINOR;
404         browserFuncs.size = sizeof(NPNetscapeFuncs);
405         browserFuncs.geturl = (NPN_GetURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURL);
406         browserFuncs.posturl = (NPN_PostURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURL);
407         browserFuncs.requestread = (NPN_RequestReadProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_RequestRead);
408         browserFuncs.newstream = (NPN_NewStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_NewStream);
409         browserFuncs.write = (NPN_WriteProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Write);
410         browserFuncs.destroystream = (NPN_DestroyStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_DestroyStream);
411         browserFuncs.status = (NPN_StatusProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Status);
412         browserFuncs.uagent = (NPN_UserAgentProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_UserAgent);
413         browserFuncs.memalloc = (NPN_MemAllocProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemAlloc);
414         browserFuncs.memfree = (NPN_MemFreeProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFree);
415         browserFuncs.memflush = (NPN_MemFlushProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFlush);
416         browserFuncs.reloadplugins = (NPN_ReloadPluginsProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ReloadPlugins);
417         browserFuncs.geturlnotify = (NPN_GetURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURLNotify);
418         browserFuncs.posturlnotify = (NPN_PostURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURLNotify);
419         browserFuncs.getvalue = (NPN_GetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetValue);
420         browserFuncs.setvalue = (NPN_SetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_SetValue);
421         browserFuncs.invalidaterect = (NPN_InvalidateRectProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRect);
422         browserFuncs.invalidateregion = (NPN_InvalidateRegionProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRegion);
423         browserFuncs.forceredraw = (NPN_ForceRedrawProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ForceRedraw);
424         browserFuncs.getJavaEnv = (NPN_GetJavaEnvProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaEnv);
425         browserFuncs.getJavaPeer = (NPN_GetJavaPeerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaPeer);
426
427         browserFuncs.releasevariantvalue = (NPN_ReleaseVariantValueProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseVariantValue);
428         browserFuncs.getstringidentifier = (NPN_GetStringIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifier);
429         browserFuncs.getstringidentifiers = (NPN_GetStringIdentifiersProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifiers);
430         browserFuncs.getintidentifier = (NPN_GetIntIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetIntIdentifier);
431         browserFuncs.identifierisstring = (NPN_IdentifierIsStringProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_IdentifierIsString);
432         browserFuncs.utf8fromidentifier = (NPN_UTF8FromIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_UTF8FromIdentifier);
433         browserFuncs.createobject = (NPN_CreateObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_CreateObject);
434         browserFuncs.retainobject = (NPN_RetainObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RetainObject);
435         browserFuncs.releaseobject = (NPN_ReleaseObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseObject);
436         browserFuncs.invoke = (NPN_InvokeProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Invoke);
437         browserFuncs.invokeDefault = (NPN_InvokeDefaultProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_InvokeDefault);
438         browserFuncs.evaluate = (NPN_EvaluateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Evaluate);
439         browserFuncs.getproperty = (NPN_GetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetProperty);
440         browserFuncs.setproperty = (NPN_SetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetProperty);
441         browserFuncs.removeproperty = (NPN_RemovePropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RemoveProperty);
442         browserFuncs.setexception = (NPN_SetExceptionProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetException);
443
444 #if !LOG_DISABLED
445         CFAbsoluteTime mainStart = CFAbsoluteTimeGetCurrent();
446 #endif
447         LOG(Plugins, "%f main timing started", mainStart);
448         NPP_ShutdownProcPtr shutdownFunction;
449         npErr = pluginMainFunc(&browserFuncs, &pluginFuncs, &shutdownFunction);
450         NPP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction);
451         if (!isBundle) {
452             // Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case.
453             free(pluginMainFunc);
454         }
455         
456         // Workaround for 3270576. The RealPlayer plug-in fails to load if its preference file is out of date.
457         // Launch the RealPlayer application to refresh the file.
458         if (npErr != NPERR_NO_ERROR) {
459             if (npErr == NPERR_MODULE_LOAD_FAILED_ERROR && [[self filename] isEqualToString:RealPlayerPluginFilename]) {
460                 [self launchRealPlayer];
461             }
462             goto abort;
463         }
464 #if !LOG_DISABLED
465         CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
466         CFAbsoluteTime duration = currentTime - mainStart;
467 #endif
468         LOG(Plugins, "%f main took %f seconds", currentTime, duration);
469         
470         pluginSize = pluginFuncs.size;
471         pluginVersion = pluginFuncs.version;
472         LOG(Plugins, "pluginMainFunc: %d, size=%d, version=%d", npErr, pluginSize, pluginVersion);
473         
474         NPP_New = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp);
475         NPP_Destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy);
476         NPP_SetWindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow);
477         NPP_NewStream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream);
478         NPP_DestroyStream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream);
479         NPP_StreamAsFile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile);
480         NPP_WriteReady = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready);
481         NPP_Write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write);
482         NPP_Print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print);
483         NPP_HandleEvent = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event);
484         NPP_URLNotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify);
485         NPP_GetValue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue);
486         NPP_SetValue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue);
487
488         // LiveConnect support
489         NPP_GetJavaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass);
490         if (NPP_GetJavaClass){
491             LOG(LiveConnect, "%@:  CFM entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
492         } else {
493             LOG(LiveConnect, "%@:  no entry point for NPP_GetJavaClass", [self name]);
494         }
495
496     } else {
497         // no function pointer conversion necessary for mach-o
498         browserFuncs.version = NP_VERSION_MINOR;
499         browserFuncs.size = sizeof(NPNetscapeFuncs);
500         browserFuncs.geturl = NPN_GetURL;
501         browserFuncs.posturl = NPN_PostURL;
502         browserFuncs.requestread = NPN_RequestRead;
503         browserFuncs.newstream = NPN_NewStream;
504         browserFuncs.write = NPN_Write;
505         browserFuncs.destroystream = NPN_DestroyStream;
506         browserFuncs.status = NPN_Status;
507         browserFuncs.uagent = NPN_UserAgent;
508         browserFuncs.memalloc = NPN_MemAlloc;
509         browserFuncs.memfree = NPN_MemFree;
510         browserFuncs.memflush = NPN_MemFlush;
511         browserFuncs.reloadplugins = NPN_ReloadPlugins;
512         browserFuncs.geturlnotify = NPN_GetURLNotify;
513         browserFuncs.posturlnotify = NPN_PostURLNotify;
514         browserFuncs.getvalue = NPN_GetValue;
515         browserFuncs.setvalue = NPN_SetValue;
516         browserFuncs.invalidaterect = NPN_InvalidateRect;
517         browserFuncs.invalidateregion = NPN_InvalidateRegion;
518         browserFuncs.forceredraw = NPN_ForceRedraw;
519         browserFuncs.getJavaEnv = NPN_GetJavaEnv;
520         browserFuncs.getJavaPeer = NPN_GetJavaPeer;
521
522         browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue;
523         browserFuncs.getstringidentifier = _NPN_GetStringIdentifier;
524         browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers;
525         browserFuncs.getintidentifier = _NPN_GetIntIdentifier;
526         browserFuncs.identifierisstring = _NPN_IdentifierIsString;
527         browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier;
528         browserFuncs.createobject = _NPN_CreateObject;
529         browserFuncs.retainobject = _NPN_RetainObject;
530         browserFuncs.releaseobject = _NPN_ReleaseObject;
531         browserFuncs.invoke = _NPN_Invoke;
532         browserFuncs.invokeDefault = _NPN_InvokeDefault;
533         browserFuncs.evaluate = _NPN_Evaluate;
534         browserFuncs.getproperty = _NPN_GetProperty;
535         browserFuncs.setproperty = _NPN_SetProperty;
536         browserFuncs.removeproperty = _NPN_RemoveProperty;
537         browserFuncs.setexception = _NPN_SetException;
538
539 #if !LOG_DISABLED
540         CFAbsoluteTime initializeStart = CFAbsoluteTimeGetCurrent();
541 #endif
542         LOG(Plugins, "%f NP_Initialize timing started", initializeStart);
543         npErr = NP_Initialize(&browserFuncs);
544         if (npErr != NPERR_NO_ERROR) {
545             goto abort;
546         }
547 #if !LOG_DISABLED
548         CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
549         CFAbsoluteTime duration = currentTime - initializeStart;
550 #endif
551         LOG(Plugins, "%f NP_Initialize took %f seconds", currentTime, duration);
552
553         npErr = NP_GetEntryPoints(&pluginFuncs);
554         if (npErr != NPERR_NO_ERROR) {
555             goto abort;
556         }
557         
558         pluginSize = pluginFuncs.size;
559         pluginVersion = pluginFuncs.version;
560         
561         NPP_New = pluginFuncs.newp;
562         NPP_Destroy = pluginFuncs.destroy;
563         NPP_SetWindow = pluginFuncs.setwindow;
564         NPP_NewStream = pluginFuncs.newstream;
565         NPP_DestroyStream = pluginFuncs.destroystream;
566         NPP_StreamAsFile = pluginFuncs.asfile;
567         NPP_WriteReady = pluginFuncs.writeready;
568         NPP_Write = pluginFuncs.write;
569         NPP_Print = pluginFuncs.print;
570         NPP_HandleEvent = pluginFuncs.event;
571         NPP_URLNotify = pluginFuncs.urlnotify;
572         NPP_GetValue = pluginFuncs.getvalue;
573         NPP_SetValue = pluginFuncs.setvalue;
574
575         // LiveConnect support
576         NPP_GetJavaClass = pluginFuncs.javaClass;
577         if (NPP_GetJavaClass){
578             LOG(LiveConnect, "%@:  mach-o entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
579         } else {
580             LOG(LiveConnect, "%@:  no entry point for NPP_GetJavaClass", [self name]);
581         }
582     }
583
584 #if !LOG_DISABLED
585     CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
586     CFAbsoluteTime duration = currentTime - start;
587 #endif
588     LOG(Plugins, "%f Total load time: %f seconds", currentTime, duration);
589
590     return [super load];
591
592 abort:
593     [self unloadWithoutShutdown];
594     return NO;
595 }
596     
597 - (void)unload
598 {
599     if (!isLoaded) {
600         return;
601     }
602     
603     LOG(Plugins, "Unloading %@...", name);
604
605     NPP_Shutdown();
606
607     [self unloadWithoutShutdown];
608 }
609
610 - (NPP_SetWindowProcPtr)NPP_SetWindow
611 {
612     return NPP_SetWindow;
613 }
614
615 - (NPP_NewProcPtr)NPP_New
616 {
617     return NPP_New;
618 }
619
620 - (NPP_DestroyProcPtr)NPP_Destroy
621 {
622     return NPP_Destroy;
623 }
624
625 - (NPP_NewStreamProcPtr)NPP_NewStream
626 {
627     return NPP_NewStream;
628 }
629
630 - (NPP_StreamAsFileProcPtr)NPP_StreamAsFile
631 {
632     return NPP_StreamAsFile;
633 }
634 - (NPP_DestroyStreamProcPtr)NPP_DestroyStream
635 {
636     return NPP_DestroyStream;
637 }
638
639 - (NPP_WriteReadyProcPtr)NPP_WriteReady
640 {
641     return NPP_WriteReady;
642 }
643 - (NPP_WriteProcPtr)NPP_Write
644 {
645     return NPP_Write;
646 }
647
648 - (NPP_HandleEventProcPtr)NPP_HandleEvent
649 {
650     return NPP_HandleEvent;
651 }
652
653 -(NPP_URLNotifyProcPtr)NPP_URLNotify
654 {
655     return NPP_URLNotify;
656 }
657
658 -(NPP_GetValueProcPtr)NPP_GetValue
659 {
660     return NPP_GetValue;
661 }
662
663 -(NPP_SetValueProcPtr)NPP_SetValue
664 {
665     return NPP_SetValue;
666 }
667
668 -(NPP_PrintProcPtr)NPP_Print
669 {
670     return NPP_Print;
671 }
672
673 @end
674
675
676 // function pointer converters
677
678 FunctionPointer functionPointerForTVector(TransitionVector tvp)
679 {
680     const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420};
681     uint32 *newGlue = NULL;
682
683     if (tvp != NULL) {
684         newGlue = (uint32 *)malloc(sizeof(temp));
685         if (newGlue != NULL) {
686             unsigned i;
687             for (i = 0; i < 6; i++) newGlue[i] = temp[i];
688             newGlue[0] |= ((UInt32)tvp >> 16);
689             newGlue[1] |= ((UInt32)tvp & 0xFFFF);
690             MakeDataExecutable(newGlue, sizeof(temp));
691         }
692     }
693     
694     return (FunctionPointer)newGlue;
695 }
696
697 TransitionVector tVectorForFunctionPointer(FunctionPointer fp)
698 {
699     FunctionPointer *newGlue = NULL;
700     if (fp != NULL) {
701         newGlue = (FunctionPointer *)malloc(2 * sizeof(FunctionPointer));
702         if (newGlue != NULL) {
703             newGlue[0] = fp;
704             newGlue[1] = NULL;
705         }
706     }
707     return (TransitionVector)newGlue;
708 }