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 id
s Those id
s
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 pass 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.