--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/Plugins/WebNetscapePluginPackage.m Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,773 @@
+/*
+ * 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 <JavaScriptCore/npruntime_impl.h>
+
+#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