зеркало из https://github.com/mozilla/gecko-dev.git
93 строки
3.0 KiB
JavaScript
93 строки
3.0 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* ManifestObtainer is an implementation of:
|
|
* http://w3c.github.io/manifest/#obtaining
|
|
*
|
|
* Exposes public method `.obtainManifest(browserWindow)`, which returns
|
|
* a promise. If successful, you get back a manifest (string).
|
|
*
|
|
* For e10s compat, this JSM relies on the following to do
|
|
* the nessesary IPC:
|
|
* dom/ipc/manifestMessages.js
|
|
*
|
|
* whose internal URL is:
|
|
* 'chrome://global/content/manifestMessages.js'
|
|
*
|
|
* Which is injected into every browser instance via browser.js.
|
|
*
|
|
* BUG: https://bugzilla.mozilla.org/show_bug.cgi?id=1083410
|
|
* exported ManifestObtainer
|
|
*/
|
|
'use strict';
|
|
const MSG_KEY = 'DOM:ManifestObtainer:Obtain';
|
|
let messageCounter = 0;
|
|
// FIXME: Ideally, we would store a reference to the
|
|
// message manager in a weakmap instead of needing a
|
|
// browserMap. However, trying to store a messageManager
|
|
// results in a TypeError because of:
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=888600
|
|
const browsersMap = new WeakMap();
|
|
|
|
function ManifestObtainer() {}
|
|
|
|
ManifestObtainer.prototype = {
|
|
obtainManifest(aBrowserWindow) {
|
|
if (!aBrowserWindow) {
|
|
const err = new TypeError('Invalid input. Expected xul browser.');
|
|
return Promise.reject(err);
|
|
}
|
|
const mm = aBrowserWindow.messageManager;
|
|
const onMessage = function(aMsg) {
|
|
const msgId = aMsg.data.msgId;
|
|
const {
|
|
resolve, reject
|
|
} = browsersMap.get(aBrowserWindow).get(msgId);
|
|
browsersMap.get(aBrowserWindow).delete(msgId);
|
|
// If we we've processed all messages,
|
|
// stop listening.
|
|
if (!browsersMap.get(aBrowserWindow).size) {
|
|
browsersMap.delete(aBrowserWindow);
|
|
mm.removeMessageListener(MSG_KEY, onMessage);
|
|
}
|
|
if (aMsg.data.success) {
|
|
return resolve(aMsg.data.result);
|
|
}
|
|
reject(toError(aMsg.data.result));
|
|
};
|
|
// If we are not already listening for messages
|
|
// start listening.
|
|
if (!browsersMap.has(aBrowserWindow)) {
|
|
browsersMap.set(aBrowserWindow, new Map());
|
|
mm.addMessageListener(MSG_KEY, onMessage);
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
const msgId = messageCounter++;
|
|
browsersMap.get(aBrowserWindow).set(msgId, {
|
|
resolve: resolve,
|
|
reject: reject
|
|
});
|
|
mm.sendAsyncMessage(MSG_KEY, {
|
|
msgId: msgId
|
|
});
|
|
});
|
|
|
|
function toError(aErrorClone) {
|
|
let error;
|
|
switch (aErrorClone.name) {
|
|
case 'TypeError':
|
|
error = new TypeError();
|
|
break;
|
|
default:
|
|
error = new Error();
|
|
}
|
|
Object.getOwnPropertyNames(aErrorClone)
|
|
.forEach(name => error[name] = aErrorClone[name]);
|
|
return error;
|
|
}
|
|
}
|
|
};
|
|
this.ManifestObtainer = ManifestObtainer; // jshint ignore:line
|
|
this.EXPORTED_SYMBOLS = ['ManifestObtainer']; // jshint ignore:line
|