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 44using namespace WebKit; 45#endif 46 47using namespace WebCore; 48 49#ifdef SUPPORT_CFM 50typedef void (* FunctionPointer)(void); 51typedef void (* TransitionVector)(void); 52static FunctionPointer functionPointerForTVector(TransitionVector); 53static 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 717FunctionPointer 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 736TransitionVector 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 783