When developing a web app for use with WebAppFind, it is even more important to protect the privacy and security of your users since your web app may inadvertently be exposing data they have passed in from their desktops and have the potential to even overwrite their data.
- Please note the security comments within the API section comments for
details on how to make communication with the add-on safely (via
postMessage
). - As with any web app, do not trust user-supplied data (e.g., don't paste
in using
innerHTML
), especially if that data is supplied via the URL (to which hackers can link or cause their visitors to visit such pages). See https://en.wikipedia.org/wiki/Cross-site_scripting for some of the concerns. - There should be no side effects upon the opening of a link to your web app (and whether or not your app is opened as a URL, protocol, or protocol-opened-through-WebAppFind), so for example, you should not automatically save file contents back to disk (at least not without user approval). (An exception might be made in the future if AsYouWish is installed and the user wished to bookmark privileged but harmless or per-use-confirmed processes, e.g., to visit a link to package up some files as part of a build process.) See https://en.wikipedia.org/wiki/Cross-site_request_forgery for some of the concerns.
The API is detailed below. You may wish to use the utility webappfind.js
within webappfind-demos-samples
for a slightly easier-to-use API.
See also Executable Builder for that API.
The 'view' type of message (see the example below) will be sent to the web
app when a desktop file has been opened in the "view" or "edit" mode. This
message delivers the file contents (whether in binary form or not) to the
web app. (If binary
is set to true, the content
will contain an array
that can be used for building a typed array.)
let pathID; // We might use an array to track multiple path IDs within the same app (once WebAppFind may be modified to support this capability!)
window.addEventListener('message', function ({origin, data}) {
// `data` might be set to something like:
// {type: 'view', pathID: '{1e5c754e-95d3-4431-a08c-5364db753d97}', content: 'the loaded file contents will be here!'}
let type, pathID, content;
try {
({type, pathID, content} = data); // May throw if data is not an object
if (origin !== location.origin || // We are only interested in a message sent as though within this URL by our browser add-on
type === 'save' // Avoid our post below (other messages might be possible in the future which may also need to be excluded if your subsequent code makes assumptions on the type of message this is)
) {
return;
}
} catch (err) {
return;
}
if (type === 'view') {
// We remember the pathID in case we are in "edit" mode which requires a pathID for saving back to disk
// Do something with `content` like adding it to a textarea, etc.
}
});
Only windows with the URI approved by the process detailed above will be able to successfully receive such messages (and only for files explicitly supplied (in that session)).
A save will be performed by sending a 'save' type message to the add-on (see the code below).
A pathID will be needed when making a save of file contents back to
the add-on (which will save back to disk). You can obtain this before
making saves, by listening for the 'view' message (described
under "API: reading file contents" above); the pathID
value of the
webappfind
object argument (previouslySavedPathIDFromViewEvent
) will
contain this information.
This pathID
is intended to allow for sites to handle multiple files in a
single session (although WebAppFind currently will always open the file
in a new tab as a new instance).
Note the important comment below about ensuring your users' privacy.
Once a save has been performed, a message, 'save-end', will be sent from the add-on back to the WebAppFind-opened app (in case the app would like to inform the user in some manner).
// For your user's privacy, you should only post the
// file contents to this page itself (and this save
// will be picked up by the browser add-on), so do
// NOT change the second argument of `location.origin`.
// You should only call this when the user has indicated
// they wish to make a save such as if they have approved
// draft auto-saving or when manually clicking a save button.
window.postMessage({
webappfind: {
type: 'save',
pathID: previouslySavedPathIDFromViewEvent,
content: dataToSaveAsString
}
}, location.origin);
Only windows with the URI approved by the process detailed above will be able to successfully save such messages (and only for files explicitly supplied (in that session)).
Although you are free to define your own file types and custom modes, in order to prevent future conflicts, it is recommended that you register your file types, arguments and custom modes (or at least namespace them well).