/* * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __LP64__ #import "WebNetscapePluginPackage.h" #import "WebKitLogging.h" #import "WebKitNSStringExtras.h" #import "WebNSObjectExtras.h" #import "WebNetscapeDeprecatedFunctions.h" #import #ifdef SUPPORT_CFM typedef void (* FunctionPointer)(void); typedef void (* TransitionVector)(void); static FunctionPointer functionPointerForTVector(TransitionVector); static TransitionVector tVectorForFunctionPointer(FunctionPointer); #endif #define PluginNameOrDescriptionStringNumber 126 #define MIMEDescriptionStringNumber 127 #define MIMEListStringStringNumber 128 #define RealPlayerAppIndentifier @"com.RealNetworks.RealOne Player" #define RealPlayerPluginFilename @"RealPlayer Plugin" @interface WebNetscapePluginPackage (Internal) - (void)_unloadWithShutdown:(BOOL)shutdown; @end @implementation WebNetscapePluginPackage #ifndef __LP64__ + (void)initialize { // The Shockwave plugin requires a valid file in CurApRefNum. // But it doesn't seem to matter what file it is. // If we're called inside a Cocoa application which won't have a // CurApRefNum, we set it to point to the system resource file. // Call CurResFile before testing the result of WebLMGetCurApRefNum. // If we are called before the bundle resource map has been opened // for a Carbon application (or a Cocoa app with Resource Manager // resources) we *do not* want to set CurApRefNum to point at the // system resource file. CurResFile triggers Resource Manager lazy // initialization, and will open the bundle resource map as necessary. CurResFile(); if (WebLMGetCurApRefNum() == -1) { // To get the refNum for the system resource file, we have to do // UseResFile(kSystemResFile) and then look at CurResFile(). short savedCurResFile = CurResFile(); UseResFile(kSystemResFile); WebLMSetCurApRefNum(CurResFile()); UseResFile(savedCurResFile); } } #endif - (ResFileRefNum)openResourceFile { #ifdef SUPPORT_CFM if (!isBundle) { FSRef fref; OSErr err = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &fref, NULL); if (err != noErr) return -1; return FSOpenResFile(&fref, fsRdPerm); } #endif return CFBundleOpenBundleResourceMap(cfBundle); } - (void)closeResourceFile:(ResFileRefNum)resRef { #ifdef SUPPORT_CFM if (!isBundle) { CloseResFile(resRef); return; } #endif CFBundleCloseBundleResourceMap(cfBundle, resRef); } - (NSString *)stringForStringListID:(SInt16)stringListID andIndex:(SInt16)index { // Get resource, and dereference the handle. Handle stringHandle = Get1Resource('STR#', stringListID); if (stringHandle == NULL) { return nil; } unsigned char *p = (unsigned char *)*stringHandle; if (!p) return nil; // Check the index against the length of the string list, then skip the length. if (index < 1 || index > *(SInt16 *)p) return nil; p += sizeof(SInt16); // Skip any strings that come before the one we are looking for. while (--index) p += 1 + *p; // Convert the one we found into an NSString. return [[[NSString alloc] initWithBytes:(p + 1) length:*p encoding:[NSString _web_encodingForResource:stringHandle]] autorelease]; } - (BOOL)getPluginInfoFromResources { SInt16 resRef = [self openResourceFile]; if (resRef == -1) return NO; UseResFile(resRef); if (ResError() != noErr) return NO; NSString *MIME, *extensionsList, *description; NSArray *extensions; unsigned i; NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary]; NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary]; for (i=1; 1; i+=2) { MIME = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i] lowercaseString]; if (!MIME) break; extensionsList = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i+1] lowercaseString]; if (extensionsList) { extensions = [extensionsList componentsSeparatedByString:@","]; [MIMEToExtensionsDictionary setObject:extensions forKey:MIME]; } else // DRM and WMP claim MIMEs without extensions. Use a @"" extension in this case. [MIMEToExtensionsDictionary setObject:[NSArray arrayWithObject:@""] forKey:MIME]; description = [self stringForStringListID:MIMEDescriptionStringNumber andIndex:[MIMEToExtensionsDictionary count]]; if (description) [MIMEToDescriptionDictionary setObject:description forKey:MIME]; else [MIMEToDescriptionDictionary setObject:@"" forKey:MIME]; } [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary]; [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary]; NSString *filename = [self filename]; description = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:1]; if (!description) description = filename; [self setPluginDescription:description]; NSString *theName = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:2]; if (!theName) theName = filename; [self setName:theName]; [self closeResourceFile:resRef]; return YES; } - (BOOL)_initWithPath:(NSString *)pluginPath { resourceRef = -1; OSType type = 0; if (bundle) { // Bundle CFBundleGetPackageInfo(cfBundle, &type, NULL); #ifdef SUPPORT_CFM isBundle = YES; #endif } else { #ifdef SUPPORT_CFM // Single-file plug-in with resource fork type = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileHFSTypeCode]; isBundle = NO; isCFM = YES; #else return NO; #endif } if (type != FOUR_CHAR_CODE('BRPL')) return NO; // Check if the executable is Mach-O or CFM. if (bundle) { NSFileHandle *executableFile = [NSFileHandle fileHandleForReadingAtPath:[bundle executablePath]]; NSData *data = [executableFile readDataOfLength:512]; [executableFile closeFile]; // Check the length of the data before calling memcmp. We think this fixes 3782543. if (data == nil || [data length] < 8) return NO; BOOL hasCFMHeader = memcmp([data bytes], "Joy!peff", 8) == 0; #ifdef SUPPORT_CFM isCFM = hasCFMHeader; #else if (hasCFMHeader) return NO; #endif if (![self isNativeLibraryData:data]) return NO; } if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources]) return NO; return YES; } - (id)initWithPath:(NSString *)pluginPath { if (!(self = [super initWithPath:pluginPath])) return nil; // Initializing a plugin package can cause it to be loaded. If there was an error initializing the plugin package, // ensure that it is unloaded before deallocating it (WebBasePluginPackage requires & asserts this). if (![self _initWithPath:pluginPath]) { [self _unloadWithShutdown:YES]; [self release]; return nil; } return self; } - (WebExecutableType)executableType { #ifdef SUPPORT_CFM if (isCFM) return WebCFMExecutableType; #endif return WebMachOExecutableType; } - (void)launchRealPlayer { CFURLRef appURL = NULL; OSStatus error = LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)RealPlayerAppIndentifier, NULL, NULL, &appURL); if (!error) { LSLaunchURLSpec URLSpec; bzero(&URLSpec, sizeof(URLSpec)); URLSpec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; URLSpec.appURL = appURL; LSOpenFromURLSpec(&URLSpec, NULL); CFRelease(appURL); } } - (void)_applyDjVuWorkaround { if (!cfBundle) return; if ([(NSString *)CFBundleGetIdentifier(cfBundle) isEqualToString:@"com.lizardtech.NPDjVu"]) { // The DjVu plug-in will crash copying the vtable if it's too big so we cap it to // what the plug-in expects here. // size + version + 40 function pointers. browserFuncs.size = 2 + 2 + sizeof(void *) * 40; } } - (BOOL)load { NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL; NP_InitializeFuncPtr NP_Initialize = NULL; NPError npErr; #ifdef SUPPORT_CFM MainFuncPtr pluginMainFunc = NULL; #endif #if !LOG_DISABLED CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); CFAbsoluteTime currentTime; CFAbsoluteTime duration; #endif LOG(Plugins, "%f Load timing started for: %@", start, [self name]); if (isLoaded) return YES; #ifdef SUPPORT_CFM if (isBundle) { #endif if (!CFBundleLoadExecutable(cfBundle)) goto abort; #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - start; #endif LOG(Plugins, "%f CFBundleLoadExecutable took %f seconds", currentTime, duration); isLoaded = YES; #ifdef SUPPORT_CFM if (isCFM) { pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") ); if (!pluginMainFunc) goto abort; } else { #endif NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize")); NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints")); NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown")); if (!NP_Initialize || !NP_GetEntryPoints || !NPP_Shutdown) goto abort; #ifdef SUPPORT_CFM } } else { // single CFM file FSSpec spec; FSRef fref; OSErr err; err = FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], &fref, NULL); if (err != noErr) { LOG_ERROR("FSPathMakeRef failed. Error=%d", err); goto abort; } err = FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &spec, NULL); if (err != noErr) { LOG_ERROR("FSGetCatalogInfo failed. Error=%d", err); goto abort; } err = WebGetDiskFragment(&spec, 0, kCFragGoesToEOF, nil, kPrivateCFragCopy, &connID, (Ptr *)&pluginMainFunc, nil); if (err != noErr) { LOG_ERROR("WebGetDiskFragment failed. Error=%d", err); goto abort; } #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - start; #endif LOG(Plugins, "%f WebGetDiskFragment took %f seconds", currentTime, duration); isLoaded = YES; pluginMainFunc = (MainFuncPtr)functionPointerForTVector((TransitionVector)pluginMainFunc); if (!pluginMainFunc) { goto abort; } // NOTE: pluginMainFunc is freed after it is called. Be sure not to return before that. isCFM = YES; } #endif /* SUPPORT_CFM */ // Plugins (at least QT) require that you call UseResFile on the resource file before loading it. resourceRef = [self openResourceFile]; if (resourceRef != -1) { UseResFile(resourceRef); } // swap function tables #ifdef SUPPORT_CFM if (isCFM) { browserFuncs.version = NP_VERSION_MINOR; browserFuncs.size = sizeof(NPNetscapeFuncs); browserFuncs.geturl = (NPN_GetURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURL); browserFuncs.posturl = (NPN_PostURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURL); browserFuncs.requestread = (NPN_RequestReadProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_RequestRead); browserFuncs.newstream = (NPN_NewStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_NewStream); browserFuncs.write = (NPN_WriteProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Write); browserFuncs.destroystream = (NPN_DestroyStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_DestroyStream); browserFuncs.status = (NPN_StatusProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Status); browserFuncs.uagent = (NPN_UserAgentProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_UserAgent); browserFuncs.memalloc = (NPN_MemAllocProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemAlloc); browserFuncs.memfree = (NPN_MemFreeProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFree); browserFuncs.memflush = (NPN_MemFlushProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFlush); browserFuncs.reloadplugins = (NPN_ReloadPluginsProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ReloadPlugins); browserFuncs.geturlnotify = (NPN_GetURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURLNotify); browserFuncs.posturlnotify = (NPN_PostURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURLNotify); browserFuncs.getvalue = (NPN_GetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetValue); browserFuncs.setvalue = (NPN_SetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_SetValue); browserFuncs.invalidaterect = (NPN_InvalidateRectProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRect); browserFuncs.invalidateregion = (NPN_InvalidateRegionProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRegion); browserFuncs.forceredraw = (NPN_ForceRedrawProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ForceRedraw); browserFuncs.getJavaEnv = (NPN_GetJavaEnvProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaEnv); browserFuncs.getJavaPeer = (NPN_GetJavaPeerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaPeer); browserFuncs.pushpopupsenabledstate = (NPN_PushPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PushPopupsEnabledState); browserFuncs.poppopupsenabledstate = (NPN_PopPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PopPopupsEnabledState); browserFuncs.releasevariantvalue = (NPN_ReleaseVariantValueProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseVariantValue); browserFuncs.getstringidentifier = (NPN_GetStringIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifier); browserFuncs.getstringidentifiers = (NPN_GetStringIdentifiersProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifiers); browserFuncs.getintidentifier = (NPN_GetIntIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetIntIdentifier); browserFuncs.identifierisstring = (NPN_IdentifierIsStringProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_IdentifierIsString); browserFuncs.utf8fromidentifier = (NPN_UTF8FromIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_UTF8FromIdentifier); browserFuncs.createobject = (NPN_CreateObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_CreateObject); browserFuncs.retainobject = (NPN_RetainObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RetainObject); browserFuncs.releaseobject = (NPN_ReleaseObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseObject); browserFuncs.invoke = (NPN_InvokeProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Invoke); browserFuncs.invokeDefault = (NPN_InvokeDefaultProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_InvokeDefault); browserFuncs.evaluate = (NPN_EvaluateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Evaluate); browserFuncs.getproperty = (NPN_GetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetProperty); browserFuncs.setproperty = (NPN_SetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetProperty); browserFuncs.removeproperty = (NPN_RemovePropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RemoveProperty); browserFuncs.setexception = (NPN_SetExceptionProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetException); browserFuncs.enumerate = (NPN_EnumerateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Enumerate); [self _applyDjVuWorkaround]; #if !LOG_DISABLED CFAbsoluteTime mainStart = CFAbsoluteTimeGetCurrent(); #endif LOG(Plugins, "%f main timing started", mainStart); NPP_ShutdownProcPtr shutdownFunction; npErr = pluginMainFunc(&browserFuncs, &pluginFuncs, &shutdownFunction); NPP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction); if (!isBundle) // Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case. free(pluginMainFunc); // Workaround for 3270576. The RealPlayer plug-in fails to load if its preference file is out of date. // Launch the RealPlayer application to refresh the file. if (npErr != NPERR_NO_ERROR) { if (npErr == NPERR_MODULE_LOAD_FAILED_ERROR && [[self filename] isEqualToString:RealPlayerPluginFilename]) [self launchRealPlayer]; goto abort; } #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - mainStart; #endif LOG(Plugins, "%f main took %f seconds", currentTime, duration); pluginSize = pluginFuncs.size; pluginVersion = pluginFuncs.version; LOG(Plugins, "pluginMainFunc: %d, size=%d, version=%d", npErr, pluginSize, pluginVersion); NPP_New = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp); NPP_Destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy); NPP_SetWindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow); NPP_NewStream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream); NPP_DestroyStream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream); NPP_StreamAsFile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile); NPP_WriteReady = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready); NPP_Write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write); NPP_Print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print); NPP_HandleEvent = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event); NPP_URLNotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify); NPP_GetValue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue); NPP_SetValue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue); // LiveConnect support NPP_GetJavaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass); if (NPP_GetJavaClass) { LOG(LiveConnect, "%@: CFM entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass); } else { LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]); } } else { #endif // no function pointer conversion necessary for Mach-O browserFuncs.version = NP_VERSION_MINOR; browserFuncs.size = sizeof(NPNetscapeFuncs); browserFuncs.geturl = NPN_GetURL; browserFuncs.posturl = NPN_PostURL; browserFuncs.requestread = NPN_RequestRead; browserFuncs.newstream = NPN_NewStream; browserFuncs.write = NPN_Write; browserFuncs.destroystream = NPN_DestroyStream; browserFuncs.status = NPN_Status; browserFuncs.uagent = NPN_UserAgent; browserFuncs.memalloc = NPN_MemAlloc; browserFuncs.memfree = NPN_MemFree; browserFuncs.memflush = NPN_MemFlush; browserFuncs.reloadplugins = NPN_ReloadPlugins; browserFuncs.geturlnotify = NPN_GetURLNotify; browserFuncs.posturlnotify = NPN_PostURLNotify; browserFuncs.getvalue = NPN_GetValue; browserFuncs.setvalue = NPN_SetValue; browserFuncs.invalidaterect = NPN_InvalidateRect; browserFuncs.invalidateregion = NPN_InvalidateRegion; browserFuncs.forceredraw = NPN_ForceRedraw; browserFuncs.getJavaEnv = NPN_GetJavaEnv; browserFuncs.getJavaPeer = NPN_GetJavaPeer; browserFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState; browserFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState; browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue; browserFuncs.getstringidentifier = _NPN_GetStringIdentifier; browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers; browserFuncs.getintidentifier = _NPN_GetIntIdentifier; browserFuncs.identifierisstring = _NPN_IdentifierIsString; browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier; browserFuncs.createobject = _NPN_CreateObject; browserFuncs.retainobject = _NPN_RetainObject; browserFuncs.releaseobject = _NPN_ReleaseObject; browserFuncs.invoke = _NPN_Invoke; browserFuncs.invokeDefault = _NPN_InvokeDefault; browserFuncs.evaluate = _NPN_Evaluate; browserFuncs.getproperty = _NPN_GetProperty; browserFuncs.setproperty = _NPN_SetProperty; browserFuncs.removeproperty = _NPN_RemoveProperty; browserFuncs.setexception = _NPN_SetException; browserFuncs.enumerate = _NPN_Enumerate; [self _applyDjVuWorkaround]; #if !LOG_DISABLED CFAbsoluteTime initializeStart = CFAbsoluteTimeGetCurrent(); #endif LOG(Plugins, "%f NP_Initialize timing started", initializeStart); npErr = NP_Initialize(&browserFuncs); if (npErr != NPERR_NO_ERROR) goto abort; #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - initializeStart; #endif LOG(Plugins, "%f NP_Initialize took %f seconds", currentTime, duration); npErr = NP_GetEntryPoints(&pluginFuncs); if (npErr != NPERR_NO_ERROR) goto abort; pluginSize = pluginFuncs.size; pluginVersion = pluginFuncs.version; NPP_New = pluginFuncs.newp; NPP_Destroy = pluginFuncs.destroy; NPP_SetWindow = pluginFuncs.setwindow; NPP_NewStream = pluginFuncs.newstream; NPP_DestroyStream = pluginFuncs.destroystream; NPP_StreamAsFile = pluginFuncs.asfile; NPP_WriteReady = pluginFuncs.writeready; NPP_Write = pluginFuncs.write; NPP_Print = pluginFuncs.print; NPP_HandleEvent = pluginFuncs.event; NPP_URLNotify = pluginFuncs.urlnotify; NPP_GetValue = pluginFuncs.getvalue; NPP_SetValue = pluginFuncs.setvalue; // LiveConnect support NPP_GetJavaClass = pluginFuncs.javaClass; if (NPP_GetJavaClass){ LOG(LiveConnect, "%@: mach-o entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass); } else { LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]); } #ifdef SUPPORT_CFM } #endif #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - start; #endif LOG(Plugins, "%f Total load time: %f seconds", currentTime, duration); return [super load]; abort: [self _unloadWithShutdown:NO]; return NO; } - (NPP_SetWindowProcPtr)NPP_SetWindow { return NPP_SetWindow; } - (NPP_NewProcPtr)NPP_New { return NPP_New; } - (NPP_DestroyProcPtr)NPP_Destroy { return NPP_Destroy; } - (NPP_NewStreamProcPtr)NPP_NewStream { return NPP_NewStream; } - (NPP_StreamAsFileProcPtr)NPP_StreamAsFile { return NPP_StreamAsFile; } - (NPP_DestroyStreamProcPtr)NPP_DestroyStream { return NPP_DestroyStream; } - (NPP_WriteReadyProcPtr)NPP_WriteReady { return NPP_WriteReady; } - (NPP_WriteProcPtr)NPP_Write { return NPP_Write; } - (NPP_HandleEventProcPtr)NPP_HandleEvent { return NPP_HandleEvent; } -(NPP_URLNotifyProcPtr)NPP_URLNotify { return NPP_URLNotify; } -(NPP_GetValueProcPtr)NPP_GetValue { return NPP_GetValue; } -(NPP_SetValueProcPtr)NPP_SetValue { return NPP_SetValue; } -(NPP_PrintProcPtr)NPP_Print { return NPP_Print; } - (void)wasRemovedFromPluginDatabase:(WebPluginDatabase *)database { [super wasRemovedFromPluginDatabase:database]; // Unload when removed from final plug-in database if ([pluginDatabases count] == 0) [self _unloadWithShutdown:YES]; } - (void)open { instanceCount++; // Handle the case where all instances close a plug-in package, but another // instance opens the package before it is unloaded (which only happens when // the plug-in database is refreshed) needsUnload = NO; if (!isLoaded) { // Should load when the first instance opens the plug-in package ASSERT(instanceCount == 1); [self load]; } } - (void)close { ASSERT(instanceCount > 0); instanceCount--; if (instanceCount == 0 && needsUnload) [self _unloadWithShutdown:YES]; } @end #ifdef SUPPORT_CFM // function pointer converters FunctionPointer functionPointerForTVector(TransitionVector tvp) { const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; uint32 *newGlue = NULL; if (tvp != NULL) { newGlue = (uint32 *)malloc(sizeof(temp)); if (newGlue != NULL) { unsigned i; for (i = 0; i < 6; i++) newGlue[i] = temp[i]; newGlue[0] |= ((uintptr_t)tvp >> 16); newGlue[1] |= ((uintptr_t)tvp & 0xFFFF); MakeDataExecutable(newGlue, sizeof(temp)); } } return (FunctionPointer)newGlue; } TransitionVector tVectorForFunctionPointer(FunctionPointer fp) { FunctionPointer *newGlue = NULL; if (fp != NULL) { newGlue = (FunctionPointer *)malloc(2 * sizeof(FunctionPointer)); if (newGlue != NULL) { newGlue[0] = fp; newGlue[1] = NULL; } } return (TransitionVector)newGlue; } #endif @implementation WebNetscapePluginPackage (Internal) - (void)_unloadWithShutdown:(BOOL)shutdown { if (!isLoaded) return; LOG(Plugins, "Unloading %@...", name); // Cannot unload a plug-in package while an instance is still using it if (instanceCount > 0) { needsUnload = YES; return; } if (shutdown && NPP_Shutdown) NPP_Shutdown(); if (resourceRef != -1) [self closeResourceFile:resourceRef]; #ifdef SUPPORT_CFM if (isBundle) #endif CFBundleUnloadExecutable(cfBundle); #ifdef SUPPORT_CFM else WebCloseConnection(&connID); #endif LOG(Plugins, "Plugin Unloaded"); isLoaded = NO; } @end #endif