summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/Plugins/WebPluginController.mm
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-13 16:23:25 +0100
committerBen Murdoch <benm@google.com>2011-05-16 11:35:02 +0100
commit65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch)
treef478babb801e720de7bfaee23443ffe029f58731 /WebKit/mac/Plugins/WebPluginController.mm
parent47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff)
downloadexternal_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'WebKit/mac/Plugins/WebPluginController.mm')
-rw-r--r--WebKit/mac/Plugins/WebPluginController.mm601
1 files changed, 0 insertions, 601 deletions
diff --git a/WebKit/mac/Plugins/WebPluginController.mm b/WebKit/mac/Plugins/WebPluginController.mm
deleted file mode 100644
index c802d4c..0000000
--- a/WebKit/mac/Plugins/WebPluginController.mm
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright (C) 2005, 2006 Apple Computer, 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.
- */
-
-
-#import "WebPluginController.h"
-
-#import "DOMNodeInternal.h"
-#import "WebDataSourceInternal.h"
-#import "WebFrameInternal.h"
-#import "WebFrameView.h"
-#import "WebHTMLViewPrivate.h"
-#import "WebKitErrorsPrivate.h"
-#import "WebKitLogging.h"
-#import "WebNSObjectExtras.h"
-#import "WebNSURLExtras.h"
-#import "WebNSViewExtras.h"
-#import "WebPlugin.h"
-#import "WebPluginContainer.h"
-#import "WebPluginContainerCheck.h"
-#import "WebPluginPackage.h"
-#import "WebPluginPrivate.h"
-#import "WebPluginViewFactory.h"
-#import "WebUIDelegate.h"
-#import "WebViewInternal.h"
-#import <Foundation/NSURLRequest.h>
-#import <WebCore/DocumentLoader.h>
-#import <WebCore/Frame.h>
-#import <WebCore/FrameLoader.h>
-#import <WebCore/HTMLMediaElement.h>
-#import <WebCore/HTMLNames.h>
-#import <WebCore/MediaPlayerProxy.h>
-#import <WebCore/PlatformString.h>
-#import <WebCore/ResourceRequest.h>
-#import <WebCore/ScriptController.h>
-#import <WebCore/WebCoreURLResponse.h>
-#import <objc/objc-runtime.h>
-#import <runtime/JSLock.h>
-
-using namespace WebCore;
-using namespace HTMLNames;
-
-@interface NSView (PluginSecrets)
-- (void)setContainingWindow:(NSWindow *)w;
-@end
-
-// For compatibility only.
-@interface NSObject (OldPluginAPI)
-+ (NSView *)pluginViewWithArguments:(NSDictionary *)arguments;
-@end
-
-@interface NSView (OldPluginAPI)
-- (void)pluginInitialize;
-- (void)pluginStart;
-- (void)pluginStop;
-- (void)pluginDestroy;
-@end
-
-static bool isKindOfClass(id, NSString* className);
-static void installFlip4MacPlugInWorkaroundIfNecessary();
-
-
-static NSMutableSet *pluginViews = nil;
-
-@implementation WebPluginController
-
-+ (NSView *)plugInViewWithArguments:(NSDictionary *)arguments fromPluginPackage:(WebPluginPackage *)pluginPackage
-{
- [pluginPackage load];
- Class viewFactory = [pluginPackage viewFactory];
-
- NSView *view = nil;
-
- if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- view = [viewFactory plugInViewWithArguments:arguments];
- } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- view = [viewFactory pluginViewWithArguments:arguments];
- }
-
- if (view == nil) {
- return nil;
- }
-
- if (pluginViews == nil) {
- pluginViews = [[NSMutableSet alloc] init];
- }
- [pluginViews addObject:view];
-
- return view;
-}
-
-+ (BOOL)isPlugInView:(NSView *)view
-{
- return [pluginViews containsObject:view];
-}
-
-- (id)initWithDocumentView:(NSView *)view
-{
- [super init];
- _documentView = view;
- _views = [[NSMutableArray alloc] init];
- _checksInProgress = (NSMutableSet *)CFMakeCollectable(CFSetCreateMutable(NULL, 0, NULL));
- return self;
-}
-
-- (void)setDataSource:(WebDataSource *)dataSource
-{
- _dataSource = dataSource;
-}
-
-- (void)dealloc
-{
- [_views release];
- [_checksInProgress release];
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- [_viewsNotInDocument release];
-#endif
- [super dealloc];
-}
-
-- (void)stopOnePlugin:(NSView *)view
-{
- if ([view respondsToSelector:@selector(webPlugInStop)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view webPlugInStop];
- } else if ([view respondsToSelector:@selector(pluginStop)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view pluginStop];
- }
-}
-
-- (void)destroyOnePlugin:(NSView *)view
-{
- if ([view respondsToSelector:@selector(webPlugInDestroy)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view webPlugInDestroy];
- } else if ([view respondsToSelector:@selector(pluginDestroy)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view pluginDestroy];
- }
-}
-
-- (void)startAllPlugins
-{
- if (_started)
- return;
-
- if ([_views count] > 0)
- LOG(Plugins, "starting WebKit plugins : %@", [_views description]);
-
- int count = [_views count];
- for (int i = 0; i < count; i++) {
- id aView = [_views objectAtIndex:i];
- if ([aView respondsToSelector:@selector(webPlugInStart)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [aView webPlugInStart];
- } else if ([aView respondsToSelector:@selector(pluginStart)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [aView pluginStart];
- }
- }
- _started = YES;
-}
-
-- (void)stopAllPlugins
-{
- if (!_started)
- return;
-
- if ([_views count] > 0) {
- LOG(Plugins, "stopping WebKit plugins: %@", [_views description]);
- }
-
- int viewsCount = [_views count];
- for (int i = 0; i < viewsCount; i++)
- [self stopOnePlugin:[_views objectAtIndex:i]];
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- int viewsNotInDocumentCount = [_viewsNotInDocument count];
- for (int i = 0; i < viewsNotInDocumentCount; i++)
- [self stopOnePlugin:[_viewsNotInDocument objectAtIndex:i]];
-#endif
-
- _started = NO;
-}
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-- (void)pluginViewCreated:(NSView *)view
-{
- if (!_viewsNotInDocument)
- _viewsNotInDocument= [[NSMutableArray alloc] init];
- if (![_viewsNotInDocument containsObject:view])
- [_viewsNotInDocument addObject:view];
-}
-
-+ (void)pluginViewHidden:(NSView *)view
-{
- [pluginViews removeObject:view];
-}
-#endif
-
-- (void)addPlugin:(NSView *)view
-{
- if (!_documentView) {
- LOG_ERROR("can't add a plug-in to a defunct WebPluginController");
- return;
- }
-
- if (![_views containsObject:view]) {
- [_views addObject:view];
- [[_documentView _webView] addPluginInstanceView:view];
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- if ([_viewsNotInDocument containsObject:view])
- [_viewsNotInDocument removeObject:view];
-#endif
-
- BOOL oldDefersCallbacks = [[self webView] defersCallbacks];
- if (!oldDefersCallbacks)
- [[self webView] setDefersCallbacks:YES];
-
- if (isKindOfClass(view, @"WmvPlugin"))
- installFlip4MacPlugInWorkaroundIfNecessary();
-
- LOG(Plugins, "initializing plug-in %@", view);
- if ([view respondsToSelector:@selector(webPlugInInitialize)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view webPlugInInitialize];
- } else if ([view respondsToSelector:@selector(pluginInitialize)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view pluginInitialize];
- }
-
- if (!oldDefersCallbacks)
- [[self webView] setDefersCallbacks:NO];
-
- if (_started) {
- LOG(Plugins, "starting plug-in %@", view);
- if ([view respondsToSelector:@selector(webPlugInStart)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view webPlugInStart];
- } else if ([view respondsToSelector:@selector(pluginStart)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view pluginStart];
- }
-
- if ([view respondsToSelector:@selector(setContainingWindow:)]) {
- JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
- [view setContainingWindow:[_documentView window]];
- }
- }
- }
-}
-
-- (void)destroyPlugin:(NSView *)view
-{
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- if ([_views containsObject:view] || [_viewsNotInDocument containsObject:view]) {
-#else
- if ([_views containsObject:view]) {
-#endif
- if (_started)
- [self stopOnePlugin:view];
- [self destroyOnePlugin:view];
-
-#if ENABLE(NETSCAPE_PLUGIN_API)
- if (Frame* frame = core([self webFrame]))
- frame->script()->cleanupScriptObjectsForPlugin(self);
-#endif
-
- [pluginViews removeObject:view];
- [[_documentView _webView] removePluginInstanceView:view];
- [_views removeObject:view];
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- [_viewsNotInDocument removeObject:view];
-#endif
- }
-}
-
-- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)checkIdentifier
-{
- [checkIdentifier cancel];
- [_checksInProgress removeObject:checkIdentifier];
-}
-
-static void cancelOutstandingCheck(const void *item, void *context)
-{
- [(id)item cancel];
-}
-
-- (void)_cancelOutstandingChecks
-{
- if (_checksInProgress) {
- CFSetApplyFunction((CFSetRef)_checksInProgress, cancelOutstandingCheck, NULL);
- [_checksInProgress release];
- _checksInProgress = nil;
- }
-}
-
-- (void)destroyAllPlugins
-{
- [self stopAllPlugins];
-
- if ([_views count] > 0) {
- LOG(Plugins, "destroying WebKit plugins: %@", [_views description]);
- }
-
- [self _cancelOutstandingChecks];
-
- int viewsCount = [_views count];
- for (int i = 0; i < viewsCount; i++) {
- id aView = [_views objectAtIndex:i];
- [self destroyOnePlugin:aView];
-
-#if ENABLE(NETSCAPE_PLUGIN_API)
- if (Frame* frame = core([self webFrame]))
- frame->script()->cleanupScriptObjectsForPlugin(self);
-#endif
-
- [pluginViews removeObject:aView];
- [[_documentView _webView] removePluginInstanceView:aView];
- }
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- int viewsNotInDocumentCount = [_viewsNotInDocument count];
- for (int i = 0; i < viewsNotInDocumentCount; i++)
- [self destroyOnePlugin:[_viewsNotInDocument objectAtIndex:i]];
-#endif
-
- [_views makeObjectsPerformSelector:@selector(removeFromSuperviewWithoutNeedingDisplay)];
- [_views release];
- _views = nil;
-
- _documentView = nil;
-}
-
-- (id)_webPluginContainerCheckIfAllowedToLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target resultObject:(id)obj selector:(SEL)selector
-{
- WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:request target:target resultObject:obj selector:selector controller:self contextInfo:nil];
- [_checksInProgress addObject:check];
- [check start];
-
- return check;
-}
-
-- (void)webPlugInContainerLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target
-{
- if (!request) {
- LOG_ERROR("nil URL passed");
- return;
- }
- if (!_documentView) {
- LOG_ERROR("could not load URL %@ because plug-in has already been destroyed", request);
- return;
- }
- WebFrame *frame = [_dataSource webFrame];
- if (!frame) {
- LOG_ERROR("could not load URL %@ because plug-in has already been stopped", request);
- return;
- }
- if (!target) {
- target = @"_top";
- }
- NSString *JSString = [[request URL] _webkit_scriptIfJavaScriptURL];
- if (JSString) {
- if ([frame findFrameNamed:target] != frame) {
- LOG_ERROR("JavaScript requests can only be made on the frame that contains the plug-in");
- return;
- }
- [frame _stringByEvaluatingJavaScriptFromString:JSString];
- } else {
- if (!request) {
- LOG_ERROR("could not load URL %@", [request URL]);
- return;
- }
- core(frame)->loader()->load(request, target, false);
- }
-}
-
-- (void)webPlugInContainerShowStatus:(NSString *)message
-{
- if (!message)
- message = @"";
-
- WebView *v = [_dataSource _webView];
- [[v _UIDelegateForwarder] webView:v setStatusText:message];
-}
-
-// For compatibility only.
-- (void)showStatus:(NSString *)message
-{
- [self webPlugInContainerShowStatus:message];
-}
-
-- (NSColor *)webPlugInContainerSelectionColor
-{
- bool primary = true;
- if (Frame* frame = core([self webFrame]))
- primary = frame->selection()->isFocusedAndActive();
- return primary ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
-}
-
-// For compatibility only.
-- (NSColor *)selectionColor
-{
- return [self webPlugInContainerSelectionColor];
-}
-
-- (WebFrame *)webFrame
-{
- return [_dataSource webFrame];
-}
-
-- (WebView *)webView
-{
- return [[self webFrame] webView];
-}
-
-- (NSString *)URLPolicyCheckReferrer
-{
- NSURL *responseURL = [[[[self webFrame] _dataSource] response] URL];
- ASSERT(responseURL);
- return [responseURL _web_originalDataAsString];
-}
-
-- (void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response
-{
- if ([pluginView respondsToSelector:@selector(webPlugInMainResourceDidReceiveResponse:)])
- [pluginView webPlugInMainResourceDidReceiveResponse:response];
- else {
- // Cancel the load since this plug-in does its own loading.
- // FIXME: See <rdar://problem/4258008> for a problem with this.
- NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad
- contentURL:[response URL]
- pluginPageURL:nil
- pluginName:nil // FIXME: Get this from somewhere
- MIMEType:[response MIMEType]];
- [_dataSource _documentLoader]->cancelMainResourceLoad(error);
- [error release];
- }
-}
-
-- (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
-{
- if ([pluginView respondsToSelector:@selector(webPlugInMainResourceDidReceiveData:)])
- [pluginView webPlugInMainResourceDidReceiveData:data];
-}
-
-- (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error
-{
- if ([pluginView respondsToSelector:@selector(webPlugInMainResourceDidFailWithError:)])
- [pluginView webPlugInMainResourceDidFailWithError:error];
-}
-
-- (void)pluginViewFinishedLoading:(NSView *)pluginView
-{
- if ([pluginView respondsToSelector:@selector(webPlugInMainResourceDidFinishLoading)])
- [pluginView webPlugInMainResourceDidFinishLoading];
-}
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-static WebCore::HTMLMediaElement* mediaProxyClient(DOMElement* element)
-{
- if (!element) {
- LOG_ERROR("nil element passed");
- return nil;
- }
-
- Element* node = core(element);
- if (!node || (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))) {
- LOG_ERROR("invalid media element passed");
- return nil;
- }
-
- return static_cast<WebCore::HTMLMediaElement*>(node);
-}
-
-- (void)_webPluginContainerSetMediaPlayerProxy:(WebMediaPlayerProxy *)proxy forElement:(DOMElement *)element
-{
- WebCore::HTMLMediaElement* client = mediaProxyClient(element);
- if (client)
- client->setMediaPlayerProxy(proxy);
-}
-
-- (void)_webPluginContainerPostMediaPlayerNotification:(int)notification forElement:(DOMElement *)element
-{
- WebCore::HTMLMediaElement* client = mediaProxyClient(element);
- if (client)
- client->deliverNotification((MediaPlayerProxyNotificationType)notification);
-}
-#endif
-
-@end
-
-static bool isKindOfClass(id object, NSString *className)
-{
- Class cls = NSClassFromString(className);
-
- if (!cls)
- return false;
-
- return [object isKindOfClass:cls];
-}
-
-
-// Existing versions of the Flip4Mac WebKit plug-in have an object lifetime bug related to an NSAlert that is
-// used to notify the user about updates to the plug-in. This bug can result in Safari crashing if the page
-// containing the plug-in navigates while the alert is displayed (<rdar://problem/7313430>).
-//
-// The gist of the bug is thus: Flip4Mac sets an instance of the TSUpdateCheck class as the modal delegate of the
-// NSAlert instance. This TSUpdateCheck instance itself has a delegate. The delegate is set to the WmvPlugin
-// instance which is the NSView subclass that is exposed to WebKit as the plug-in view. Since this relationship
-// is that of delegates the TSUpdateCheck does not retain the WmvPlugin. This leads to a bug if the WmvPlugin
-// instance is destroyed before the TSUpdateCheck instance as the TSUpdateCheck instance will be left with a
-// pointer to a stale object. This will happen if a page containing the Flip4Mac plug-in triggers a navigation
-// while the update sheet is visible as the WmvPlugin instance is removed from the view hierarchy and there are
-// no other references to keep the object alive.
-//
-// We work around this bug by patching the following two messages:
-//
-// 1) -[NSAlert beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:]
-// 2) -[TSUpdateCheck alertDidEnd:returnCode:contextInfo:]
-//
-// Our override of 1) detects whether it is Flip4Mac's update sheet triggering the alert by checking whether the
-// modal delegate is an instance of TSUpdateCheck. If it is, it retains the modal delegate's delegate.
-//
-// Our override of 2) then autoreleases the delegate, balancing the retain we added in 1).
-//
-// These two overrides have the effect of ensuring that the WmvPlugin instance will always outlive the TSUpdateCheck
-// instance, preventing the TSUpdateCheck instance from accessing a stale delegate pointer and crashing the application.
-
-
-typedef void (*beginSheetModalForWindowIMP)(id, SEL, NSWindow *, id, SEL, void*);
-static beginSheetModalForWindowIMP original_NSAlert_beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_;
-
-typedef void (*alertDidEndIMP)(id, SEL, NSAlert *, NSInteger, void*);
-static alertDidEndIMP original_TSUpdateCheck_alertDidEnd_returnCode_contextInfo_;
-
-static void WebKit_TSUpdateCheck_alertDidEnd_returnCode_contextInfo_(id object, SEL selector, NSAlert *alert, NSInteger returnCode, void* contextInfo)
-{
- [[object delegate] autorelease];
-
- original_TSUpdateCheck_alertDidEnd_returnCode_contextInfo_(object, selector, alert, returnCode, contextInfo);
-}
-
-static void WebKit_NSAlert_beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(id object, SEL selector, NSWindow *window, id modalDelegate, SEL didEndSelector, void* contextInfo)
-{
- if (isKindOfClass(modalDelegate, @"TSUpdateCheck"))
- [[modalDelegate delegate] retain];
-
- original_NSAlert_beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(object, selector, window, modalDelegate, didEndSelector, contextInfo);
-}
-
-static void installFlip4MacPlugInWorkaroundIfNecessary()
-{
- static bool hasInstalledFlip4MacPlugInWorkaround;
- if (!hasInstalledFlip4MacPlugInWorkaround) {
- Class TSUpdateCheck = objc_lookUpClass("TSUpdateCheck");
- if (!TSUpdateCheck)
- return;
-
- Method methodToPatch = class_getInstanceMethod(TSUpdateCheck, @selector(alertDidEnd:returnCode:contextInfo:));
- if (!methodToPatch)
- return;
-
- IMP originalMethod = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(WebKit_TSUpdateCheck_alertDidEnd_returnCode_contextInfo_));
- original_TSUpdateCheck_alertDidEnd_returnCode_contextInfo_ = reinterpret_cast<alertDidEndIMP>(originalMethod);
-
- methodToPatch = class_getInstanceMethod(objc_getRequiredClass("NSAlert"), @selector(beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:));
- originalMethod = method_setImplementation(methodToPatch, reinterpret_cast<IMP>(WebKit_NSAlert_beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_));
- original_NSAlert_beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_ = reinterpret_cast<beginSheetModalForWindowIMP>(originalMethod);
-
- hasInstalledFlip4MacPlugInWorkaround = true;
- }
-}