|
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 |