2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #if ENABLE(NETSCAPE_PLUGIN_API)
30 #import "WebNetscapePluginPackage.h"
32 #import "WebKitLogging.h"
33 #import "WebKitNSStringExtras.h"
34 #import "WebNSObjectExtras.h"
35 #import "WebNetscapeDeprecatedFunctions.h"
36 #import <WebCore/npruntime_impl.h>
39 typedef void (* FunctionPointer)(void);
40 typedef void (* TransitionVector)(void);
41 static FunctionPointer functionPointerForTVector(TransitionVector);
42 static TransitionVector tVectorForFunctionPointer(FunctionPointer);
45 #define PluginNameOrDescriptionStringNumber 126
46 #define MIMEDescriptionStringNumber 127
47 #define MIMEListStringStringNumber 128
49 #define RealPlayerAppIndentifier @"com.RealNetworks.RealOne Player"
50 #define RealPlayerPluginFilename @"RealPlayer Plugin"
52 @interface WebNetscapePluginPackage (Internal)
53 - (void)_unloadWithShutdown:(BOOL)shutdown;
56 @implementation WebNetscapePluginPackage
61 // The Shockwave plugin requires a valid file in CurApRefNum.
62 // But it doesn't seem to matter what file it is.
63 // If we're called inside a Cocoa application which won't have a
64 // CurApRefNum, we set it to point to the system resource file.
66 // Call CurResFile before testing the result of WebLMGetCurApRefNum.
67 // If we are called before the bundle resource map has been opened
68 // for a Carbon application (or a Cocoa app with Resource Manager
69 // resources) we *do not* want to set CurApRefNum to point at the
70 // system resource file. CurResFile triggers Resource Manager lazy
71 // initialization, and will open the bundle resource map as necessary.
75 if (WebLMGetCurApRefNum() == -1) {
76 // To get the refNum for the system resource file, we have to do
77 // UseResFile(kSystemResFile) and then look at CurResFile().
78 short savedCurResFile = CurResFile();
79 UseResFile(kSystemResFile);
80 WebLMSetCurApRefNum(CurResFile());
81 UseResFile(savedCurResFile);
86 - (ResFileRefNum)openResourceFile
91 OSErr err = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &fref, NULL);
95 return FSOpenResFile(&fref, fsRdPerm);
99 return CFBundleOpenBundleResourceMap(cfBundle);
102 - (void)closeResourceFile:(ResFileRefNum)resRef
106 CloseResFile(resRef);
111 CFBundleCloseBundleResourceMap(cfBundle, resRef);
114 - (NSString *)stringForStringListID:(SInt16)stringListID andIndex:(SInt16)index
116 // Get resource, and dereference the handle.
117 Handle stringHandle = Get1Resource('STR#', stringListID);
118 if (stringHandle == NULL) {
121 unsigned char *p = (unsigned char *)*stringHandle;
125 // Check the index against the length of the string list, then skip the length.
126 if (index < 1 || index > *(SInt16 *)p)
130 // Skip any strings that come before the one we are looking for.
134 // Convert the one we found into an NSString.
135 return [[[NSString alloc] initWithBytes:(p + 1) length:*p encoding:[NSString _web_encodingForResource:stringHandle]] autorelease];
138 - (BOOL)getPluginInfoFromResources
140 SInt16 resRef = [self openResourceFile];
145 if (ResError() != noErr)
148 NSString *MIME, *extensionsList, *description;
152 NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary];
153 NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary];
156 MIME = [[self stringForStringListID:MIMEListStringStringNumber
157 andIndex:i] lowercaseString];
161 extensionsList = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i+1] lowercaseString];
162 if (extensionsList) {
163 extensions = [extensionsList componentsSeparatedByString:@","];
164 [MIMEToExtensionsDictionary setObject:extensions forKey:MIME];
166 // DRM and WMP claim MIMEs without extensions. Use a @"" extension in this case.
167 [MIMEToExtensionsDictionary setObject:[NSArray arrayWithObject:@""] forKey:MIME];
169 description = [self stringForStringListID:MIMEDescriptionStringNumber
170 andIndex:[MIMEToExtensionsDictionary count]];
172 [MIMEToDescriptionDictionary setObject:description forKey:MIME];
174 [MIMEToDescriptionDictionary setObject:@"" forKey:MIME];
177 [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary];
178 [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary];
180 NSString *filename = [self filename];
182 description = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:1];
184 description = filename;
185 [self setPluginDescription:description];
188 NSString *theName = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:2];
191 [self setName:theName];
193 [self closeResourceFile:resRef];
198 - (BOOL)_initWithPath:(NSString *)pluginPath
206 CFBundleGetPackageInfo(cfBundle, &type, NULL);
212 // Single-file plug-in with resource fork
213 type = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileHFSTypeCode];
221 if (type != FOUR_CHAR_CODE('BRPL'))
224 // Check if the executable is Mach-O or CFM.
226 NSFileHandle *executableFile = [NSFileHandle fileHandleForReadingAtPath:[bundle executablePath]];
227 NSData *data = [executableFile readDataOfLength:512];
228 [executableFile closeFile];
229 // Check the length of the data before calling memcmp. We think this fixes 3782543.
230 if (data == nil || [data length] < 8)
232 BOOL hasCFMHeader = memcmp([data bytes], "Joy!peff", 8) == 0;
234 isCFM = hasCFMHeader;
240 if (![self isNativeLibraryData:data])
244 if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources])
250 - (id)initWithPath:(NSString *)pluginPath
252 if (!(self = [super initWithPath:pluginPath]))
255 // Initializing a plugin package can cause it to be loaded. If there was an error initializing the plugin package,
256 // ensure that it is unloaded before deallocating it (WebBasePluginPackage requires & asserts this).
257 if (![self _initWithPath:pluginPath]) {
258 [self _unloadWithShutdown:YES];
266 - (WebExecutableType)executableType
270 return WebCFMExecutableType;
272 return WebMachOExecutableType;
275 - (void)launchRealPlayer
277 CFURLRef appURL = NULL;
278 OSStatus error = LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)RealPlayerAppIndentifier, NULL, NULL, &appURL);
280 LSLaunchURLSpec URLSpec;
281 bzero(&URLSpec, sizeof(URLSpec));
282 URLSpec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch;
283 URLSpec.appURL = appURL;
284 LSOpenFromURLSpec(&URLSpec, NULL);
289 - (void)_applyDjVuWorkaround
294 if ([(NSString *)CFBundleGetIdentifier(cfBundle) isEqualToString:@"com.lizardtech.NPDjVu"]) {
295 // The DjVu plug-in will crash copying the vtable if it's too big so we cap it to
296 // what the plug-in expects here.
297 // size + version + 40 function pointers.
298 browserFuncs.size = 2 + 2 + sizeof(void *) * 40;
305 [self _unloadWithShutdown:YES];
310 NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL;
311 NP_InitializeFuncPtr NP_Initialize = NULL;
315 MainFuncPtr pluginMainFunc = NULL;
319 CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
320 CFAbsoluteTime currentTime;
321 CFAbsoluteTime duration;
323 LOG(Plugins, "%f Load timing started for: %@", start, [self name]);
331 if (!CFBundleLoadExecutable(cfBundle))
334 currentTime = CFAbsoluteTimeGetCurrent();
335 duration = currentTime - start;
337 LOG(Plugins, "%f CFBundleLoadExecutable took %f seconds", currentTime, duration);
342 pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") );
347 NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize"));
348 NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints"));
349 NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
350 if (!NP_Initialize || !NP_GetEntryPoints || !NPP_Shutdown)
360 err = FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], &fref, NULL);
362 LOG_ERROR("FSPathMakeRef failed. Error=%d", err);
365 err = FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
367 LOG_ERROR("FSGetCatalogInfo failed. Error=%d", err);
370 err = WebGetDiskFragment(&spec, 0, kCFragGoesToEOF, nil, kPrivateCFragCopy, &connID, (Ptr *)&pluginMainFunc, nil);
372 LOG_ERROR("WebGetDiskFragment failed. Error=%d", err);
376 currentTime = CFAbsoluteTimeGetCurrent();
377 duration = currentTime - start;
379 LOG(Plugins, "%f WebGetDiskFragment took %f seconds", currentTime, duration);
382 pluginMainFunc = (MainFuncPtr)functionPointerForTVector((TransitionVector)pluginMainFunc);
383 if (!pluginMainFunc) {
387 // NOTE: pluginMainFunc is freed after it is called. Be sure not to return before that.
391 #endif /* SUPPORT_CFM */
393 // Plugins (at least QT) require that you call UseResFile on the resource file before loading it.
394 resourceRef = [self openResourceFile];
395 if (resourceRef != -1) {
396 UseResFile(resourceRef);
399 // swap function tables
402 browserFuncs.version = NP_VERSION_MINOR;
403 browserFuncs.size = sizeof(NPNetscapeFuncs);
404 browserFuncs.geturl = (NPN_GetURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURL);
405 browserFuncs.posturl = (NPN_PostURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURL);
406 browserFuncs.requestread = (NPN_RequestReadProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_RequestRead);
407 browserFuncs.newstream = (NPN_NewStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_NewStream);
408 browserFuncs.write = (NPN_WriteProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Write);
409 browserFuncs.destroystream = (NPN_DestroyStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_DestroyStream);
410 browserFuncs.status = (NPN_StatusProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Status);
411 browserFuncs.uagent = (NPN_UserAgentProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_UserAgent);
412 browserFuncs.memalloc = (NPN_MemAllocProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemAlloc);
413 browserFuncs.memfree = (NPN_MemFreeProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFree);
414 browserFuncs.memflush = (NPN_MemFlushProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFlush);
415 browserFuncs.reloadplugins = (NPN_ReloadPluginsProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ReloadPlugins);
416 browserFuncs.geturlnotify = (NPN_GetURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURLNotify);
417 browserFuncs.posturlnotify = (NPN_PostURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURLNotify);
418 browserFuncs.getvalue = (NPN_GetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetValue);
419 browserFuncs.setvalue = (NPN_SetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_SetValue);
420 browserFuncs.invalidaterect = (NPN_InvalidateRectProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRect);
421 browserFuncs.invalidateregion = (NPN_InvalidateRegionProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRegion);
422 browserFuncs.forceredraw = (NPN_ForceRedrawProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ForceRedraw);
423 browserFuncs.getJavaEnv = (NPN_GetJavaEnvProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaEnv);
424 browserFuncs.getJavaPeer = (NPN_GetJavaPeerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaPeer);
425 browserFuncs.pushpopupsenabledstate = (NPN_PushPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PushPopupsEnabledState);
426 browserFuncs.poppopupsenabledstate = (NPN_PopPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PopPopupsEnabledState);
427 browserFuncs.scheduletimer = (NPN_ScheduleTimerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ScheduleTimer);
428 browserFuncs.unscheduletimer = (NPN_UnscheduleTimerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_UnscheduleTimer);
430 browserFuncs.releasevariantvalue = (NPN_ReleaseVariantValueProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseVariantValue);
431 browserFuncs.getstringidentifier = (NPN_GetStringIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifier);
432 browserFuncs.getstringidentifiers = (NPN_GetStringIdentifiersProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifiers);
433 browserFuncs.getintidentifier = (NPN_GetIntIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetIntIdentifier);
434 browserFuncs.identifierisstring = (NPN_IdentifierIsStringProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_IdentifierIsString);
435 browserFuncs.utf8fromidentifier = (NPN_UTF8FromIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_UTF8FromIdentifier);
436 browserFuncs.intfromidentifier = (NPN_IntFromIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_IntFromIdentifier);
437 browserFuncs.createobject = (NPN_CreateObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_CreateObject);
438 browserFuncs.retainobject = (NPN_RetainObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RetainObject);
439 browserFuncs.releaseobject = (NPN_ReleaseObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseObject);
440 browserFuncs.invoke = (NPN_InvokeProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Invoke);
441 browserFuncs.invokeDefault = (NPN_InvokeDefaultProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_InvokeDefault);
442 browserFuncs.evaluate = (NPN_EvaluateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Evaluate);
443 browserFuncs.getproperty = (NPN_GetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetProperty);
444 browserFuncs.setproperty = (NPN_SetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetProperty);
445 browserFuncs.removeproperty = (NPN_RemovePropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RemoveProperty);
446 browserFuncs.setexception = (NPN_SetExceptionProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetException);
447 browserFuncs.enumerate = (NPN_EnumerateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Enumerate);
449 [self _applyDjVuWorkaround];
452 CFAbsoluteTime mainStart = CFAbsoluteTimeGetCurrent();
454 LOG(Plugins, "%f main timing started", mainStart);
455 NPP_ShutdownProcPtr shutdownFunction;
456 npErr = pluginMainFunc(&browserFuncs, &pluginFuncs, &shutdownFunction);
457 NPP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction);
459 // Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case.
460 free(pluginMainFunc);
462 // Workaround for 3270576. The RealPlayer plug-in fails to load if its preference file is out of date.
463 // Launch the RealPlayer application to refresh the file.
464 if (npErr != NPERR_NO_ERROR) {
465 if (npErr == NPERR_MODULE_LOAD_FAILED_ERROR && [[self filename] isEqualToString:RealPlayerPluginFilename])
466 [self launchRealPlayer];
470 currentTime = CFAbsoluteTimeGetCurrent();
471 duration = currentTime - mainStart;
473 LOG(Plugins, "%f main took %f seconds", currentTime, duration);
475 pluginSize = pluginFuncs.size;
476 pluginVersion = pluginFuncs.version;
477 LOG(Plugins, "pluginMainFunc: %d, size=%d, version=%d", npErr, pluginSize, pluginVersion);
479 NPP_New = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp);
480 NPP_Destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy);
481 NPP_SetWindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow);
482 NPP_NewStream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream);
483 NPP_DestroyStream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream);
484 NPP_StreamAsFile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile);
485 NPP_WriteReady = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready);
486 NPP_Write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write);
487 NPP_Print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print);
488 NPP_HandleEvent = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event);
489 NPP_URLNotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify);
490 NPP_GetValue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue);
491 NPP_SetValue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue);
493 // LiveConnect support
494 NPP_GetJavaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass);
495 if (NPP_GetJavaClass) {
496 LOG(LiveConnect, "%@: CFM entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
498 LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]);
505 // no function pointer conversion necessary for Mach-O
506 browserFuncs.version = NP_VERSION_MINOR;
507 browserFuncs.size = sizeof(NPNetscapeFuncs);
508 browserFuncs.geturl = NPN_GetURL;
509 browserFuncs.posturl = NPN_PostURL;
510 browserFuncs.requestread = NPN_RequestRead;
511 browserFuncs.newstream = NPN_NewStream;
512 browserFuncs.write = NPN_Write;
513 browserFuncs.destroystream = NPN_DestroyStream;
514 browserFuncs.status = NPN_Status;
515 browserFuncs.uagent = NPN_UserAgent;
516 browserFuncs.memalloc = NPN_MemAlloc;
517 browserFuncs.memfree = NPN_MemFree;
518 browserFuncs.memflush = NPN_MemFlush;
519 browserFuncs.reloadplugins = NPN_ReloadPlugins;
520 browserFuncs.geturlnotify = NPN_GetURLNotify;
521 browserFuncs.posturlnotify = NPN_PostURLNotify;
522 browserFuncs.getvalue = NPN_GetValue;
523 browserFuncs.setvalue = NPN_SetValue;
524 browserFuncs.invalidaterect = NPN_InvalidateRect;
525 browserFuncs.invalidateregion = NPN_InvalidateRegion;
526 browserFuncs.forceredraw = NPN_ForceRedraw;
527 browserFuncs.getJavaEnv = NPN_GetJavaEnv;
528 browserFuncs.getJavaPeer = NPN_GetJavaPeer;
529 browserFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
530 browserFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
531 browserFuncs.scheduletimer = NPN_ScheduleTimer;
532 browserFuncs.unscheduletimer = NPN_UnscheduleTimer;
534 browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue;
535 browserFuncs.getstringidentifier = _NPN_GetStringIdentifier;
536 browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers;
537 browserFuncs.getintidentifier = _NPN_GetIntIdentifier;
538 browserFuncs.identifierisstring = _NPN_IdentifierIsString;
539 browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier;
540 browserFuncs.intfromidentifier = _NPN_IntFromIdentifier;
541 browserFuncs.createobject = _NPN_CreateObject;
542 browserFuncs.retainobject = _NPN_RetainObject;
543 browserFuncs.releaseobject = _NPN_ReleaseObject;
544 browserFuncs.invoke = _NPN_Invoke;
545 browserFuncs.invokeDefault = _NPN_InvokeDefault;
546 browserFuncs.evaluate = _NPN_Evaluate;
547 browserFuncs.getproperty = _NPN_GetProperty;
548 browserFuncs.setproperty = _NPN_SetProperty;
549 browserFuncs.removeproperty = _NPN_RemoveProperty;
550 browserFuncs.setexception = _NPN_SetException;
551 browserFuncs.enumerate = _NPN_Enumerate;
553 [self _applyDjVuWorkaround];
556 CFAbsoluteTime initializeStart = CFAbsoluteTimeGetCurrent();
558 LOG(Plugins, "%f NP_Initialize timing started", initializeStart);
559 npErr = NP_Initialize(&browserFuncs);
560 if (npErr != NPERR_NO_ERROR)
563 currentTime = CFAbsoluteTimeGetCurrent();
564 duration = currentTime - initializeStart;
566 LOG(Plugins, "%f NP_Initialize took %f seconds", currentTime, duration);
568 npErr = NP_GetEntryPoints(&pluginFuncs);
569 if (npErr != NPERR_NO_ERROR)
572 pluginSize = pluginFuncs.size;
573 pluginVersion = pluginFuncs.version;
575 NPP_New = pluginFuncs.newp;
576 NPP_Destroy = pluginFuncs.destroy;
577 NPP_SetWindow = pluginFuncs.setwindow;
578 NPP_NewStream = pluginFuncs.newstream;
579 NPP_DestroyStream = pluginFuncs.destroystream;
580 NPP_StreamAsFile = pluginFuncs.asfile;
581 NPP_WriteReady = pluginFuncs.writeready;
582 NPP_Write = pluginFuncs.write;
583 NPP_Print = pluginFuncs.print;
584 NPP_HandleEvent = pluginFuncs.event;
585 NPP_URLNotify = pluginFuncs.urlnotify;
586 NPP_GetValue = pluginFuncs.getvalue;
587 NPP_SetValue = pluginFuncs.setvalue;
589 // LiveConnect support
590 NPP_GetJavaClass = pluginFuncs.javaClass;
591 if (NPP_GetJavaClass){
592 LOG(LiveConnect, "%@: mach-o entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
594 LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]);
602 currentTime = CFAbsoluteTimeGetCurrent();
603 duration = currentTime - start;
605 LOG(Plugins, "%f Total load time: %f seconds", currentTime, duration);
610 [self _unloadWithShutdown:NO];
614 - (NPP_SetWindowProcPtr)NPP_SetWindow
616 return NPP_SetWindow;
619 - (NPP_NewProcPtr)NPP_New
624 - (NPP_DestroyProcPtr)NPP_Destroy
629 - (NPP_NewStreamProcPtr)NPP_NewStream
631 return NPP_NewStream;
634 - (NPP_StreamAsFileProcPtr)NPP_StreamAsFile
636 return NPP_StreamAsFile;
638 - (NPP_DestroyStreamProcPtr)NPP_DestroyStream
640 return NPP_DestroyStream;
643 - (NPP_WriteReadyProcPtr)NPP_WriteReady
645 return NPP_WriteReady;
647 - (NPP_WriteProcPtr)NPP_Write
652 - (NPP_HandleEventProcPtr)NPP_HandleEvent
654 return NPP_HandleEvent;
657 -(NPP_URLNotifyProcPtr)NPP_URLNotify
659 return NPP_URLNotify;
662 -(NPP_GetValueProcPtr)NPP_GetValue
667 -(NPP_SetValueProcPtr)NPP_SetValue
672 -(NPP_PrintProcPtr)NPP_Print
677 - (void)wasRemovedFromPluginDatabase:(WebPluginDatabase *)database
679 [super wasRemovedFromPluginDatabase:database];
681 // Unload when removed from final plug-in database
682 if ([pluginDatabases count] == 0)
683 [self _unloadWithShutdown:YES];
690 // Handle the case where all instances close a plug-in package, but another
691 // instance opens the package before it is unloaded (which only happens when
692 // the plug-in database is refreshed)
696 // Should load when the first instance opens the plug-in package
697 ASSERT(instanceCount == 1);
704 ASSERT(instanceCount > 0);
706 if (instanceCount == 0 && needsUnload)
707 [self _unloadWithShutdown:YES];
714 // function pointer converters
716 FunctionPointer functionPointerForTVector(TransitionVector tvp)
718 const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420};
719 uint32 *newGlue = NULL;
722 newGlue = (uint32 *)malloc(sizeof(temp));
723 if (newGlue != NULL) {
725 for (i = 0; i < 6; i++) newGlue[i] = temp[i];
726 newGlue[0] |= ((uintptr_t)tvp >> 16);
727 newGlue[1] |= ((uintptr_t)tvp & 0xFFFF);
728 MakeDataExecutable(newGlue, sizeof(temp));
732 return (FunctionPointer)newGlue;
735 TransitionVector tVectorForFunctionPointer(FunctionPointer fp)
737 FunctionPointer *newGlue = NULL;
739 newGlue = (FunctionPointer *)malloc(2 * sizeof(FunctionPointer));
740 if (newGlue != NULL) {
745 return (TransitionVector)newGlue;
750 @implementation WebNetscapePluginPackage (Internal)
752 - (void)_unloadWithShutdown:(BOOL)shutdown
757 LOG(Plugins, "Unloading %@...", name);
759 // Cannot unload a plug-in package while an instance is still using it
760 if (instanceCount > 0) {
765 if (shutdown && NPP_Shutdown)
768 if (resourceRef != -1)
769 [self closeResourceFile:resourceRef];
774 CFBundleUnloadExecutable(cfBundle);
777 WebCloseConnection(&connID);
780 LOG(Plugins, "Plugin Unloaded");