📄 webnetscapepluginpackage.mm
字号:
/* * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#if ENABLE(NETSCAPE_PLUGIN_API)#import "WebNetscapePluginPackage.h"#import "WebKitLogging.h"#import "WebKitNSStringExtras.h"#import "WebNSObjectExtras.h"#import "WebNetscapeDeprecatedFunctions.h"#import <WebCore/npruntime_impl.h>#if USE(PLUGIN_HOST_PROCESS)#import "NetscapePluginHostManager.h"using namespace WebKit;#endif#ifdef SUPPORT_CFMtypedef void (* FunctionPointer)(void);typedef void (* TransitionVector)(void);static FunctionPointer functionPointerForTVector(TransitionVector);static TransitionVector tVectorForFunctionPointer(FunctionPointer);#endif#define PluginNameOrDescriptionStringNumber 126#define MIMEDescriptionStringNumber 127#define MIMEListStringStringNumber 128#define RealPlayerAppIndentifier @"com.RealNetworks.RealOne Player"#define RealPlayerPluginFilename @"RealPlayer Plugin"@interface WebNetscapePluginPackage (Internal)- (void)_unloadWithShutdown:(BOOL)shutdown;@end@implementation WebNetscapePluginPackage#ifndef __LP64__+ (void)initialize{ // The Shockwave plugin requires a valid file in CurApRefNum. // But it doesn't seem to matter what file it is. // If we're called inside a Cocoa application which won't have a // CurApRefNum, we set it to point to the system resource file. // Call CurResFile before testing the result of WebLMGetCurApRefNum. // If we are called before the bundle resource map has been opened // for a Carbon application (or a Cocoa app with Resource Manager // resources) we *do not* want to set CurApRefNum to point at the // system resource file. CurResFile triggers Resource Manager lazy // initialization, and will open the bundle resource map as necessary. CurResFile(); if (WebLMGetCurApRefNum() == -1) { // To get the refNum for the system resource file, we have to do // UseResFile(kSystemResFile) and then look at CurResFile(). short savedCurResFile = CurResFile(); UseResFile(kSystemResFile); WebLMSetCurApRefNum(CurResFile()); UseResFile(savedCurResFile); }}#endif- (ResFileRefNum)openResourceFile{#ifdef SUPPORT_CFM if (!isBundle) { FSRef fref; OSErr err = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &fref, NULL); if (err != noErr) return -1; return FSOpenResFile(&fref, fsRdPerm); }#endif return CFBundleOpenBundleResourceMap(cfBundle);}- (void)closeResourceFile:(ResFileRefNum)resRef{#ifdef SUPPORT_CFM if (!isBundle) { CloseResFile(resRef); return; }#endif CFBundleCloseBundleResourceMap(cfBundle, resRef);}- (NSString *)stringForStringListID:(SInt16)stringListID andIndex:(SInt16)index{ // Get resource, and dereference the handle. Handle stringHandle = Get1Resource('STR#', stringListID); if (stringHandle == NULL) { return nil; } unsigned char *p = (unsigned char *)*stringHandle; if (!p) return nil; // Check the index against the length of the string list, then skip the length. if (index < 1 || index > *(SInt16 *)p) return nil; p += sizeof(SInt16); // Skip any strings that come before the one we are looking for. while (--index) p += 1 + *p; // Convert the one we found into an NSString. return [[[NSString alloc] initWithBytes:(p + 1) length:*p encoding:[NSString _web_encodingForResource:stringHandle]] autorelease];}- (BOOL)getPluginInfoFromResources{ SInt16 resRef = [self openResourceFile]; if (resRef == -1) return NO; UseResFile(resRef); if (ResError() != noErr) return NO; NSString *MIME, *extensionsList, *description; NSArray *extensions; unsigned i; NSMutableDictionary *MIMEToExtensionsDictionary = [NSMutableDictionary dictionary]; NSMutableDictionary *MIMEToDescriptionDictionary = [NSMutableDictionary dictionary]; for (i=1; 1; i+=2) { MIME = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i] lowercaseString]; if (!MIME) break; extensionsList = [[self stringForStringListID:MIMEListStringStringNumber andIndex:i+1] lowercaseString]; if (extensionsList) { extensions = [extensionsList componentsSeparatedByString:@","]; [MIMEToExtensionsDictionary setObject:extensions forKey:MIME]; } else // DRM and WMP claim MIMEs without extensions. Use a @"" extension in this case. [MIMEToExtensionsDictionary setObject:[NSArray arrayWithObject:@""] forKey:MIME]; description = [self stringForStringListID:MIMEDescriptionStringNumber andIndex:[MIMEToExtensionsDictionary count]]; if (description) [MIMEToDescriptionDictionary setObject:description forKey:MIME]; else [MIMEToDescriptionDictionary setObject:@"" forKey:MIME]; } [self setMIMEToDescriptionDictionary:MIMEToDescriptionDictionary]; [self setMIMEToExtensionsDictionary:MIMEToExtensionsDictionary]; NSString *filename = [self filename]; description = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:1]; if (!description) description = filename; [self setPluginDescription:description]; NSString *theName = [self stringForStringListID:PluginNameOrDescriptionStringNumber andIndex:2]; if (!theName) theName = filename; [self setName:theName]; [self closeResourceFile:resRef]; return YES;}- (BOOL)_initWithPath:(NSString *)pluginPath{ resourceRef = -1; OSType type = 0; if (bundle) { // Bundle CFBundleGetPackageInfo(cfBundle, &type, NULL);#ifdef SUPPORT_CFM isBundle = YES;#endif } else {#ifdef SUPPORT_CFM // Single-file plug-in with resource fork type = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileHFSTypeCode]; isBundle = NO; isCFM = YES;#else return NO;#endif } if (type != FOUR_CHAR_CODE('BRPL')) return NO; // Check if the executable is Mach-O or CFM. if (bundle) { NSFileHandle *executableFile = [NSFileHandle fileHandleForReadingAtPath:[bundle executablePath]]; NSData *data = [executableFile readDataOfLength:512]; [executableFile closeFile]; // Check the length of the data before calling memcmp. We think this fixes 3782543. if (data == nil || [data length] < 8) return NO; BOOL hasCFMHeader = memcmp([data bytes], "Joy!peff", 8) == 0;#ifdef SUPPORT_CFM isCFM = hasCFMHeader;#else if (hasCFMHeader) return NO;#endif#if USE(PLUGIN_HOST_PROCESS) NSArray *archs = [bundle executableArchitectures]; if ([archs containsObject:[NSNumber numberWithInteger:NSBundleExecutableArchitectureX86_64]]) pluginHostArchitecture = CPU_TYPE_X86_64; else if ([archs containsObject:[NSNumber numberWithInteger:NSBundleExecutableArchitectureI386]]) pluginHostArchitecture = CPU_TYPE_X86; else return NO;#else if (![self isNativeLibraryData:data]) return NO;#endif } if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources]) return NO; return YES;}- (id)initWithPath:(NSString *)pluginPath{ if (!(self = [super initWithPath:pluginPath])) return nil; // Initializing a plugin package can cause it to be loaded. If there was an error initializing the plugin package, // ensure that it is unloaded before deallocating it (WebBasePluginPackage requires & asserts this). if (![self _initWithPath:pluginPath]) { [self _unloadWithShutdown:YES]; [self release]; return nil; } return self;}- (WebExecutableType)executableType{#ifdef SUPPORT_CFM if (isCFM) return WebCFMExecutableType;#endif return WebMachOExecutableType;}#if USE(PLUGIN_HOST_PROCESS)- (cpu_type_t)pluginHostArchitecture{ return pluginHostArchitecture;}- (void)createPropertyListFile{ NetscapePluginHostManager::createPropertyListFile(self);}#endif- (void)launchRealPlayer{ CFURLRef appURL = NULL; OSStatus error = LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)RealPlayerAppIndentifier, NULL, NULL, &appURL); if (!error) { LSLaunchURLSpec URLSpec; bzero(&URLSpec, sizeof(URLSpec)); URLSpec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; URLSpec.appURL = appURL; LSOpenFromURLSpec(&URLSpec, NULL); CFRelease(appURL); }}- (void)_applyDjVuWorkaround{ if (!cfBundle) return; if ([(NSString *)CFBundleGetIdentifier(cfBundle) isEqualToString:@"com.lizardtech.NPDjVu"]) { // The DjVu plug-in will crash copying the vtable if it's too big so we cap it to // what the plug-in expects here. // size + version + 40 function pointers. browserFuncs.size = 2 + 2 + sizeof(void *) * 40; } }- (void)unload{ [self _unloadWithShutdown:YES];}- (BOOL)_tryLoad{ NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL; NP_InitializeFuncPtr NP_Initialize = NULL; NPError npErr;#ifdef SUPPORT_CFM MainFuncPtr pluginMainFunc = NULL;#endif#if !LOG_DISABLED CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); CFAbsoluteTime currentTime; CFAbsoluteTime duration;#endif LOG(Plugins, "%f Load timing started for: %@", start, [self name]); if (isLoaded) return YES; #ifdef SUPPORT_CFM if (isBundle) {#endif if (!CFBundleLoadExecutable(cfBundle)) return NO;#if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - start;#endif LOG(Plugins, "%f CFBundleLoadExecutable took %f seconds", currentTime, duration); isLoaded = YES; #ifdef SUPPORT_CFM if (isCFM) { pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") ); if (!pluginMainFunc) return NO; } else {#endif NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize")); NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints")); NP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -