Opera Widgets and Ajax: connecting to multiple servers

By Opera Software

24th April 2012: Please note

Starting with Opera 12, Opera Widgets will be turned off for new users and completely removed in a later release. If you're interested in building addons for Opera, we recommend going with our extensions platform — check out our extensions documentation to get started.

Introduction

Scripts on Web pages cannot connect to any Web server other than the one the page was loaded from. This is known as the same-origin security policy and is a cornerstone of keeping the Web safe.

Opera Widgets have a more liberal security model, giving widgets the ability to contact multiple servers and opening up many interesting possibilities. This also opens up some additional potential attack vectors, however, but there are ways around them – you can lock your widgets down and prevent information from being sent to random Web sites. This article describes how to do cross-site Ajax requests inside widgets and gives an example of how it can be used.

  1. The same-origin security policy
  2. The Opera Widgets security model
  3. How to do cross-site AJAX in widgets
  4. Mashup Widgets – doing mashups in the client
  5. Other techniques and work
  6. Resources

The same-origin security policy

Scripts running in Web pages may only download data from the server the page was loaded from. This is known as the same-origin security policy, and is in place to prohibit malicious scripts from getting or posting potentially sensitive data to other Web sites without the user’s knowledge.

Note that the scripts may have been downloaded from a different server than where the page was downloaded, but the script may still only connect to the server from which the page, the main document, was loaded.

The same-origin security policy of course applies to Ajax applications, which use XMLHttpRequest to read and write data from a Web server.

You can easily try an example out to see how the browser enforces this security policy. The following piece of JavaScript code will use XMLHttpRequest to read a Web page from www.opera.com:


var xhr = new XMLHttpRequest ();
xhr.open( 'GET', 'http://www.opera.com', false );
xhr.send();

Try this snippet and the browser will execute your script and emit this message in your JavaScript error console:

JavaScript URL thread: "javascript:var xhr = new XMLHttpRequest ();xhr.open( 'GET', 'http://www.opera.com', false );xhr.se..."
Error:
name: Error
message: Security violation

In this case www.opera.com is off limits to the script, because this document is not loaded from Opera’s www server.

As an additional exercise, re-try the example using the domain name of the server this page was loaded from as an argument to the XMLHttpRequest open method.

In order to work around the same-origin security policy, you can set up a service on your own Web server to proxy data to and from other Web servers. The Web page will then be able to indirectly contact multiple servers. Setting this up requires significant work, in particular to avoid misuse of the proxy by others. Widgets offer a way out of this by using only client-side Web technologies.

The Opera Widgets security model

The Opera Widgets security model allows you to specify to which protocols, hosts, and ports the widget may connect. If no limitations have explicitly been defined, all hosts and ports may be contacted. However, you must enable network access by adding a network attribute with a value of one or both of ‘public’ and ‘private’ to the widget element in the config.xml of your widget. Access restrictions are specified using the access element in the widgets’s config.xml file.

Opera Widgets may thus contact most servers by default. However, accessing file:// urls is not allowed and protocols other than http and https must be explicitly specified to be accessible.

In order to avoid security problems due to the fact that widgets may connect to multiple servers, each widget has a private cookie and document cache. See the following article on the widget security model for more details of this.

Opera has submitted the widget specification for standardization at the W3C. It is likely that the security model will be changed as part of this work.

How to do cross-site AJAX in widgets

No magic is needed to do cross-site AJAX in widgets. You just create an XMLHttpRequest object and open a connection to the desired host:


var xhr = new XMLHttpRequest ();
xhr.onreadystatechange = function () {
    if ( this.readyState == 4 )
    {
        switch ( this.status )
        {
            case 200:
                handleData(xhr.responseText);
                break;
            case 400:
              //...
            //... Handle other cases
        }
    }
}
xhr.open( 'GET', 'http://www.opera.com/', false );
xhr.send();

In this example a request is sent to Opera. The entire page will be available in the responseText property of the xhr object.

Contacting external servers for data is the cornerstone of many widgets. Examples include getting Web cam images, images from photo galleries, map data, traffic data, weather data, and more. The typical usage is contacting a server with a public XML-based API or scraping Web pages for information.

Mashup Widgets – doing mashups in the client

Mashup web applications combine information from multiple web sites or servers into new, creative web applications.

Traditionally mashup applications are implemented on a Web server connecting to the source servers. Using Opera Widgets, mashup Web applications can be implemented entirely in the client.

Mashups often make use of data from publicly-available XML APIs from Web sites such as Facebook, Flickr, Google Maps, and so on. A good overview of such APIs can be found at the ProgrammableWeb Web site.

Other techniques and work

The W3C is doing work on standardizing cross-domain access. In the current draft, this is accomplished by sending special headers to allow a Web server to control what other servers the browser may connect to. See the draft on Access Control for Cross-site Requests for more details.

It is possible to lessen the cross-site security restrictions of most browsers by changing their settings. Versions of Internet Explorer up until version 5 allowed the user to define trusted sites or zones. Ajax calls to these sites would then be possible. Mozilla Firefox allows the user to set the document.domain property to a parent domain, allowing the script to access data from different subdomains.

Resources

This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.

Comments

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

No new comments accepted.