Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to block external resources to load on a WKWebView?

I have an app that loads a webpage, but prevents the downloads of images, fonts, javascripts, etc. For this I implemented an NSURLProtocol subclass which works very well with UIWebView.

However I'm migrating to WKWebview, and realise that my crafted NSURLProtocol class no longer works to filter out these resources.

Have anyone an insight as to how to achive the filtering/blocking?

In case you're wondering how am I doing the migration, I started with this post: http://floatlearning.com/2014/12/uiwebview-wkwebview-and-tying-them-together-using-swift/

like image 206
dequin Avatar asked Aug 20 '15 13:08

dequin


2 Answers

Since iOS 11 you can use WKContentRuleList

First, create a Content Rule or a list. Each rule is comprised of a trigger and an action. See Apple's Documentation on Content Rule creation

This is a creation example, blocks all image and Style Sheet content, but allows those ended on jpeg by way of ignoring the previous rules:

     let blockRules = """
         [{
             "trigger": {
                 "url-filter": ".*",
                 "resource-type": ["image"]
             },
             "action": {
                 "type": "block"
             }
         },
         {
             "trigger": {
                 "url-filter": ".*",
                 "resource-type": ["style-sheet"]
             },
             "action": {
                 "type": "block"
             }
         },
         {
             "trigger": {
                 "url-filter": ".*.jpeg"
             },
             "action": {
                 "type": "ignore-previous-rules"
             }
         }]
      """        

Having your list of rules, you can add them to the ContentRuleListStore

    import WebKit
    @IBOutlet weak var wkWebView: WKWebView!

    let request = URLRequest(url: URL(string: "https://yourSite.com/")!)

    WKContentRuleListStore.default().compileContentRuleList(
        forIdentifier: "ContentBlockingRules",
        encodedContentRuleList: blockRules) { (contentRuleList, error) in

            if let error = error {
                return
            }

            let configuration = self.webView.configuration
            configuration.userContentController.add(contentRuleList!)

            self.wkWwebView.load(self.request)
    }

If later you want to remove all your rules, call:

    self.wkWebView.configuration.userContentController.removeAllContentRuleLists()
    self.wkWebView.load(self.request)

Here is the 2017 WWDC video

Best of lucks!

I've created a sample project on Github WKContentRuleExample

like image 200
dequin Avatar answered Oct 04 '22 15:10

dequin


As of iOS 9.0 there is no way to intercept network requests for the WKWebView. You can do this with JavaScript in a limited way.

Please file a WebKit bug or an Apple bug to request this functionality. Many of us are in need of these hooks.

like image 30
Stefan Arentz Avatar answered Oct 04 '22 14:10

Stefan Arentz