Site blocking with Opera’s URL Filter API

By Daniel Davis

From Opera 15 onward, Opera 11 & 12’s extension format is no longer supported, and instead, we’ve switched to Chromium’s extension model. Check out our new documentation for developing extensions for Opera 15 and higher and start building your own extensions.

Introduction

Picture the scene: You come back home late, tired from a fun but exhausting night out and you decide to quickly check your preferred microblogging site. You don’t quite agree with one of the messages you read and decide to fire off a quick reply. When you return to your normal self the following morning however, you re-read your message and cringe. Did I really write that?

There are times when blocking sites from ourselves is not a bad idea. Maybe it’s better if you're unable to open that website after a few drinks on a Saturday night. Maybe your credit card report would be healthier if checkout pages were hidden from view, or maybe there's a particular website that you'd rather not see at all, even by accident.

Opera’s built-in content blocker has been helping users for a long time now, but with the release of the URL Filter API in Opera 11.10, web developers can build extensions that not only make it easier for users to block content but also give them more control. In this tutorial we'll look at the concept of the URL Filter API, some scenarios in which it could be used and a step-by-step explanation of how to use it.

Concept

Opera’s built-in content blocker uses a file containing a list of domains, similar to the way an operating system’s hosts file works. This file, urlfilter.ini, is found in a user's profile directory and URLs can be easily added through the Opera UI by right-clicking on a page and selecting "Block content". You can also manage content by going to Tools > Advanced > Blocked content. The URL Filter API can enable an extension to temporarily add domains to the content blocker. The following diagram illustrates this concept.

The URL Filter API adds virtual lists to Opera's built-in content blocker.

Figure 1: The URL Filter API adds virtual lists to Opera’s built-in content blocker.

Scenarios

Examples of when this could be useful include:

  • Blocking by time: Block social networking or other sites you are addicted to, at certain times.
  • Blocking by page content: Block any page that has a “Buy” button or a field requesting a credit card number.
  • One-click blocking: Block the current domain at the click of a button.
  • Remotely controlled blocking: Block domains based on a third party's list.

But wait a minute, I hear you say. Can’t we do all this stuff already with JavaScript? Well, yes you can, but using this API offers two main advantages:

  • When blocking hundreds or even thousands of domains, letting the browser do the work can increase efficiency considerably.
  • With just a single method needed to block a domain, your code will be simpler to write and maintain.

Getting it to work

Enough talking, let’s start coding! In this tutorial, we're going to make a very basic example extension that increases productivity by blocking the two most popular social networking sites. The first thing we need to do when using the URL Filter API in an extension is enable it simply by adding the following line to our config.xml file:

<feature name="opera:urlfilter"/>

Now on to the extension’s content. As you probably know, as well as a config.xml file, all extensions require an index.html file so we’ll create one now. All this does is call a script file — background.js in this case.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <script src="background.js"></script>
        <title>URLFilter (Opera extension)</title>
    </head>
    <body>
    </body>
</html>

Now we’ll move onto the JavaScript. First we’ll create a background.js file and add an array containing the sites to block. We’ll also store a reference to the URLFilter object, which is slightly more efficient than repeatedly referring to opera.extension.urlfilter.

var sites = ['*://twitter.com/*',  '*://*.twitter.com', '*://facebook.com/*', '*://*.facebook.com/*'];

var filter = opera.extension.urlfilter;

Note that asterisks (*) can be used as wild cards anywhere within a URL, for example *:// will block pages using any protocol including http and https.

So far so easy. The URLFilter object contains a virtual list — block — for blocking domains and has two methods: add() and remove(). To block sites in our example, we loop through our array and use the add() method for each site:

for (var i = 0, len = sites.length; i < len; i++) {
    filter.block.add(sites[i]);
}

Lastly we wrap the above code in a check for the URL Filter API itself:

if (typeof opera.extension.urlfilter != 'undefined') {
    ...
}

Believe it or not, that’s it! To test it out, you can download our URLFilterExample.oex example extension or have a go at building it yourself using the complete code shown below, not forgetting the icons of course! Note that you may have to clear the browser's cache after installing the extension, otherwise it may look as though the site is not blocked.

config.xml

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="http://people.opera.com/danield/URLFilterExample" defaultlocale="en">
    <name>URL Filter Example</name>
    <description xml:lang="en">Block certain sites with Opera's in-built URL filter.</description>
    <author href="http://people.opera.com/danield/">Daniel Davis</author>
    <icon src="icon_64.png"/>
    <icon src="icon_18.png"/>
    <feature name="opera:urlfilter"/>
</widget>

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <script src="background.js"></script>
        <title>URL Filter Example (Opera extension)</title>
    </head>
    <body>
    </body>
</html>

background.js

// Check that the URL Filter API exists
if (typeof opera.extension.urlfilter != 'undefined') {

    // Put the sites we want to block in an array
    var sites = ['*://twitter.com/*', '*://*.twitter.com', '*://facebook.com/*', '*://*.facebook.com/*'];

    // Asign the URLFilter object to a variable for efficiency
    var filter = opera.extension.urlfilter;

    // Loop through the array of sites and add each one to the "block" list
    for (var i = 0, len = sites.length; i < len; i++) {
        filter.block.add(sites[i]);
    }
}

Naturally there are several improvements we could make to this simple example before releasing it to the world, such as enabling the user to add or remove sites as they wish. To do this, you could use the extension preferences feature.

Conclusion

As you can see, the URL Filter API is easy to use, but can be very powerful. It builds on technology that has existed in the Opera desktop browser for years but as of Opera 11.10 you can now build your own interface to it and add enhancements. It’s worth remembering that blocked content is not simply hidden – it’s prevented from downloading in the first place so users don’t have to wait or pay for content they’re not going to see. There are many applications for this: We’re looking forward to seeing what you create and submit to the Opera extensions repository.

Reference

URL Filter API for Opera extensions

This article is licensed under a Creative Commons Attribution 3.0 Unported license.

Comments

The forum archive of this article is still available on My Opera.

  • photo

    gwarser

    Tuesday, April 3, 2012

    There is a difference between '*://*.twitter.com' and '*.twitter.com'?
    If `*` catch-all, then:

    >>> /.*\.twitter\.com/.test('http://subdomain.twitter.com')
    true
    >>> /.*:\/\/.*\.twitter\.com/.test('http://subdomain.twitter.com')
    true
  • photo

    Daniel Davis

    Tuesday, May 15, 2012

    No, I don't think there's a meaningful difference between '*://*.twitter.com' and '*.twitter.com', but the article lists '*://twitter.com/*' and '*://*.twitter.com' which I think is necessary for URLs with no subdomain.
  • photo

    Behzad ghaem

    Sunday, June 10, 2012

    i can not cunnecct to facebook
  • photo

    esr2587758

    Saturday, February 9, 2013

    Is there any clue about blocking by time? I think it is not easy.
No new comments accepted.