18

I'm working on a Safari Content Blocking extension. I intend to show setup instructions if the extension is disabled and to show settings if it is conversely enabled. How can I determine if the extension is enabled by the user?

I've seen this method to detect if a custom keyboard is activated but there's no key on NSUserDefaults that relates to Safari Content Blockers.

Community
  • 1
  • 1
Ryan Brodie
  • 6,554
  • 8
  • 40
  • 57
  • Looks like this isn't exposed as a public API yet. If you are working in a Jailbroken environment, there might be a plist or file with that info in `/var/mobile/Media/Safari/`. – JAL Nov 09 '15 at 22:33
  • Possible duplicate of http://stackoverflow.com/questions/32970259/how-do-i-know-if-my-ios-safari-content-blocker-is-enabled – kabiroberai Nov 10 '15 at 06:22
  • break the structure of your `.json` file and see if you get an error in `debugger`. If you do - everything is fine and you should revert your `.json` to the normal state and carry on. – TheLuminor Nov 10 '15 at 08:49
  • 1
    https://www.hackingwithswift.com/safari-content-blocking-ios9 this should be of some help. Please feel free to get back. – TheLuminor Nov 10 '15 at 08:52

2 Answers2

9

As of iOS 10, there is a new method in SFContentBlockerManager to support this:

getStateOfContentBlocker(withIdentifier:completionHandler:)

And you call it like this (Swift 3):

SFContentBlockerManager.getStateOfContentBlocker(withIdentifier: "your.identifier.here", completionHandler: { (state, error) in
    if let error = error {
        // TODO: handle the error
    }
    if let state = state {
        let contentBlockerIsEnabled = state.isEnabled
        // TODO: do something with this value
    }
})
breakingobstacles
  • 2,815
  • 27
  • 24
  • hi bro, i am going to create subscription based app i want programatically enabled and disabled blocker its possible or not ? – ikbal Dec 21 '16 at 10:36
  • @Rock: You cannot change the enabled/disabled state in Safari's Content Blocker settings programmatically. Only the user can change it via the Settings app. – breakingobstacles Dec 21 '16 at 18:36
7

You could utilize a SFSafariViewController to load a custom website. This website checks whether it is able to show something that your content blocker should block. Then redirect to the respective custom url (success/failure) that your app previously registered for. You could even use a hidden Safari View Controller without animation to avoid any distraction from the user's perspective (as shown here). (I guess this technique is used by former content blocker Peace)

Steps

App

  1. Register custom URLs for success/failure
  2. Register for notification callback using the NotificationCenter (e.g. contentBlockerEnabled)
  3. Use SFSafariViewController to show a custom website and include the following rule in blockerList.json:

    {
        "action": {
            "type": "css-display-none",
            "selector": ".blocked_selector"
        },
        "trigger": {
            "url-filter": ".*"
        }
    }
    

Website

  1. Check for blocked content:

    if($('.blocked_selector').css('display') == "none") {
       // Content blocker enabled
    }
    
  2. Redirect to custom URL (success/failure)

App

  1. Post notification from application:openURL:options: (success/failure based on called url)

Update 18/01

Following on from Tilo's hypothesis, I built the proposed solution. I wrote about what I learnt on Medium and you can grab the source files from GitHub.

TL;DR It works but only temperamentally due to the latency incurred of the content blocking rules database to update. A potential workaround is redirecting the test page to create an artificial delay.

Community
  • 1
  • 1
tilo
  • 14,009
  • 6
  • 68
  • 85
  • How do you check for blocked content on the custom site? – Ryan Brodie Nov 10 '15 at 09:45
  • A possible solution is described here (using jQuery): http://www.hongkiat.com/blog/jquery-detect-ads-block/ – tilo Nov 10 '15 at 09:52
  • Right I've tidied up the answer and it looks very promising. I won't be able to verify tonight but for the sake of the bounty I've marked this as correct. – Ryan Brodie Nov 10 '15 at 10:07