зеркало из https://github.com/mozilla/pjs.git
Bug 509130 - Crashes [@objc_msgSend | IdleTimerVector ] (OS X) caused by WebKit used by Carbon plugin (DivXBrowserPlugin). r=josh
This commit is contained in:
Родитель
543c64358a
Коммит
fbbd483d41
|
@ -69,6 +69,79 @@ extern PRUint32 gLastModifierState;
|
|||
// defined in nsCocoaWindow.mm
|
||||
extern PRInt32 gXULModalLevel;
|
||||
|
||||
#ifndef __LP64__
|
||||
#include <dlfcn.h>
|
||||
|
||||
void (*WebKit_WebInitForCarbon)() = NULL;
|
||||
|
||||
// Plugins may exist that use the WebKit framework. Those that are
|
||||
// Carbon-based need to call WebKit's WebInitForCarbon() method. There
|
||||
// currently appears to be only one Carbon WebKit plugin --
|
||||
// DivXBrowserPlugin (included with the DivX Web Player,
|
||||
// http://www.divx.com/en/downloads/divx/mac). See bug 509130.
|
||||
//
|
||||
// The source-code for WebInitForCarbon() is in the WebKit source tree's
|
||||
// WebKit/mac/Carbon/CarbonUtils.mm file. Among other things it installs
|
||||
// an idle timer on the main event loop, whose target is the PoolCleaner()
|
||||
// function (also in CarbonUtils.mm). WebInitForCarbon() allocates an
|
||||
// NSAutoreleasePool object which it stores in the global sPool variable.
|
||||
// PoolCleaner() periodically releases/drains sPool and creates another
|
||||
// NSAutoreleasePool object to take its place. The intention is to ensure
|
||||
// an autorelease pool is in place for whatever Objective-C code may be
|
||||
// called by WebKit code, and that it periodically gets "cleaned". But
|
||||
// PoolCleaner()'s periodic cleaning has a very bad effect on us -- it
|
||||
// causes objects to be deleted prematurely, so that attempts to access them
|
||||
// cause crashes. This is probably because, when WebInitForCarbon() is
|
||||
// called from a plugin in a Cocoa browser, one or more autorelease pools
|
||||
// are already in place. So, other things being equal, PoolCleaner() should
|
||||
// have a similar effect on any Cocoa app that hosts a Carbon WebKit plugin.
|
||||
//
|
||||
// PoolCleaner() only "works" if the autorelease pool count (returned by
|
||||
// WKGetNSAutoreleasePoolCount(), stored in numPools) is the same as when
|
||||
// sPool was last set. So we can permanently disable it by ensuring that,
|
||||
// when sPool is first set, numPools gets set to a value that it will never
|
||||
// have again until just after the app shell is destroyed. To accomplish
|
||||
// this we need to call WebInitForCarbon() ourselves, before any plugin
|
||||
// calls it (subsequent calls to WebInitForCarbon() (after the first) are
|
||||
// no-ops): We release all of the app shell's autorelease pools (including
|
||||
// mMainPool) just before calling WebInitForCarbon(), then restore mMainPool
|
||||
// just afterwards (before the idle timer has time to call PoolCleaner()).
|
||||
//
|
||||
// WKGetNSAutoreleasePoolCount() only works on OS X 10.5 and below -- not on
|
||||
// OS X 10.6 and above. So PoolCleaner() is always disabled on 10.6 and
|
||||
// above -- we needn't do anything to explicitly disable it.
|
||||
//
|
||||
// WKGetNSAutoreleasePoolCount() is a thin wrapper around the following code:
|
||||
//
|
||||
// unsigned count = NSPushAutoreleasePool(0);
|
||||
// NSPopAutoreleasePool(count);
|
||||
// return count;
|
||||
//
|
||||
// NSPushAutoreleasePool() and NSPopAutoreleasePool() are undocumented
|
||||
// functions from the Foundation framework. On OS X 10.5.X and below their
|
||||
// declarations are (as best I can tell) as follows. ('capacity' is
|
||||
// presumably the initial capacity, in number of items, of the autorelease
|
||||
// pool to be created.)
|
||||
//
|
||||
// unsigned NSPushAutoreleasePool(unsigned capacity);
|
||||
// void NSPopAutoreleasePool(unsigned offset);
|
||||
//
|
||||
// But as of OS X 10.6 these functions appear to have changed as follows:
|
||||
//
|
||||
// AutoreleasePool *NSPushAutoreleasePool(unsigned capacity);
|
||||
// void NSPopAutoreleasePool(AutoreleasePool *aPool);
|
||||
static void InitCarbonWebKit()
|
||||
{
|
||||
if (!WebKit_WebInitForCarbon) {
|
||||
void* webkithandle = dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", RTLD_LAZY);
|
||||
if (webkithandle)
|
||||
*(void **)(&WebKit_WebInitForCarbon) = dlsym(webkithandle, "WebInitForCarbon");
|
||||
}
|
||||
if (WebKit_WebInitForCarbon)
|
||||
WebKit_WebInitForCarbon();
|
||||
}
|
||||
#endif // __LP64__
|
||||
|
||||
static PRBool gAppShellMethodsSwizzled = PR_FALSE;
|
||||
// List of current Cocoa app-modal windows (nested if more than one).
|
||||
nsCocoaAppModalWindowList *gCocoaAppModalWindowList = NULL;
|
||||
|
@ -363,6 +436,14 @@ nsAppShell::Init()
|
|||
|
||||
[localPool release];
|
||||
|
||||
#ifndef __LP64__
|
||||
if (!nsToolkit::OnSnowLeopardOrLater()) {
|
||||
[mMainPool release];
|
||||
InitCarbonWebKit();
|
||||
mMainPool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
|
Загрузка…
Ссылка в новой задаче