Title: Como criar um novo wrapper 

The primary focus of jShelter is to provide security and privacy oriented
wrappers of JavaScript APIs. As some of the code is very similar for each
wrapper, we use a unified approach to describe wrappers. The approach is
described below. This approach also helps to automatically modify `toString`
conversions of the wrapped APIs, i.e. a correctly written wrapper creates a
modified function but `wrapper.toString()` returns the original string.

[TOC]

## File structure

* `wrapping.js` provides main facilities for interacting with specific wrappers:
   * `add_wrappers()` has to be provided with all the wrappers. Hence, a typical
module with wrappers of a web standard APIS. ends with a call of
`add_wrappers(list_of_all_wrappers_defined_by_the_module)`.
   * `build_wrapping_code` contains all the registered wrappers. The keys are
referenced by the levels wrapper list. Do not modify the `build_wrapping_code`
variable directly, use `add_wrappers` instead.
   * The module also provides common functions used by the wrappers, e.g.
`rounding_function` and `noise_function`.
* `wrappingS-XYZ` are files dealing with APIs introduced by specific web or ECMA
standard. See the **naming conventions** for details on the XYZ part of the
name. See the **wrapper specification** section for the properties of the
wrapper objects.

## Naming conventions

jShelter adopted the naming conventions of the [Web API
Manager](https://github.com/pes10k/web-api-manager/tree/master/sources/standards).
See the paper:

Peter Snyder, Cynthia Taylor, and Chris Kanich, “[Most Websites Don’t Need to
Vibrate: A Cost–Benefit Approach to Improving Browser
Security](https://arxiv.org/abs/1708.08510),” in Proceedings of the [2017 ACM
Conference on Computer and Communications
Security](https://www.sigsac.org/ccs/CCS2017/), 2017.

## Wrapper specification

Once you are set with the file name for your wrappers, you can start coding. The
basic structure of the file is:

```js
(function() {
    // definition of common functions used by the wrappers bellow
    var wrappers = [
        {
            // wrapping object 1
        },
        {
            // wrapping object 2
        },
...
        {
            // wrapping object n
        },
    ]
    add_wrappers(wrappers);
})();
```

The content of the module should be in an IIFE so that it does not polute the
global namespace. The property values are strings that are generally interpreted
either as identifiers or JS code.

Each wrapping object must have the following mandatory properties:

* `parent_object` and `parent_object_property` are used to define the name of the
wrapping (`parent_object.parent_object_property`) that is referenced by level
wrappers. Additionally, it is used if `wrapper_prototype` is defined to provide
the object name to have the prototype changed. Finally, `Object.freeze` can be
optionally called on `parent_object.parent_object_property`.
* `apply_if` optionally provides a condition that needs to be fullfilled to apply
the wrapper. For example if a wrapper should be applied only when an API
already provides some information. For example,
`apply_if: "navigator.plugins.length > 0"`.
* `wrapped_objects` is a list of objects, each having the following properties (1
mandatory, 2 optional, typically, wrappers use one of the optional names in
the wrapper code to access the original result of the call):
   * `original_name` (*mandatory*) - the original name of the object to be wrapped.
Do not mention `window` here!
      * `wrapped_name` - the variable name that points to the actual original object.
Wrappers might need it for identity comparisons or other instance-specific use
cases. The variable name can be used by `wrapping_function_body`, `helping_code`
and other code fragments to reference the original object. Note that this name
is not available outside the code generated by this wrappper.
      * `callable_name` - is similar to the `wrapped_name` but the variable refers to a
proxy of the original object. The proxy intercepts calls and automatically
marshals parameters and return values. Wrappers MUST define `callable_name` if
the object is passed to other code like `Promise` objects or callbacks. The
variable is available only in the code generate by this wrapper. `callable_name`
is specifically **meant to be used for native methods and functions** which the
wrapper needs to call. This is especially important if it **accepts callback
arguments or returns `Promise` objects**: invoking them through their
`callable_name` automates complex steps otherwise required for [sandboxed
browser extensions to interact with web
pages](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts).

Generally speaking, use `wrapped_name` whenever you need to access the original
objects only inside the wrapper and you do not need to pass the object to other
code, such as `Promise` objects or callbacks. Compared to `callable_name`,
`wrapped_name` has less overhead and is the preferred way.

Each wrapping object can have the following optional properties:

* `wrapping_function_args` is a string that is used as an argument list for the
wrapping function. Typically this string reflects the parameters of the
original method, it can be an empty string, a list of parameters, such as
`"source, target, color"` or `"...args"`.
* `wrapping_function_body` specified the behaviour of the wrapped function. You
can provide a completely different implementation but often, you want to refer
to the original implementation (available in the variable `wrapped_name`) and
modify the original implementation.
* `wrapping_code_function_name` can be used to call the wrapping function from
the other code inside the wrapper. For example to create another wrapper
similar to the original wrapper.
* `wrapper_prototype` - if defined, `parent_object.parent_object_property`
prototype is set to the prototype identifier provided by `wrapper_prototype`.
* `original_function` if not provided, it defaults to
`parent_object.parent_object_property`. This name is used for overloading the
`toString` function. Instead of the wrapping code, `toString` returns the
content of the original function.
* `helping_code` provides you an option to define code available for both
`replacement` function and `post_wrapping_code`
* `replace_original_function` is used to control which function should be replaced
* `post_replacement_code` Allows to provide additional code with the access to
the original function and to the wrapped function
* `freeze` if set to `true` causes the API to be freezed. It should not be
necessary if the wrapping is performed at the right level of the object's
prototype chain (i.e. where the property to be modified was originally defined,
i.e. usually in the object's prototype). Use this option with caution, only if
strictly needed, because native APIs are configurable (otherwise our wrapping
couldn't work) and therefore freezing them introduces a "weirdness", exploitable
for fingerprinting.
* `post_wrapping_code` is a list of additional wrapping objects with a similar
structure to the wrappers, see the section bellow.

### Post wrapping code

Complex wrappers need to provide additional wrapping code.

You can make the generation of the post wrapping code generation conditional by
using `apply_if`, e.g.:

```js
                {
                    ...
                    apply_if: "!enableGeolocation",
                }
```

(`enableGeolocation` is a Booloean variable)

Currently jShelter supports additional wrapping of:

* Definition of a function (used, for example, to reintroduce `Date.now()`
function to the wrapped `Date` object)

```js
[
    {
        code_type: "function_define",
        original_function: "originalDateConstructor.now",
        parent_object: "window.Date",
        parent_object_property: "now",
        wrapping_function_args: "",
        wrapping_function_body: "return func(originalDateConstructor.now.call(Date), precision);",
    },
]
```

* Export a function from the wrapping namespace (currently not used, the
following code exposes the unwrapped, i.e. original, version of Date.now to
page scripts)

```js
[
    {
        code_type: "function_export",
        parent_object: "window.Date",
        parent_object_property: "now",
        export_function_name: "originalDateConstructor.now",
    },
]
```

* Redefine an object property (used to prevent leaking iframe properties to the
unwrapped objects):

```js
{
    code_type: "object_properties",
    parent_object: "HTMLIFrameElement.prototype",
    parent_object_property: "contentWindow",
    wrapped_objects: [
        {
            original_name: "HTMLIFrameElement.prototype.__lookupGetter__('contentWindow')",
            wrapped_name: "cw",
        },
    ],
    wrapped_properties: [
        {
            property_name: "get",
            property_value: `
                function() {
                    var parent=cw.call(this);
                    try {
                        parent.HTMLCanvasElement;
                    }
                    catch(d) {
                        return; // HTMLIFrameElement.contentWindow properties could not be accessed anyway
                    }
                    wrapping(parent);
                    return parent;
                }`,
        },
    ],
}
```

* Deleting a property (used when you want to completely disable an API):

```js
                {
                    code_type: "delete_properties",
                    parent_object: "navigator",
                    apply_if: "!enableGeolocation",
                    delete_properties: ["geolocation"],
                }
```

### The WrapHelper API

A `WrapHelper` object is globally available to wrappers code, exposing some
methods and properties which are mostly used internally by the code builders to
automate tasks such as handling [Firefox's content script
sandbox](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts)
or making replacement objects look as native as possible. However a few of them
may be useful to complex wrappers or in edge case not covered by `callable_name`
and other declarative object replacement / property definition wrapper
constructs:

* `WrapHelper.shared: {}` - a "bare" JavaScript object which a wrapper can use to
share information with other wrappers (e.g. to coordinate behavior between
related parts of the same API requiring multiple wrappings) by attaching its own
data objects as properties. **Warning**: namespacing is not enforced and up to
the wrapper implementor, but obviously recommended.
* `WrapHelper.overlay(obj, data)` - Proxies the prototype of the `obj` object in
order to return the properties of the `data` object as if they were native
properties (e.g. as if they were returned by getters on the prototype chain,
rather than defined on the instance). This allows spoofing some native objects
data in a less detectable / fingerprintable way than by using
`Object.defineProperty()`. See `wrappingS-MCS.js` for an example.
* `WrapHelper.forPage(obj)` - it's mostly used internally and transparently by
`code_builder.js`, but may be useful to very complex proxies in edge cases
needing to explicitly prepare an object/function created in [Firefox's sandboxed
content script
environment](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts)
to be consumed/called from the page context, and to make replacements for native
objects and functions provided by the wrappers look as much native as possible
(on Chromium, too). In most cases, however, this gets automated by the code
builders replacing Object methods with their WrapHelper counterpart in the
wrapper sources and by proxying "callable_name" function references through
`WrapHelper.pageAPI()` (see below).
* `WrapHelper.pageAPI(f)` - proxies the function/method f so that arguments and
return values, and especially callbacks and `Promise` objects, are recursively
managed in order to transparently marshal objects back and forth [Firefox's
sandbox for extensions
(https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts).
**Wrapper implementors should almost never need to use this API directly**,
since any function referenced via its "callable_name" goes automatically through
it.

### The generated wrapper structure

To get a better idea how the code is generated see the following pseudo code.
Please do not refer to any name created by the code builders from your wrapper.
Use your custom names. If it is not available, please, open an issue where you
explain what you are trying to achieve. It is probable that we will introduce a
new property that allows to provide your name to the code builders. The code
lives in an anonymous namespaces, so variables introduced here do not directly
leak to page scripts.

```js
// Define wrapped_name(s) variables holding the original JS objects
helping_code // if present
function wrapping_code_function_name(param) {
    // Store original function: either original_function which defaults to parent_object.parent_object_property
    function replacement(wrapping_function_args) {
        wrapping_function_body
    }
    if (replace_original_function)
        original_function = replacement
    else
        parent_object.parent_object_property = replacement
    // Modify toString
    post_replacement_code
}
wrapping_code_function_name(window if wrapping_code_function_call_window) // The function is called even if the name is not explicitely provided
// wrappings generated by post wrapping code
```

## Compiling the wrappers

Of course the wrappers need to be compiled to JavaScript before inserting the
code to page scripts. See `code_builders.js`.

## Registering a new wrapper

`fix_manifest.sh` automatically adds all modules with file name of `wrapping*.js`
to the manifest.json of the extension. There is no need for any additional
action.

## Register new wrapper to be used by the extension in a level or available in the
GUI.

See `levels.js` and its list `wrapping_groups.groups`. Once you add your wrapper
to an existing group or create a new group, the wrapper becomes available in the
built-in levels containing the group and in the GUI for custom levels.

## Describe the wrapper for Doxygen documentation

Describe what the wrapper tries to accomplish and its approach:

* Add Doxygen comment at the top of the file with the following structure:

```js
/** \file
 * \brief This file contains wrappers for the X API (link to the standard or MDN)
 * \ingroup wrappers
 *
 * Put at least one paragraph describing the goal of the wrapper. Describe a possible attack vector.
 * Link to further resources/readings.
 *
 * Describe the options of the wrapper. Mention examples when a user should want to use the
 *  available options.
 *
 * Describe any \note, \bug ór use other suitable Doxygen commands
 * (https://www.doxygen.nl/manual/commands.html)
 */
```

* Describe helping functions and `wrapping_function_body`
* Use Doxygen command `\fn fake wrapped.object` for each `wrapping_function_body`
* Use the following structure for function comments:

```js
/**
 * \brief Short description
 *
 * \param X Descripton
 * \param Y Descripton
 *
 * \returns Description
 *
 * Main description of the aim of the function, algorithm, etc.
 *
 * Describe any \note, \bug ór use other suitable Doxygen commands
 * (https://www.doxygen.nl/manual/commands.html)
 */
```

## Write unit tests or integration tests for the wrapper

Follow instructions for [unit testing](/unit_tests/) and [integration
testing](/integration_tests/).
