iossafari-content-blocker

Added site is not blocked with content blocker


Hi I am writing a simple content blocker app. In this app I want to allow the user add a website that he wants to block and block it but for some reasons my content blocker doesn't block newly added website for some reasons. I used SFContentBlockerManager.reloadContentBlocker(withIdentifier: blockerIdentifier) it prints success but for some reasons it doesn't work.

import UIKit
import Cartography
import SwiftyJSON
import SafariServices

protocol MyProtocol{
  func DeleteSite(num:Int)
}


class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, MyProtocol {
var tableView: UITableView = UITableView()
var arr = [String]()
func DeleteSite(num: Int) {

    if let path = Bundle.main.path(forResource: "blockerList", ofType: "json"){
        guard let data = NSData(contentsOf: URL(fileURLWithPath: path)) else{
            return
        }
  //      JSON(data: data as Data)[num] = nil
        var jsonObj = JSON(data: data as Data)
     //   jsonObj.arrayObject?.remove(at: num)
        print(jsonObj)
        if jsonObj != JSON.null {
           // jsonObj.arrayObject[num] =
            jsonObj[num] = nil
           //  print("Hello I do work here \(jsonObj.arrayValue.remove(at: num))")
            tableView.reloadData()
           // jsonObj.arrayObject?.remove(at: num)

        } else {
            print("Could not get json from file, make sure that file contains valid json.")
        }
    }

}


override func viewDidLoad() {
    super.viewDidLoad()
    let blockerIdentifier = "saltaim.SelfControl2.blocker"
    SFContentBlockerManager.reloadContentBlocker(withIdentifier: blockerIdentifier) {error in
        if error == nil {
            print("Success")
        } else {
            print("----------------------------------------------")
            print(error)
            print("----------------------------------------------")

        }
    }

    super.view.backgroundColor = UIColor.red;

    //let blockerIdentifier = "com.appsfoundation.ContentBlocker.Blocker"
    //SFContentBlockerManager.
    // print("--------------------")
    //print(FileManager.default.c)
    //Bundle(for: ContentBlockerRequestHandler)
    //print(Bundle.main.path(forResource: "blocker/blockerList", ofType: "json"))
    //print(Bundle.main.path(forResource: "blockerList", ofType: "json"))

    //print("--------------------")
    //Bundle.main.url
    //Bundle.main.pa
    //FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: <#T##String#>)
    // print(Bundle.main.url(forResource: "blocker/blockerList", withExtension: "json"))
    // Bundle.init(for: ContentBlockerRequestHandler)
    // print(Bundle.main.paths(forResourcesOfType: "blockerList.json", inDirectory: "blocker"))
    tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "cell")

    if let path = Bundle.main.path(forResource: "blockerList", ofType: "json"){
        guard let data = NSData(contentsOf: URL(fileURLWithPath: path)) else{
            return
        }
        let jsonObj = JSON(data: data as Data)
        print(jsonObj)
        if jsonObj != JSON.null {
            // print("Hello I do work here \(jsonObj["trigger"])")
            guard let arr1 = jsonObj.array else{
                return;
            }
            var count = arr1.count;
            for index in 0...count-1{
                //print("-------")
                // print(jsonObj[index]["trigger"]["url-filter"].stringValue)
                arr.append(jsonObj[index]["trigger"]["url-filter"].stringValue);


            }
            //for

        } else {
            print("Could not get json from file, make sure that file contains valid json.")
        }
        //


    }
    // arr.append("Hello")
    // arr.append("my name is ")
    let button = UIButton();
    button.setTitle("+", for: .normal)
    button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
    // button.titleLabel?.text = "+"

    self.view.addSubview(tableView)
    self.view.addSubview(button)
    tableView.delegate = self
    tableView.dataSource = self
    constrain(tableView, view, button){
        tableView, view, button in
        tableView.width == view.width
        tableView.height == view.height - 50
        tableView.top == view.top
        tableView.right == view.right
        button.height == 50
        button.width == view.width
        button.top == view.bottom - 50
        button.right == view.right

    }
    //arr = Array()
    // Do any additional setup after loading the view, typically from a nib.
    // self.view.backgroundColor = UIColor.redColor();
}
func buttonPressed(){
    // print("I was pressed")
    //var alert = UIAlertView();
    //alert.title = "Enter a website";
    // alert.alertViewStyle = UIAlertViewStyle.plainTextInput
    // alert.addB
    //alert.addButton(withTitle: "Done")
    //alert.addButton(withTitle: "Cancel")
    var s:String?
    var alert = UIAlertController(title: "Alert", message: "Enter website that you would like to block", preferredStyle: UIAlertControllerStyle.alert)

    alert.addTextField { (text) in
        text.placeholder = "http://";
        s=text.text
    }
    let action = UIAlertAction(title: "Done", style: UIAlertActionStyle.default) { (action: UIAlertAction) in
        guard let s = alert.textFields?[0].text else{
            return
        }

        //var c = ["action":["type": "block"], "trigger":["url-filter":s]];
        //print(c)
        let path = Bundle.main.path(forResource: "blockerList", ofType: "json")!
        var readString = "" // Used to store the file contents
        do {
            // Read the file contents
            readString = try String.init(contentsOf: URL(fileURLWithPath: path))
            //readString = fileURL.absoluteString
            // readString = try String(contentsOfURL: fileURL)
        } catch let error as NSError {
            print("Failed reading from URL: \(URL(fileURLWithPath: path)), Error: " + error.localizedDescription)
        }
       // var size = (readString.characters.count - 1)
        //print("The end index is \(readString.endIndex)")
        print("------------------------")
        readString = readString.replacingOccurrences(of: "]", with: "")
      //  print(readString.endIndex)
       // readString = String(readString.characters.dropLast())
        print(readString)
        print("--------------------------")
       // readString.remove(at: readString.endIndex)
       // readString = readString.substring(to: readString.index(before: readString.endIndex))
        readString += ",{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"" + s+"\"}}]"
        print("File Text: \(readString)")
  //      let fileName = "blockerList"
      //  let DocumentDirURL = try! FileManager.default.url(for: ., in: .userDomainMask, appropriateFor: nil, create: true)
     //   let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("json")
        print("FilePath: \(path)")
        let fileHandler = try! FileHandle(forWritingTo: URL(fileURLWithPath: path))
        //fileHandler.
        //fileHandler.seekToEndOfFile()
        fileHandler.write(readString.data(using: String.Encoding.utf8, allowLossyConversion: false)!)

       // fileHandler.write("Hello".data(using: String.Encoding.utf8, allowLossyConversion: false)!)
       // fileHandler.write(c.description.data(using: String.Encoding.utf8, allowLossyConversion: false)!)
        fileHandler.closeFile()
        var readString1 = "" // Used to store the file contents
        do {
            // Read the file contents
            readString1 = try String.init(contentsOf: URL(fileURLWithPath: path))
            //readString = fileURL.absoluteString
            // readString = try String(contentsOfURL: fileURL)
        } catch let error as NSError {
            print("Failed reading from URL: \(URL(fileURLWithPath: path)), Error: " + error.localizedDescription)
        }
        print("File Text: \(readString1)")
        let blockerIdentifier = "saltaim.SelfControl2.blocker"
        SFContentBlockerManager.reloadContentBlocker(withIdentifier: blockerIdentifier) {error in
            if error == nil {
                print("Success")
            } else {
                print("----------------------------------------------")
                print(error)
                print("----------------------------------------------")

            }
        }



    }
    let action2 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) { (UIAlertAction) in
        self.dismiss(animated: true, completion: nil)
    }
    alert.addAction(action)
    alert.addAction(action2)
    self.present(alert, animated: true, completion: nil)
    //self.viewC
    //presentedViewController(alert)
    //alert.addA
    // alert.show()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

    // Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return arr.count

}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
    return 50
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    // Code here
    // let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
    var site = arr[(indexPath as NSIndexPath).item]
    let cell = MyTableViewCell(num: (indexPath as NSIndexPath).item,site: site, style: UITableViewCellStyle.default, reuseIdentifier: "cell")
    cell.delegate = self;
    // let cell = MyTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
    // cell.site = arr[(indexPath as NSIndexPath).item]

    // let cell1 = MyTableViewCell();

    // let cell = MyTableV
    //cell.t
    //let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell")
    //cell.textLabel?.text = "Hello"
    //cell.textLabel?.text = arr[(indexPath as NSIndexPath).item]
    return cell;
}


 }

Solution

  • I ran into a similar issue when I wrote my own content blocker. When you create the content-blocker extension you also create a json file that the extension reads from. Now, the important part to that is that the extension ONLY reads from that file located in the extension's bundle directory.

    From what I can see you are writing to a json file in your main app bundle and then reloading the content blocker. So the content blocker just simply looks at the file in it's own directory (again, seperate from the main bundle directory) and loads that json file.

    To resolve this, you need to actually write your file changes to the json file located in the extensions bundle directory.

    Here's an example:

    let groupUrl: NSURL = fileManager.containerURLForSecurityApplicationGroupIdentifier("group.com.mygroup")!
    
    if let path = NSURL(string: "blockerList.json", relativeToURL: groupUrl) {
        // write your json data to the path here
        SFContentBlockerManager.reloadContentBlockerWithIdentifier("com.my.extension.identifier", completionHandler: nil)
    }
    

    Another important thing to note is you'll have to request special permissons to read and write from the extension's bundle.