ALPHA
Widget Structure
DOM API
Sample widgets: Roman Sudoku JSLint

ADsafe Widget Structure

ADsafe defines a safe subset of the JavaScript Programming Language, and an interface that allows programs written in that language to usefully interact with a specific subtree of of the HTML document. A programmed HTML fragment is called a widget.

A widget is a fragment of HTML with some script. That script is able to manipulate the HTML fragment, but is unable to manipulate any other part of the document. All <input> tags must contain an autocomplete="off" attribute.

This is the simplest widget pattern allowed by ADsafe:

<div id="WIDGETNAME_">
   html markup required by the widget
<script>
ADSAFE.go("WIDGETNAME_", function (dom) {
    "use strict";

// This is where the code for the widget is placed. It can access
// the document through the dom parameter, allowing it indirect
// access to html elements, allowing it to change content, styling,
// and behavior.

});
</script>
</div>

It uses the JSLint option {adsafe: true, fragment: true}. The widget must be wrapped in a <div> element. The <div> element must have an id. The id must contain only upper case ASCII letters with a trailing _ character. It is the page builder's responsibility to assure that the id of the <div> is unique to the page.

The other elements may have ids Those ids must be in all uppercase and have a prefix that matches the widget id . For example,

<div id="KODA_">
<p id="KODA_BOSANDA">

The ADSAFE.go method gives the script access to a dom object that provides a limited interface to the widget's DOM tree.

Another ADsafe pattern allows the widget to load approved JavaScript libraries. All of the script tags in a <div> must be at the top level of the <div>.

<div id="WIDGETNAME_">
    html markup required by the widget
<script>
ADSAFE.id("WIDGETNAME_");
</script>
<script src="ADsafe approved url"></script>
<script>
ADSAFE.go("WIDGETNAME_", function (dom, lib) {
    "use strict";

// This is where the code for the widget is placed. It can access
// the document through the dom parameter, allowing it indirect
// access to html elements, allowing it to change content, styling,
// and behavior.

// Each library file can give itself a name. This script can access
// the library file as lib.name.

});
</script>
</div>

It uses the JSLint option {adsafe: true, fragment: true}.

The services provided through ADSAFE methods can include communication with the network and manipulation of the DOM. The ADSAFE methods are provided by the page to give the widgets restricted access to essential services. It is not safe to give a widget direct access to any DOM node because access to any DOM node gives access to the document object, which gives unrestricted access to the entire tree and to the network. It is safe to give a widget indirect access to the DOM through methods that assure that no capability leakage occurs.

In order for a widget to be approved by ADsafe, it may not make use of any global variables except the ADSAFE object (or other global variables that a site may designate). It may not define any global variables, and it may not contain any code that could give the guest code access to the window object or document object.

All ADsafe approved library files must conform to this pattern:

ADSAFE.lib("name", function (lib) {
    "use strict";

// This is where the code for the library module is placed. It cannot
// access the document unless the guest code passes the dom parameter
// to its methods. The optional lib parameter gives it access to the
// currently loaded libraries.

    return {

// Return an object containing the library module's privileged methods.
// The script can get access to this object at lib.name.

    };
});

It uses the JSLint option {adsafe: true, fragment: false}. A library file contains a call to ADSAFE.lib, which allows the file to identify itself and to pass an object to the guest code.

ADSAFE.lib can only be called at the top of a script file. It cannot be called from any other location. Calls to ADSAFE.lib must occur after the call to ADSAFE.id, but before the call to ADSAFE.go.

ADSAFE.id can only be called at the top of the widget's first script. It cannot be called from any other location.

ADSAFE.go can only be called from an inline script. It cannot be called from a file. It can only be called once. It must be called from the last script block in the fragment.

The id of the widget's containing <div> must exactly match the id passed to the ADSAFE.id and ADSAFE.go methods.

The ADsafe verifier is able to statically enforce all of these restrictions.

If the page wants to modify the dom and lib objects and the bunch prototype object that are given to the widget, it passes a function to the ADSAFE._intercept method. The function will be called before the function that is supplied with ADSAFE.go. This can be used to add or remove or modify the methods that are provided to the widget.

ADSAFE._intercept(function (id, dom, lib, bunch) {
    "use strict";

// Do not allow widgets to set position to absolute.
// This is to prevent phishing and other annoyances.

    var style = bunch.prototype.style;

    bunch.prototype.style = function (name, value) {
        if (name.toLowerCase() === 'position' &&
                value.toLowerCase() === 'absolute') {
            throw {
                name: 'error',
                message: 'position:absolute is not allowed'
            }
        }
        return style.apply(this, arguments);
    };
});

A page could allow inter-widget communication by providing communication methods to the lib object. A page could allow a method to change the src of a node.

The file adsafe.js contains the runtime component that provides the ADSAFE object, and should be loaded before all interceptors and widgets. The file template.html contains the template for a widget. The file template.js contains the template for a JavaScript library file.