Tuesday, 21 March 2017

How to Create a Safari Content Blocker Extension in Swift or Objective C

Safari Content Blocker

Create Content Blocker Extension

Now that you have your basic application created we need to add a new application extension. We do this by going to FileNew > Target. This will open up a Dialogue window for us and from that window, in the left hand side pane select Application Extension. Now, from the right main pane, select Content Blocker Extension:
Click Next. You will then be asked to name your content blocker. I have called this one SuperEvil.You will then get a message asking you to Activate “SuperEvil” Scheme. Click Activate:

Once that is done, go to your Project Navigation Pane. You should see a new folder called SuperEvil and a subfile of that folder called: blockerList.json. Double click that file. by default the code inside should be:[
[
    {
        "action": {
            "type": "block"
        },
        "trigger": {
            "url-filter": "https?://(www.)?google.*" ////block specific url/////// 
        }                                         
                                                   
    },
 {
        "action": {
            "type": "block"
    },
        "trigger": {
            "url-filter": ".*",
            "resource-type": ["media"]
                 ///block video, audio all types of media files for all websites///
    }
 }

]  
Block phrases or urls with Safari Content Block
Let me show you a very quick example. Let us assume that you are fed up of reddit. (For the record, I love reddit) You no longer want to display any pages from the reddit website. This includes subdomains. Then you would replace the above code with
[ { "action": { "type": "block" }, "trigger": { "url-filter": ".*reddit.*" } } ]
Table 1  Supported features of JavaScript regular expressions
Syntax
Description
.*
The search matches all strings with a dot appearing zero or more times. Use this syntax to match every URL.
.
The search matches any character.
\.
The search explicitly matches the dot character.
[a-b]
The search matches a range of alphabetic characters.
(abc)
The search matches groups of the specified characters.
+
The search matches the preceding term one or more times.
*
The search matches the preceding character zero or more times.
?
The search matches the preceding character zero or one time.

url-filter-is-case-sensitive
The value associated with this key is a Boolean value. The default value is false.
if-domain or unless-domain
The value associated with this key is an array of strings. The strings are matched to the domain of the URL. The if-domain field limits the action to a specific list of domains. The unless-domain field acts on any site except domains in provided list. Triggers cannot have both unless- and if-domain fields. Domain values must be lowercase ASCII. Use punycode to encode non-ASCII characters.
Add the * character before the domain name to match the domain and any subdomains. For instance, *webkit.org matches bugs.webkit.org and webkit.org.
resource-type
The value associated with this key is an array of strings representing the resource types that the rule should match. If not specified, the rule matches all resource types. The strings describes how the browser intends to use the resource, not necessarily the type of the resource itself. For example, <img src="something.css"> is identified as an image. Valid values for resource-type are:
  • document
  • image
  • style-sheet
  • script
  • font
  • raw (Any untyped load, such as XMLHttpRequest)
  • svg-document
  • media
  • popup
load-type
The value associated with this key is an array of strings. There are two possible values at this time and those values are mutually exclusive. If not specified, the rule matches all load types.
  • first-party
    The rule is triggered only if the resource has the same scheme, domain, and port as the main resource on the page.
  • third-party
    The rule is triggered if the resource is not from the same domain as the main page resource.


If any changes in "blockerlist.json" you have to reload. you have to call the below displayed function in "AppDelegate.m" in "didFinishLaunchingWithOptions" function.

#import <SafariServices/SafariServices.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    NSString *id = [[NSString alloc]initWithString:@"com.gears42.Nix-Agent.contentBlock"];
    [SFContentBlockerManager reloadContentBlockerWithIdentifier:id completionHandler:^(NSError * error){
        if(error == nil){
            NSLog(@"Reloaded");
        }
        else{
            NSLog(@"Failed to reload:::%@",error);
        }
    }];

    
}

or

AppDelegate.swift


import SafariServices
func applicationDidBecomeActive(application: UIApplication) {
let blockerIdentifier = "com.appsfoundation.ContentBlocker.Blocke"SFContentBlockerManager.reloadContentBlockerWithIdentifier(blockerIdentifier) {error in if error == nil { print("Reloaded") } else { print(error) } }}





https://developer.apple.com/library/content/documentation/Extensions/Conceptual/ContentBlockingRules/CreatingRules/CreatingRules.html

Setting Up Multiple App Targets in Xcode from a Single Codebase

 To create two different apps (like "Light" and "Regular") from the same codebase in Xcode, you can follow these steps b...