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