webengine/osswebengine/WebKit/Plugins/WebNetscapePluginPackage.m
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2005, 2006, 2007 Apple 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 #ifndef __LP64__
       
    30 #import "WebNetscapePluginPackage.h"
       
    31 
       
    32 #import "WebKitLogging.h"
       
    33 #import "WebKitNSStringExtras.h"
       
    34 #import "WebNSObjectExtras.h"
       
    35 #import "WebNetscapeDeprecatedFunctions.h"
       
    36 #import <JavaScriptCore/npruntime_impl.h>
       
    37 
       
    38 #ifdef SUPPORT_CFM
       
    39 typedef void (* FunctionPointer)(void);
       
    40 typedef void (* TransitionVector)(void);
       
    41 static FunctionPointer functionPointerForTVector(TransitionVector);
       
    42 static TransitionVector tVectorForFunctionPointer(FunctionPointer);
       
    43 #endif
       
    44 
       
    45 #define PluginNameOrDescriptionStringNumber     126
       
    46 #define MIMEDescriptionStringNumber             127
       
    47 #define MIMEListStringStringNumber              128
       
    48 
       
    49 #define RealPlayerAppIndentifier                @"com.RealNetworks.RealOne Player"
       
    50 #define RealPlayerPluginFilename                @"RealPlayer Plugin"
       
    51 
       
    52 @interface WebNetscapePluginPackage (Internal)
       
    53 - (void)_unloadWithShutdown:(BOOL)shutdown;
       
    54 @end
       
    55 
       
    56 @implementation WebNetscapePluginPackage
       
    57 
       
    58 #ifndef __LP64__
       
    59 + (void)initialize
       
    60 {
       
    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.
       
    65 
       
    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.
       
    72 
       
    73     CurResFile();
       
    74 
       
    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);
       
    82     }
       
    83 }
       
    84 #endif
       
    85 
       
    86 - (ResFileRefNum)openResourceFile
       
    87 {
       
    88 #ifdef SUPPORT_CFM
       
    89     if (!isBundle) {
       
    90         FSRef fref;
       
    91         OSErr err = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &fref, NULL);
       
    92         if (err != noErr)
       
    93             return -1;
       
    94         
       
    95         return FSOpenResFile(&fref, fsRdPerm);
       
    96     }
       
    97 #endif
       
    98 
       
    99     return CFBundleOpenBundleResourceMap(cfBundle);
       
   100 }
       
   101 
       
   102 - (void)closeResourceFile:(ResFileRefNum)resRef
       
   103 {
       
   104 #ifdef SUPPORT_CFM
       
   105     if (!isBundle) {
       
   106         CloseResFile(resRef);
       
   107         return;
       
   108     }
       
   109 #endif
       
   110 
       
   111     CFBundleCloseBundleResourceMap(cfBundle, resRef);
       
   112 }
       
   113 
       
   114 - (NSString *)stringForStringListID:(SInt16)stringListID andIndex:(SInt16)index
       
   115 {
       
   116     // Get resource, and dereference the handle.
       
   117     Handle stringHandle = Get1Resource('STR#', stringListID);
       
   118     if (stringHandle == NULL) {
       
   119         return nil;
       
   120     }
       
   121     unsigned char *p = (unsigned char *)*stringHandle;
       
   122     if (!p)
       
   123         return nil;
       
   124     
       
   125     // Check the index against the length of the string list, then skip the length.
       
   126     if (index < 1 || index > *(SInt16 *)p)
       
   127         return nil;
       
   128     p += sizeof(SInt16);
       
   129     
       
   130     // Skip any strings that come before the one we are looking for.
       
   131     while (--index)
       
   132         p += 1 + *p;
       
   133     
       
   134     // Convert the one we found into an NSString.
       
   135     return [[[NSString alloc] initWithBytes:(p + 1) length:*p encoding:[NSString _web_encodingForResource:stringHandle]] autorelease];
       
   136 }
       
   137 
       
   138 - (BOOL)getPluginInfoFromResources
       
   139 {
       
   140     SInt16 resRef = [self openResourceFile];
       
   141     if (resRef == -1)
       
   142         return NO;
       
   143     
       
   144     UseResFile(resRef);
       
   145     if (ResError() != noErr)
       
   146         return NO;
       
   147 
       
   148     NSString *MIME, *extensionsList, *description;
       
   149     NSArray *extensions;
       
   150     unsigned i;
       
   151     
       
   152     NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary];
       
   153     NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary];
       
   154 
       
   155     for (i=1; 1; i+=2) {
       
   156         MIME = [[self stringForStringListID:MIMEListStringStringNumber
       
   157                                    andIndex:i] lowercaseString];
       
   158         if (!MIME)
       
   159             break;
       
   160 
       
   161         extensionsList = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i+1] lowercaseString];
       
   162         if (extensionsList) {
       
   163             extensions = [extensionsList componentsSeparatedByString:@","];
       
   164             [MIMEToExtensionsDictionary setObject:extensions forKey:MIME];
       
   165         } else
       
   166             // DRM and WMP claim MIMEs without extensions. Use a @"" extension in this case.
       
   167             [MIMEToExtensionsDictionary setObject:[NSArray arrayWithObject:@""] forKey:MIME];
       
   168         
       
   169         description = [self stringForStringListID:MIMEDescriptionStringNumber
       
   170                                          andIndex:[MIMEToExtensionsDictionary count]];
       
   171         if (description)
       
   172             [MIMEToDescriptionDictionary setObject:description forKey:MIME];
       
   173         else
       
   174             [MIMEToDescriptionDictionary setObject:@"" forKey:MIME];
       
   175     }
       
   176 
       
   177     [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary];
       
   178     [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary];
       
   179 
       
   180     NSString *filename = [self filename];
       
   181     
       
   182     description = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:1];
       
   183     if (!description)
       
   184         description = filename;
       
   185     [self setPluginDescription:description];
       
   186     
       
   187     
       
   188     NSString *theName = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:2];
       
   189     if (!theName)
       
   190         theName = filename;
       
   191     [self setName:theName];
       
   192     
       
   193     [self closeResourceFile:resRef];
       
   194     
       
   195     return YES;
       
   196 }
       
   197 
       
   198 - (BOOL)_initWithPath:(NSString *)pluginPath
       
   199 {
       
   200     resourceRef = -1;
       
   201     
       
   202     OSType type = 0;
       
   203 
       
   204     if (bundle) {
       
   205         // Bundle
       
   206         CFBundleGetPackageInfo(cfBundle, &type, NULL);
       
   207 #ifdef SUPPORT_CFM
       
   208         isBundle = YES;
       
   209 #endif
       
   210     } else {
       
   211 #ifdef SUPPORT_CFM
       
   212         // Single-file plug-in with resource fork
       
   213         type = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileHFSTypeCode];
       
   214         isBundle = NO;
       
   215         isCFM = YES;
       
   216 #else
       
   217         return NO;
       
   218 #endif
       
   219     }
       
   220     
       
   221     if (type != FOUR_CHAR_CODE('BRPL'))
       
   222         return NO;
       
   223 
       
   224     // Check if the executable is Mach-O or CFM.
       
   225     if (bundle) {
       
   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)
       
   231             return NO;
       
   232         BOOL hasCFMHeader = memcmp([data bytes], "Joy!peff", 8) == 0;
       
   233 #ifdef SUPPORT_CFM
       
   234         isCFM = hasCFMHeader;
       
   235 #else
       
   236         if (hasCFMHeader)
       
   237             return NO;
       
   238 #endif
       
   239         if (![self isNativeLibraryData:data])
       
   240             return NO;
       
   241     }
       
   242 
       
   243     if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources])
       
   244         return NO;
       
   245     
       
   246     return YES;
       
   247 }
       
   248 
       
   249 - (id)initWithPath:(NSString *)pluginPath
       
   250 {
       
   251     if (!(self = [super initWithPath:pluginPath]))
       
   252         return nil;
       
   253     
       
   254     // Initializing a plugin package can cause it to be loaded.  If there was an error initializing the plugin package,
       
   255     // ensure that it is unloaded before deallocating it (WebBasePluginPackage requires & asserts this).
       
   256     if (![self _initWithPath:pluginPath]) {
       
   257         [self _unloadWithShutdown:YES];
       
   258         [self release];
       
   259         return nil;
       
   260     }
       
   261         
       
   262     return self;
       
   263 }
       
   264 
       
   265 - (WebExecutableType)executableType
       
   266 {
       
   267 #ifdef SUPPORT_CFM
       
   268     if (isCFM)
       
   269         return WebCFMExecutableType;
       
   270 #endif
       
   271     return WebMachOExecutableType;
       
   272 }
       
   273 
       
   274 - (void)launchRealPlayer
       
   275 {
       
   276     CFURLRef appURL = NULL;
       
   277     OSStatus error = LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)RealPlayerAppIndentifier, NULL, NULL, &appURL);
       
   278     if (!error) {
       
   279         LSLaunchURLSpec URLSpec;
       
   280         bzero(&URLSpec, sizeof(URLSpec));
       
   281         URLSpec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch;
       
   282         URLSpec.appURL = appURL;
       
   283         LSOpenFromURLSpec(&URLSpec, NULL);
       
   284         CFRelease(appURL);
       
   285     }
       
   286 }
       
   287 
       
   288 - (void)_applyDjVuWorkaround
       
   289 {
       
   290     if (!cfBundle)
       
   291         return;
       
   292     
       
   293     if ([(NSString *)CFBundleGetIdentifier(cfBundle) isEqualToString:@"com.lizardtech.NPDjVu"]) {
       
   294         // The DjVu plug-in will crash copying the vtable if it's too big so we cap it to 
       
   295         // what the plug-in expects here. 
       
   296         // size + version + 40 function pointers.
       
   297         browserFuncs.size = 2 + 2 + sizeof(void *) * 40;
       
   298     }
       
   299         
       
   300 }
       
   301 
       
   302 - (BOOL)load
       
   303 {    
       
   304     NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL;
       
   305     NP_InitializeFuncPtr NP_Initialize = NULL;
       
   306     NPError npErr;
       
   307 
       
   308 #ifdef SUPPORT_CFM
       
   309     MainFuncPtr pluginMainFunc = NULL;
       
   310 #endif
       
   311 
       
   312 #if !LOG_DISABLED
       
   313     CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
       
   314     CFAbsoluteTime currentTime;
       
   315     CFAbsoluteTime duration;
       
   316 #endif
       
   317     LOG(Plugins, "%f Load timing started for: %@", start, [self name]);
       
   318 
       
   319     if (isLoaded)
       
   320         return YES;
       
   321     
       
   322 #ifdef SUPPORT_CFM
       
   323     if (isBundle) {
       
   324 #endif
       
   325         if (!CFBundleLoadExecutable(cfBundle))
       
   326             goto abort;
       
   327 #if !LOG_DISABLED
       
   328         currentTime = CFAbsoluteTimeGetCurrent();
       
   329         duration = currentTime - start;
       
   330 #endif
       
   331         LOG(Plugins, "%f CFBundleLoadExecutable took %f seconds", currentTime, duration);
       
   332         isLoaded = YES;
       
   333         
       
   334 #ifdef SUPPORT_CFM
       
   335         if (isCFM) {
       
   336             pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") );
       
   337             if (!pluginMainFunc)
       
   338                 goto abort;
       
   339         } else {
       
   340 #endif
       
   341             NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize"));
       
   342             NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints"));
       
   343             NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
       
   344             if (!NP_Initialize || !NP_GetEntryPoints || !NPP_Shutdown)
       
   345                 goto abort;
       
   346 #ifdef SUPPORT_CFM
       
   347         }
       
   348     } else {
       
   349         // single CFM file
       
   350         FSSpec spec;
       
   351         FSRef fref;
       
   352         OSErr err;
       
   353         
       
   354         err = FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], &fref, NULL);
       
   355         if (err != noErr) {
       
   356             LOG_ERROR("FSPathMakeRef failed. Error=%d", err);
       
   357             goto abort;
       
   358         }
       
   359         err = FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
       
   360         if (err != noErr) {
       
   361             LOG_ERROR("FSGetCatalogInfo failed. Error=%d", err);
       
   362             goto abort;
       
   363         }
       
   364         err = WebGetDiskFragment(&spec, 0, kCFragGoesToEOF, nil, kPrivateCFragCopy, &connID, (Ptr *)&pluginMainFunc, nil);
       
   365         if (err != noErr) {
       
   366             LOG_ERROR("WebGetDiskFragment failed. Error=%d", err);
       
   367             goto abort;
       
   368         }
       
   369 #if !LOG_DISABLED
       
   370         currentTime = CFAbsoluteTimeGetCurrent();
       
   371         duration = currentTime - start;
       
   372 #endif
       
   373         LOG(Plugins, "%f WebGetDiskFragment took %f seconds", currentTime, duration);
       
   374         isLoaded = YES;
       
   375         
       
   376         pluginMainFunc = (MainFuncPtr)functionPointerForTVector((TransitionVector)pluginMainFunc);
       
   377         if (!pluginMainFunc) {
       
   378             goto abort;
       
   379         }
       
   380 
       
   381         // NOTE: pluginMainFunc is freed after it is called. Be sure not to return before that.
       
   382         
       
   383         isCFM = YES;
       
   384     }
       
   385 #endif /* SUPPORT_CFM */
       
   386     
       
   387     // Plugins (at least QT) require that you call UseResFile on the resource file before loading it.
       
   388     resourceRef = [self openResourceFile];
       
   389     if (resourceRef != -1) {
       
   390         UseResFile(resourceRef);
       
   391     }
       
   392     
       
   393     // swap function tables
       
   394 #ifdef SUPPORT_CFM
       
   395     if (isCFM) {
       
   396         browserFuncs.version = NP_VERSION_MINOR;
       
   397         browserFuncs.size = sizeof(NPNetscapeFuncs);
       
   398         browserFuncs.geturl = (NPN_GetURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURL);
       
   399         browserFuncs.posturl = (NPN_PostURLProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURL);
       
   400         browserFuncs.requestread = (NPN_RequestReadProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_RequestRead);
       
   401         browserFuncs.newstream = (NPN_NewStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_NewStream);
       
   402         browserFuncs.write = (NPN_WriteProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Write);
       
   403         browserFuncs.destroystream = (NPN_DestroyStreamProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_DestroyStream);
       
   404         browserFuncs.status = (NPN_StatusProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_Status);
       
   405         browserFuncs.uagent = (NPN_UserAgentProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_UserAgent);
       
   406         browserFuncs.memalloc = (NPN_MemAllocProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemAlloc);
       
   407         browserFuncs.memfree = (NPN_MemFreeProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFree);
       
   408         browserFuncs.memflush = (NPN_MemFlushProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_MemFlush);
       
   409         browserFuncs.reloadplugins = (NPN_ReloadPluginsProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ReloadPlugins);
       
   410         browserFuncs.geturlnotify = (NPN_GetURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetURLNotify);
       
   411         browserFuncs.posturlnotify = (NPN_PostURLNotifyProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PostURLNotify);
       
   412         browserFuncs.getvalue = (NPN_GetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetValue);
       
   413         browserFuncs.setvalue = (NPN_SetValueProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_SetValue);
       
   414         browserFuncs.invalidaterect = (NPN_InvalidateRectProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRect);
       
   415         browserFuncs.invalidateregion = (NPN_InvalidateRegionProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_InvalidateRegion);
       
   416         browserFuncs.forceredraw = (NPN_ForceRedrawProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_ForceRedraw);
       
   417         browserFuncs.getJavaEnv = (NPN_GetJavaEnvProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaEnv);
       
   418         browserFuncs.getJavaPeer = (NPN_GetJavaPeerProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_GetJavaPeer);
       
   419         browserFuncs.pushpopupsenabledstate = (NPN_PushPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PushPopupsEnabledState);
       
   420         browserFuncs.poppopupsenabledstate = (NPN_PopPopupsEnabledStateProcPtr)tVectorForFunctionPointer((FunctionPointer)NPN_PopPopupsEnabledState);
       
   421         
       
   422         browserFuncs.releasevariantvalue = (NPN_ReleaseVariantValueProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseVariantValue);
       
   423         browserFuncs.getstringidentifier = (NPN_GetStringIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifier);
       
   424         browserFuncs.getstringidentifiers = (NPN_GetStringIdentifiersProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetStringIdentifiers);
       
   425         browserFuncs.getintidentifier = (NPN_GetIntIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetIntIdentifier);
       
   426         browserFuncs.identifierisstring = (NPN_IdentifierIsStringProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_IdentifierIsString);
       
   427         browserFuncs.utf8fromidentifier = (NPN_UTF8FromIdentifierProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_UTF8FromIdentifier);
       
   428         browserFuncs.createobject = (NPN_CreateObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_CreateObject);
       
   429         browserFuncs.retainobject = (NPN_RetainObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RetainObject);
       
   430         browserFuncs.releaseobject = (NPN_ReleaseObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseObject);
       
   431         browserFuncs.invoke = (NPN_InvokeProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Invoke);
       
   432         browserFuncs.invokeDefault = (NPN_InvokeDefaultProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_InvokeDefault);
       
   433         browserFuncs.evaluate = (NPN_EvaluateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Evaluate);
       
   434         browserFuncs.getproperty = (NPN_GetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetProperty);
       
   435         browserFuncs.setproperty = (NPN_SetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetProperty);
       
   436         browserFuncs.removeproperty = (NPN_RemovePropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RemoveProperty);
       
   437         browserFuncs.setexception = (NPN_SetExceptionProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetException);
       
   438         browserFuncs.enumerate = (NPN_EnumerateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Enumerate);
       
   439         
       
   440         [self _applyDjVuWorkaround];
       
   441         
       
   442 #if !LOG_DISABLED
       
   443         CFAbsoluteTime mainStart = CFAbsoluteTimeGetCurrent();
       
   444 #endif
       
   445         LOG(Plugins, "%f main timing started", mainStart);
       
   446         NPP_ShutdownProcPtr shutdownFunction;
       
   447         npErr = pluginMainFunc(&browserFuncs, &pluginFuncs, &shutdownFunction);
       
   448         NPP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction);
       
   449         if (!isBundle)
       
   450             // Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case.
       
   451             free(pluginMainFunc);
       
   452         
       
   453         // Workaround for 3270576. The RealPlayer plug-in fails to load if its preference file is out of date.
       
   454         // Launch the RealPlayer application to refresh the file.
       
   455         if (npErr != NPERR_NO_ERROR) {
       
   456             if (npErr == NPERR_MODULE_LOAD_FAILED_ERROR && [[self filename] isEqualToString:RealPlayerPluginFilename])
       
   457                 [self launchRealPlayer];
       
   458             goto abort;
       
   459         }
       
   460 #if !LOG_DISABLED
       
   461         currentTime = CFAbsoluteTimeGetCurrent();
       
   462         duration = currentTime - mainStart;
       
   463 #endif
       
   464         LOG(Plugins, "%f main took %f seconds", currentTime, duration);
       
   465         
       
   466         pluginSize = pluginFuncs.size;
       
   467         pluginVersion = pluginFuncs.version;
       
   468         LOG(Plugins, "pluginMainFunc: %d, size=%d, version=%d", npErr, pluginSize, pluginVersion);
       
   469         
       
   470         NPP_New = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp);
       
   471         NPP_Destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy);
       
   472         NPP_SetWindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow);
       
   473         NPP_NewStream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream);
       
   474         NPP_DestroyStream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream);
       
   475         NPP_StreamAsFile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile);
       
   476         NPP_WriteReady = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready);
       
   477         NPP_Write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write);
       
   478         NPP_Print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print);
       
   479         NPP_HandleEvent = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event);
       
   480         NPP_URLNotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify);
       
   481         NPP_GetValue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue);
       
   482         NPP_SetValue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue);
       
   483 
       
   484         // LiveConnect support
       
   485         NPP_GetJavaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass);
       
   486         if (NPP_GetJavaClass) {
       
   487             LOG(LiveConnect, "%@:  CFM entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
       
   488         } else {
       
   489             LOG(LiveConnect, "%@:  no entry point for NPP_GetJavaClass", [self name]);
       
   490         }
       
   491 
       
   492     } else {
       
   493 
       
   494 #endif
       
   495 
       
   496         // no function pointer conversion necessary for Mach-O
       
   497         browserFuncs.version = NP_VERSION_MINOR;
       
   498         browserFuncs.size = sizeof(NPNetscapeFuncs);
       
   499         browserFuncs.geturl = NPN_GetURL;
       
   500         browserFuncs.posturl = NPN_PostURL;
       
   501         browserFuncs.requestread = NPN_RequestRead;
       
   502         browserFuncs.newstream = NPN_NewStream;
       
   503         browserFuncs.write = NPN_Write;
       
   504         browserFuncs.destroystream = NPN_DestroyStream;
       
   505         browserFuncs.status = NPN_Status;
       
   506         browserFuncs.uagent = NPN_UserAgent;
       
   507         browserFuncs.memalloc = NPN_MemAlloc;
       
   508         browserFuncs.memfree = NPN_MemFree;
       
   509         browserFuncs.memflush = NPN_MemFlush;
       
   510         browserFuncs.reloadplugins = NPN_ReloadPlugins;
       
   511         browserFuncs.geturlnotify = NPN_GetURLNotify;
       
   512         browserFuncs.posturlnotify = NPN_PostURLNotify;
       
   513         browserFuncs.getvalue = NPN_GetValue;
       
   514         browserFuncs.setvalue = NPN_SetValue;
       
   515         browserFuncs.invalidaterect = NPN_InvalidateRect;
       
   516         browserFuncs.invalidateregion = NPN_InvalidateRegion;
       
   517         browserFuncs.forceredraw = NPN_ForceRedraw;
       
   518         browserFuncs.getJavaEnv = NPN_GetJavaEnv;
       
   519         browserFuncs.getJavaPeer = NPN_GetJavaPeer;
       
   520         browserFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
       
   521         browserFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
       
   522         
       
   523         browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue;
       
   524         browserFuncs.getstringidentifier = _NPN_GetStringIdentifier;
       
   525         browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers;
       
   526         browserFuncs.getintidentifier = _NPN_GetIntIdentifier;
       
   527         browserFuncs.identifierisstring = _NPN_IdentifierIsString;
       
   528         browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier;
       
   529         browserFuncs.createobject = _NPN_CreateObject;
       
   530         browserFuncs.retainobject = _NPN_RetainObject;
       
   531         browserFuncs.releaseobject = _NPN_ReleaseObject;
       
   532         browserFuncs.invoke = _NPN_Invoke;
       
   533         browserFuncs.invokeDefault = _NPN_InvokeDefault;
       
   534         browserFuncs.evaluate = _NPN_Evaluate;
       
   535         browserFuncs.getproperty = _NPN_GetProperty;
       
   536         browserFuncs.setproperty = _NPN_SetProperty;
       
   537         browserFuncs.removeproperty = _NPN_RemoveProperty;
       
   538         browserFuncs.setexception = _NPN_SetException;
       
   539         browserFuncs.enumerate = _NPN_Enumerate;
       
   540 
       
   541         [self _applyDjVuWorkaround];
       
   542 
       
   543 #if !LOG_DISABLED
       
   544         CFAbsoluteTime initializeStart = CFAbsoluteTimeGetCurrent();
       
   545 #endif
       
   546         LOG(Plugins, "%f NP_Initialize timing started", initializeStart);
       
   547         npErr = NP_Initialize(&browserFuncs);
       
   548         if (npErr != NPERR_NO_ERROR)
       
   549             goto abort;
       
   550 #if !LOG_DISABLED
       
   551         currentTime = CFAbsoluteTimeGetCurrent();
       
   552         duration = currentTime - initializeStart;
       
   553 #endif
       
   554         LOG(Plugins, "%f NP_Initialize took %f seconds", currentTime, duration);
       
   555 
       
   556         npErr = NP_GetEntryPoints(&pluginFuncs);
       
   557         if (npErr != NPERR_NO_ERROR)
       
   558             goto abort;
       
   559         
       
   560         pluginSize = pluginFuncs.size;
       
   561         pluginVersion = pluginFuncs.version;
       
   562         
       
   563         NPP_New = pluginFuncs.newp;
       
   564         NPP_Destroy = pluginFuncs.destroy;
       
   565         NPP_SetWindow = pluginFuncs.setwindow;
       
   566         NPP_NewStream = pluginFuncs.newstream;
       
   567         NPP_DestroyStream = pluginFuncs.destroystream;
       
   568         NPP_StreamAsFile = pluginFuncs.asfile;
       
   569         NPP_WriteReady = pluginFuncs.writeready;
       
   570         NPP_Write = pluginFuncs.write;
       
   571         NPP_Print = pluginFuncs.print;
       
   572         NPP_HandleEvent = pluginFuncs.event;
       
   573         NPP_URLNotify = pluginFuncs.urlnotify;
       
   574         NPP_GetValue = pluginFuncs.getvalue;
       
   575         NPP_SetValue = pluginFuncs.setvalue;
       
   576 
       
   577         // LiveConnect support
       
   578         NPP_GetJavaClass = pluginFuncs.javaClass;
       
   579         if (NPP_GetJavaClass){
       
   580             LOG(LiveConnect, "%@:  mach-o entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
       
   581         } else {
       
   582             LOG(LiveConnect, "%@:  no entry point for NPP_GetJavaClass", [self name]);
       
   583         }
       
   584 
       
   585 #ifdef SUPPORT_CFM
       
   586     }
       
   587 #endif
       
   588 
       
   589 #if !LOG_DISABLED
       
   590     currentTime = CFAbsoluteTimeGetCurrent();
       
   591     duration = currentTime - start;
       
   592 #endif
       
   593     LOG(Plugins, "%f Total load time: %f seconds", currentTime, duration);
       
   594 
       
   595     return [super load];
       
   596 
       
   597 abort:
       
   598     [self _unloadWithShutdown:NO];
       
   599     return NO;
       
   600 }
       
   601 
       
   602 - (NPP_SetWindowProcPtr)NPP_SetWindow
       
   603 {
       
   604     return NPP_SetWindow;
       
   605 }
       
   606 
       
   607 - (NPP_NewProcPtr)NPP_New
       
   608 {
       
   609     return NPP_New;
       
   610 }
       
   611 
       
   612 - (NPP_DestroyProcPtr)NPP_Destroy
       
   613 {
       
   614     return NPP_Destroy;
       
   615 }
       
   616 
       
   617 - (NPP_NewStreamProcPtr)NPP_NewStream
       
   618 {
       
   619     return NPP_NewStream;
       
   620 }
       
   621 
       
   622 - (NPP_StreamAsFileProcPtr)NPP_StreamAsFile
       
   623 {
       
   624     return NPP_StreamAsFile;
       
   625 }
       
   626 - (NPP_DestroyStreamProcPtr)NPP_DestroyStream
       
   627 {
       
   628     return NPP_DestroyStream;
       
   629 }
       
   630 
       
   631 - (NPP_WriteReadyProcPtr)NPP_WriteReady
       
   632 {
       
   633     return NPP_WriteReady;
       
   634 }
       
   635 - (NPP_WriteProcPtr)NPP_Write
       
   636 {
       
   637     return NPP_Write;
       
   638 }
       
   639 
       
   640 - (NPP_HandleEventProcPtr)NPP_HandleEvent
       
   641 {
       
   642     return NPP_HandleEvent;
       
   643 }
       
   644 
       
   645 -(NPP_URLNotifyProcPtr)NPP_URLNotify
       
   646 {
       
   647     return NPP_URLNotify;
       
   648 }
       
   649 
       
   650 -(NPP_GetValueProcPtr)NPP_GetValue
       
   651 {
       
   652     return NPP_GetValue;
       
   653 }
       
   654 
       
   655 -(NPP_SetValueProcPtr)NPP_SetValue
       
   656 {
       
   657     return NPP_SetValue;
       
   658 }
       
   659 
       
   660 -(NPP_PrintProcPtr)NPP_Print
       
   661 {
       
   662     return NPP_Print;
       
   663 }
       
   664 
       
   665 - (void)wasRemovedFromPluginDatabase:(WebPluginDatabase *)database
       
   666 {
       
   667     [super wasRemovedFromPluginDatabase:database];
       
   668     
       
   669     // Unload when removed from final plug-in database
       
   670     if ([pluginDatabases count] == 0)
       
   671         [self _unloadWithShutdown:YES];
       
   672 }
       
   673 
       
   674 - (void)open
       
   675 {
       
   676     instanceCount++;
       
   677     
       
   678     // Handle the case where all instances close a plug-in package, but another
       
   679     // instance opens the package before it is unloaded (which only happens when
       
   680     // the plug-in database is refreshed)
       
   681     needsUnload = NO;
       
   682     
       
   683     if (!isLoaded) {
       
   684         // Should load when the first instance opens the plug-in package
       
   685         ASSERT(instanceCount == 1);
       
   686         [self load];
       
   687     }
       
   688 }
       
   689 
       
   690 - (void)close
       
   691 {
       
   692     ASSERT(instanceCount > 0);
       
   693     instanceCount--;
       
   694     if (instanceCount == 0 && needsUnload)
       
   695         [self _unloadWithShutdown:YES];
       
   696 }
       
   697 
       
   698 @end
       
   699 
       
   700 #ifdef SUPPORT_CFM
       
   701 
       
   702 // function pointer converters
       
   703 
       
   704 FunctionPointer functionPointerForTVector(TransitionVector tvp)
       
   705 {
       
   706     const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420};
       
   707     uint32 *newGlue = NULL;
       
   708 
       
   709     if (tvp != NULL) {
       
   710         newGlue = (uint32 *)malloc(sizeof(temp));
       
   711         if (newGlue != NULL) {
       
   712             unsigned i;
       
   713             for (i = 0; i < 6; i++) newGlue[i] = temp[i];
       
   714             newGlue[0] |= ((uintptr_t)tvp >> 16);
       
   715             newGlue[1] |= ((uintptr_t)tvp & 0xFFFF);
       
   716             MakeDataExecutable(newGlue, sizeof(temp));
       
   717         }
       
   718     }
       
   719     
       
   720     return (FunctionPointer)newGlue;
       
   721 }
       
   722 
       
   723 TransitionVector tVectorForFunctionPointer(FunctionPointer fp)
       
   724 {
       
   725     FunctionPointer *newGlue = NULL;
       
   726     if (fp != NULL) {
       
   727         newGlue = (FunctionPointer *)malloc(2 * sizeof(FunctionPointer));
       
   728         if (newGlue != NULL) {
       
   729             newGlue[0] = fp;
       
   730             newGlue[1] = NULL;
       
   731         }
       
   732     }
       
   733     return (TransitionVector)newGlue;
       
   734 }
       
   735 
       
   736 #endif
       
   737 
       
   738 @implementation WebNetscapePluginPackage (Internal)
       
   739 
       
   740 - (void)_unloadWithShutdown:(BOOL)shutdown
       
   741 {
       
   742     if (!isLoaded)
       
   743         return;
       
   744     
       
   745     LOG(Plugins, "Unloading %@...", name);
       
   746 
       
   747     // Cannot unload a plug-in package while an instance is still using it
       
   748     if (instanceCount > 0) {
       
   749         needsUnload = YES;
       
   750         return;
       
   751     }
       
   752 
       
   753     if (shutdown && NPP_Shutdown)
       
   754         NPP_Shutdown();
       
   755 
       
   756     if (resourceRef != -1)
       
   757         [self closeResourceFile:resourceRef];
       
   758 
       
   759 #ifdef SUPPORT_CFM
       
   760     if (isBundle)
       
   761 #endif
       
   762         CFBundleUnloadExecutable(cfBundle);
       
   763 #ifdef SUPPORT_CFM
       
   764     else
       
   765         WebCloseConnection(&connID);
       
   766 #endif
       
   767 
       
   768     LOG(Plugins, "Plugin Unloaded");
       
   769     isLoaded = NO;
       
   770 }
       
   771 
       
   772 @end
       
   773 #endif