lchamp
lchamp

Reputation: 6612

How to reload content blockers while they are active?

I have an app with several content blockers extension. Their configuration is fine and they act as they are supposed to.

However I need to call reloadContentBlocker(withIdentifier:completionHandler:) from SFContentBlockerManager when I've updated the filter lists for example.

Here is a code example (with NSLog for timestamp purposes below):

func reload(_ callback: @escaping((Bool) -> Void)) {
    NSLog("Reload start")

    let contentBlockersIdentifiers = ["com.aaa.bbb.ContentBlocker.ExampleA", "com.aaa.bbb.ContentBlocker.ExampleB", "com.aaa.bbb.ContentBlocker.ExampleC", "com.aaa.bbb.ContentBlocker.ExampleD", "com.aaa.bbb.ContentBlocker.ExampleE"]

    var failures: [String] = [String]()

    let dispatchSemaphore = DispatchSemaphore(value: 0)
    let dispatchQueue = DispatchQueue(label: "reload-queue", qos: .userInitiated)

    dispatchQueue.async {
        NSLog("Reloading content blockers")
        for aContentBlockerIdentifier in contentBlockersIdentifiers {
            NSLog("Reloading '\(aContentBlockerIdentifier)'")
            SFContentBlockerManager.reloadContentBlocker(withIdentifier: aContentBlockerIdentifier) { (error) in
                if let error = error?.localizedDescription {
                    NSLog("Failed to reload '\(aContentBlockerIdentifier)': \(error)")
                    failures.append(aContentBlockerIdentifier)
                } else {
                    NSLog("Successfully reloaded '\(aContentBlockerIdentifier)'")
                }
                dispatchSemaphore.signal()
            }
            dispatchSemaphore.wait()
        }

        callback(failures.isEmpty)
        NSLog("Reload end")
    }
}

This is what is prints:

16:41:43.391543+0200 Reload start
16:41:43.392003+0200 Reloading content blockers
16:41:43.392125+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleA'
16:41:50.010102+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleA'
16:41:50.010299+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleB'
16:41:50.351554+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleB': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.351676+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleC'
16:41:50.493327+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleC': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.493429+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleD'
16:41:50.631578+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleD': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.631681+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleE'
16:41:50.718466+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleE': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.718600+0200 Reload end

It apparently tries to do the reload one content blocker after another (as I wanted to do with the DispatchSemaphore). However after the first one succeeded the following are failures.

Now let's go and disable the Content Blockers in Setting App > Safari > Content Blockers and try again:

16:55:05.699392+0200 Reload start
16:55:05.700171+0200 Reloading content blockers
16:55:05.700564+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleA'
16:55:05.714444+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.714909+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.723056+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.723343+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleC'
16:55:05.730565+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleC'
16:55:05.730775+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleD'
16:55:05.735733+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleD'
16:55:05.735841+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleE'
16:55:05.740758+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleE'
16:55:05.740865+0200 Reload end

Surprise... it works. But I would rather not ask my users to :

  1. go manually disable the Content Blockers in the Settings
  2. perform the update manually (while waiting to develop automatic refresh)
  3. go manually re-enable the Content Blockers in the Settings

I'm missing something somewhere (maybe a thread issue). Hopefully someone will be able to help!

Upvotes: 2

Views: 560

Answers (1)

Nikita Antonenko
Nikita Antonenko

Reputation: 1

Most likely, it means that you have rules that contains incorrect syntax or rules file have more the 50 000 rules. Also the error can happened when you fill returningItems with nil context.completeRequest(returningItems: nil, completionHandler: nil) in your NSExtensionRequestHandling where context is NSExtensionContext

Upvotes: 0

Related Questions