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