gecko-dev/dom/manifest/ManifestObtainer.jsm

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

153 строки
4.7 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 2 public method:
*
* .contentObtainManifest(aContent) - used in content process
* .browserObtainManifest(aBrowser) - used in browser/parent process
*
* both return a promise. If successful, you get back a manifest object.
*
* Import it with URL:
* 'chrome://global/content/manifestMessages.js'
*
* e10s IPC message from this components are handled by:
* dom/ipc/manifestMessages.js
*
* Which is injected into every browser instance via browser.js.
*
* exported ManifestObtainer
*/
/* globals Components, Task, PromiseMessage, XPCOMUtils, ManifestProcessor, BrowserUtils*/
"use strict";
Bug 1514594: Part 3 - Change ChromeUtils.import API. *** Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8 This changes the behavior of ChromeUtils.import() to return an exports object, rather than a module global, in all cases except when `null` is passed as a second argument, and changes the default behavior not to pollute the global scope with the module's exports. Thus, the following code written for the old model: ChromeUtils.import("resource://gre/modules/Services.jsm"); is approximately the same as the following, in the new model: var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); Since the two behaviors are mutually incompatible, this patch will land with a scripted rewrite to update all existing callers to use the new model rather than the old. *** Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs This was done using the followng script: https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm *** Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D16747 *** Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16748 *** Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16749 *** Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs *** Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16750 --HG-- extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895 extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
2019-01-17 21:18:31 +03:00
const {PromiseMessage} = ChromeUtils.import("resource://gre/modules/PromiseMessage.jsm");
const {ManifestProcessor} = ChromeUtils.import("resource://gre/modules/ManifestProcessor.jsm");
var ManifestObtainer = { // jshint ignore:line
/**
* Public interface for obtaining a web manifest from a XUL browser, to use
* on the parent process.
* @param {XULBrowser} The browser to check for the manifest.
* @return {Promise<Object>} The processed manifest.
*/
async browserObtainManifest(aBrowser) {
const msgKey = "DOM:ManifestObtainer:Obtain";
if (!isXULBrowser(aBrowser)) {
throw new TypeError("Invalid input. Expected XUL browser.");
}
const mm = aBrowser.messageManager;
const {data: {success, result}} = await PromiseMessage.send(mm, msgKey);
if (!success) {
const error = toError(result);
throw error;
}
return result;
},
/**
* Public interface for obtaining a web manifest from a XUL browser.
* @param {Window} The content Window from which to extract the manifest.
* @return {Promise<Object>} The processed manifest.
*/
async contentObtainManifest(aContent) {
if (!aContent || isXULBrowser(aContent)) {
throw new TypeError("Invalid input. Expected a DOM Window.");
}
let manifest;
try {
manifest = await fetchManifest(aContent);
} catch (err) {
throw err;
}
return manifest;
},
};
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;
}
function isXULBrowser(aBrowser) {
if (!aBrowser || !aBrowser.namespaceURI || !aBrowser.localName) {
return false;
}
const XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
return (aBrowser.namespaceURI === XUL && aBrowser.localName === "browser");
}
/**
* Asynchronously processes the result of response after having fetched
* a manifest.
* @param {Response} aResp Response from fetch().
* @param {Window} aContentWindow The content window.
* @return {Promise<Object>} The processed manifest.
*/
const processResponse = async function(aResp, aContentWindow) {
const badStatus = aResp.status < 200 || aResp.status >= 300;
if (aResp.type === "error" || badStatus) {
const msg =
`Fetch error: ${aResp.status} - ${aResp.statusText} at ${aResp.url}`;
throw new Error(msg);
}
const text = await aResp.text();
const args = {
jsonText: text,
manifestURL: aResp.url,
docURL: aContentWindow.location.href,
};
const manifest = ManifestProcessor.process(args);
return manifest;
};
/**
* Asynchronously fetches a web manifest.
* @param {Window} a The content Window from where to extract the manifest.
* @return {Promise<Object>}
*/
const fetchManifest = async function(aWindow) {
if (!aWindow || aWindow.top !== aWindow) {
let msg = "Window must be a top-level browsing context.";
throw new Error(msg);
}
const elem = aWindow.document.querySelector("link[rel~='manifest']");
if (!elem || !elem.getAttribute("href")) {
let msg = `No manifest to fetch at ${aWindow.location}`;
throw new Error(msg);
}
// Throws on malformed URLs
const manifestURL = new aWindow.URL(elem.href, elem.baseURI);
const reqInit = {
mode: "cors",
};
if (elem.crossOrigin === "use-credentials") {
reqInit.credentials = "include";
}
const request = new aWindow.Request(manifestURL, reqInit);
request.overrideContentPolicyType(Ci.nsIContentPolicy.TYPE_WEB_MANIFEST);
let response;
try {
response = await aWindow.fetch(request);
} catch (err) {
throw err;
}
const manifest = await processResponse(response, aWindow);
return manifest;
};
var EXPORTED_SYMBOLS = ["ManifestObtainer"]; // jshint ignore:line