6

In my Cocoa app, I want to prevent Flash from loading in a WebView, and let the user decide if the Flash should be shown for each page. (That's the same behavior already available through the ClickToFlash plugin or Safari extension. Bundling any of those extensions is probably not an option because of licensing issues.)

Unfortunately most of the Flash I'm trying to avoid is generated from embedded JavaScript specifically designed to prevent easy flash blocking, so I cannot filter the raw HTML for inclusion of Flash objects.

Also, I cannot disable JavaScript for my WebView, as the page I want to display looks completely different when JavaScript is turned off.

Is there a notification/hook I can use to modify the page DOM after JavaScript has been executed, but before the Flash plugin is loaded?

Or should I pursue a different direction?

Thanks, Ilja

iljawascoding
  • 1,090
  • 9
  • 20
  • Here is a similar question that may help: https://stackoverflow.com/questions/2209844/suppress-plugin-loading-in-webkit – Lars Blåsjö Feb 03 '11 at 12:18
  • I'm sorry, forgot an important point in my initial question: "In my Cocoa app, I want to prevent Flash from loading in a WebView, **and let the user decide if the Flash should be shown for each page**. " – iljawascoding Feb 03 '11 at 12:23
  • The only problem is that the solution posted as the answer to that question doesn't work for MIME types handled by plugins. – Rob Keniger Feb 03 '11 at 12:34
  • Oh,sorry. Should have made it a comment rather than an answer. – Lars Blåsjö Feb 03 '11 at 12:57

2 Answers2

6

Ideally, you would just define your own WebKit plug-in that handles the application/shockwave-flash MIME type and make your plug-in do nothing.

However, there is unfortunately no way to control the priority of multiple WebKit plug-ins that all register for the same MIME type. The loading order of WebKit plug-ins is totally random and arbitrary, so you cannot guarantee that your plug-in will handle the Flash object instead of the Flash plug-in.

The only way around this that I've found is to subclass WebView and override the private method -_pluginForMIMEType: like so:

@class WebBasePluginPackage;

@interface WebView ( MyFlashPluginHack )
- (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType;
@end

@implementation MyWebView

- (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
{
    if ( [MIMEType isEqualToString:@"application/x-shockwave-flash"] )
    {
        return [super _pluginForMIMEType:@"application/my-plugin-type"];
    }
        else
    {
        return [super _pluginForMIMEType:MIMEType];
    }
}

@end

Then you just need to create a custom WebKit plugin to handle "application/my-plugin-type" and have that plug-in do nothing at all.

Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
  • Thanks for the hint. I'd follow it, but I have doubts that I would get my app approved in the Mac App Store, _pluginForMIMEType is probably on Apple's blacklist. – iljawascoding Feb 03 '11 at 12:34
  • It's possible, although I'd expect the reviewers to be a bit more lenient with WebKit since it's completely open source. I know that I've specifically been told to use certain unpublished/private methods by Apple employees on Apple's WebKit-SDK-Dev mailing list. Interestingly, [this questioner](http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application) claims to have used a private WebKit method and had an app approved. – Rob Keniger Feb 03 '11 at 12:38
  • I've used this approach myself, and it has been approved multiple times by Apple. They appear to use a different standard for open source projects like WebKit. – J. Perkins Jul 26 '13 at 22:53
  • Your code doesn't work as it is. In the interface you're using a "MyFlashPluginHack", in the implementation the class is called "MyWebView", how should this work together? Something is obviously missing and I unfortunately couldn't find out how to use those code snippets. Can you revise it and indicate how to use it with a WebView? – keeluu Oct 20 '15 at 08:51
1

Okay, we pretty much figured this out.

Since there is no official API that lets the host app know when JavaScript has finished or control what plugin should load, we are now using custom JavaScript that gets inserted into the received HTML we want to display.

The ClickToFlash Safari extension (not the Internet plugin, which it is based on) was a good inspiration.

iljawascoding
  • 1,090
  • 9
  • 20