mirror of
https://github.com/servo/servo.git
synced 2025-08-28 08:38:20 +01:00
Update web-platform-tests to revision d3cf77a7b8c20c678b725238eaa8a72eca3787ae
This commit is contained in:
parent
880f3b8b7a
commit
efca990ffe
541 changed files with 8000 additions and 2276 deletions
|
@ -5,6 +5,133 @@
|
|||
* method's JSDoc.
|
||||
*/
|
||||
|
||||
// ===============================================================
|
||||
// Types
|
||||
// ===============================================================
|
||||
// Objects of the following types are used to represent what kind of
|
||||
// subresource requests should be sent with what kind of policies,
|
||||
// from what kind of possibly nested source contexts.
|
||||
// The objects are represented as JSON objects (not JavaScript/Python classes
|
||||
// in a strict sense) to be passed between JavaScript/Python code.
|
||||
|
||||
// Note: So far this document covers:
|
||||
// - resources/common.js : client-side test infra code
|
||||
// - scope/ - server-side scripts that serves nested source contexts
|
||||
// but doesn't cover:
|
||||
// - tools/ - generator scripts that generates top-level HTML documents.
|
||||
// There are some policies only handled by generators (e.g. mixed-content
|
||||
// opt-ins) and not yet covered by the docs here.
|
||||
|
||||
/**
|
||||
@typedef PolicyDelivery
|
||||
@type {object}
|
||||
Referrer policy etc. can be applied/delivered in several ways.
|
||||
A PolicyDelivery object specifies what policy is delivered and how.
|
||||
|
||||
@property {string} deliveryType
|
||||
Specifies how the policy is delivered.
|
||||
The valid deliveryType are:
|
||||
|
||||
"attr"
|
||||
[A] DOM attributes e.g. referrerPolicy.
|
||||
|
||||
"rel-noref"
|
||||
[A] <link rel="noreferrer"> (referrer-policy only).
|
||||
|
||||
"http-rp"
|
||||
[B] HTTP response headers.
|
||||
|
||||
"meta"
|
||||
[B] <meta> elements.
|
||||
|
||||
@property {string} key
|
||||
@property {string} value
|
||||
Specifies what policy to be delivered. The valid keys are:
|
||||
|
||||
"referrerPolicy"
|
||||
Referrer Policy
|
||||
https://w3c.github.io/webappsec-referrer-policy/
|
||||
Valid values are those listed in
|
||||
https://w3c.github.io/webappsec-referrer-policy/#referrer-policy
|
||||
(except that "" is represented as null/None)
|
||||
|
||||
A PolicyDelivery can be specified in several ways:
|
||||
|
||||
- (for [A]) Associated with an individual subresource request and
|
||||
specified in `Subresource.policies`,
|
||||
e.g. referrerPolicy attributes of DOM elements.
|
||||
This is handled in invokeRequest().
|
||||
|
||||
- (for [B]) Associated with an nested environmental settings object and
|
||||
specified in `SourceContext.policies`,
|
||||
e.g. HTTP referrer-policy response headers of HTML/worker scripts.
|
||||
This is handled in server-side under /common/security-features/scope/.
|
||||
|
||||
- (for [B]) Associated with the top-level HTML document.
|
||||
This is handled by the generators.d
|
||||
*/
|
||||
|
||||
/**
|
||||
@typedef Subresource
|
||||
@type {object}
|
||||
A Subresource represents how a subresource request is sent.
|
||||
|
||||
@property{SubresourceType} subresourceType
|
||||
How the subresource request is sent,
|
||||
e.g. "img-tag" for sending a request via <img src>.
|
||||
See the keys of `subresourceMap` for valid values.
|
||||
|
||||
@property{string} url
|
||||
subresource's URL.
|
||||
Typically this is constructed by getRequestURLs() below.
|
||||
|
||||
@property{PolicyDelivery} policyDeliveries
|
||||
Policies delivered specific to the subresource request.
|
||||
*/
|
||||
|
||||
/**
|
||||
@typedef SourceContext
|
||||
@type {object}
|
||||
Requests can be possibly sent from various kinds of source contexts, i.e.
|
||||
fetch client's environment settings objects:
|
||||
top-level windows, iframes, or workers.
|
||||
A SourceContext object specifies one environment settings object, and
|
||||
an Array<SourceContext> specifies a possibly nested context,
|
||||
from the outer-most to inner-most environment settings objects.
|
||||
|
||||
For example:
|
||||
[{sourceContextType: "srcdoc"}, {sourceContextType: "classic-worker"}]
|
||||
means that a subresource request is to be sent from
|
||||
a classic dedicated worker created from <iframe srcdoc>
|
||||
inside the top-level HTML document.
|
||||
Note: the top-level document is not included in the array and
|
||||
is assumed implicitly.
|
||||
|
||||
SourceContext (or Array<SourceContext>) is set based on
|
||||
the fetch client's settings object that is used for the subresource request,
|
||||
NOT on module map settings object, and
|
||||
NOT on the inner-most settings object that appears in the test.
|
||||
For example, Array<SourceContext> is `[]` (indicating the top Window)
|
||||
for `worker.js`
|
||||
- When it is the root worker script: `new Worker('worker.js')`, or
|
||||
- When it is imported from the root worker script:
|
||||
`new Worker('top.js', {type: 'module'})`
|
||||
where `top.js` has `import 'worker.js'`.
|
||||
because the request for `worker.js` uses the Window as its fetch client's
|
||||
settings object, while a WorkerGlobalScope is created though.
|
||||
|
||||
@property {string} sourceContextType
|
||||
Kind of the source context to be used.
|
||||
Valid values are the keys of `sourceContextMap` below.
|
||||
|
||||
@property {Array<PolicyDelivery>} policyDeliveries
|
||||
A list of PolicyDelivery applied to the source context.
|
||||
*/
|
||||
|
||||
// ===============================================================
|
||||
// General utility functions
|
||||
// ===============================================================
|
||||
|
||||
function timeoutPromise(t, ms) {
|
||||
return new Promise(resolve => { t.step_timeout(resolve, ms); });
|
||||
}
|
||||
|
@ -70,8 +197,16 @@ function xhrRequest(url, responseType) {
|
|||
*/
|
||||
function setAttributes(el, attrs) {
|
||||
attrs = attrs || {}
|
||||
for (var attr in attrs)
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
for (var attr in attrs) {
|
||||
if (attr !== 'src')
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
// Workaround for Chromium: set <img>'s src attribute after all other
|
||||
// attributes to ensure the policy is applied.
|
||||
for (var attr in attrs) {
|
||||
if (attr === 'src')
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,52 +337,79 @@ function wrapResult(server_data) {
|
|||
}
|
||||
}
|
||||
|
||||
// `requestVia*()` functions return promises that are resolved on successful
|
||||
// requests with objects with the following keys:
|
||||
// - `headers`: HTTP request headers sent to server.
|
||||
// - `referrer`: Referrer.
|
||||
// - `location`: The URL of the subresource.
|
||||
//
|
||||
// Category 1:
|
||||
// `headers`: set.
|
||||
// `referrer`: set via `document.referrer`.
|
||||
// `location`: set via `document.location`.
|
||||
// See `template/document.html.template`.
|
||||
// Category 2:
|
||||
// `headers`: set.
|
||||
// `referrer`: set to `headers.referer` by `wrapResult()`.
|
||||
// `location`: not set.
|
||||
// Category 3:
|
||||
// All the keys listed above are NOT set.
|
||||
//
|
||||
// -------------------------------- -------- --------------------------
|
||||
// Function name Category Used in
|
||||
// -------- ------- ---------
|
||||
// referrer mixed- upgrade-
|
||||
// policy content insecure-
|
||||
// policy content request
|
||||
// -------------------------------- -------- -------- ------- ---------
|
||||
// requestViaAnchor 1 Y Y -
|
||||
// requestViaArea 1 Y Y -
|
||||
// requestViaAudio 3 - Y -
|
||||
// requestViaDedicatedWorker 2 Y Y Y
|
||||
// requestViaFetch 2 Y Y -
|
||||
// requestViaForm 3 - Y -
|
||||
// requestViaIframe 1 Y Y -
|
||||
// requestViaImage 3 - Y -
|
||||
// requestViaImageForReferrerPolicy 2 Y - -
|
||||
// requestViaLinkPrefetch 3 - Y -
|
||||
// requestViaLinkStylesheet 3 - Y -
|
||||
// requestViaObject 3 - Y -
|
||||
// requestViaPicture 3 - Y -
|
||||
// requestViaScript 2 Y Y -
|
||||
// requestViaSendBeacon 3 - Y -
|
||||
// requestViaSharedWorker 2 Y - -
|
||||
// requestViaVideo 3 - Y -
|
||||
// requestViaWebSocket 3 - Y -
|
||||
// requestViaWorklet 3 - Y Y
|
||||
// requestViaXhr 2 Y Y -
|
||||
// -------------------------------- -------- -------- ------- ---------
|
||||
// ===============================================================
|
||||
// Subresources
|
||||
// ===============================================================
|
||||
|
||||
/**
|
||||
@typedef RequestResult
|
||||
@type {object}
|
||||
Represents the result of sending an request.
|
||||
All properties are optional. See the comments for
|
||||
requestVia*() and invokeRequest() below to see which properties are set.
|
||||
|
||||
@property {Array<Object<string, string>>} headers
|
||||
HTTP request headers sent to server.
|
||||
@property {string} referrer - Referrer.
|
||||
@property {string} location - The URL of the subresource.
|
||||
@property {string} sourceContextUrl
|
||||
the URL of the global object where the actual request is sent.
|
||||
*/
|
||||
|
||||
/**
|
||||
requestVia*(url, additionalAttributes) functions send a subresource
|
||||
request from the current environment settings object.
|
||||
|
||||
@param {string} url
|
||||
The URL of the subresource.
|
||||
@param {Object<string, string>} additionalAttributes
|
||||
Additional attributes set to DOM elements
|
||||
(element-initiated requests only).
|
||||
|
||||
@returns {Promise} that are resolved with a RequestResult object
|
||||
on successful requests.
|
||||
|
||||
- Category 1:
|
||||
`headers`: set.
|
||||
`referrer`: set via `document.referrer`.
|
||||
`location`: set via `document.location`.
|
||||
See `template/document.html.template`.
|
||||
- Category 2:
|
||||
`headers`: set.
|
||||
`referrer`: set to `headers.referer` by `wrapResult()`.
|
||||
`location`: not set.
|
||||
- Category 3:
|
||||
All the keys listed above are NOT set.
|
||||
`sourceContextUrl` is not set here.
|
||||
|
||||
-------------------------------- -------- --------------------------
|
||||
Function name Category Used in
|
||||
-------- ------- ---------
|
||||
referrer mixed- upgrade-
|
||||
policy content insecure-
|
||||
policy content request
|
||||
-------------------------------- -------- -------- ------- ---------
|
||||
requestViaAnchor 1 Y Y -
|
||||
requestViaArea 1 Y Y -
|
||||
requestViaAudio 3 - Y -
|
||||
requestViaDedicatedWorker 2 Y Y Y
|
||||
requestViaFetch 2 Y Y -
|
||||
requestViaForm 3 - Y -
|
||||
requestViaIframe 1 Y Y -
|
||||
requestViaImage 2 Y Y -
|
||||
requestViaLinkPrefetch 3 - Y -
|
||||
requestViaLinkStylesheet 3 - Y -
|
||||
requestViaObject 3 - Y -
|
||||
requestViaPicture 3 - Y -
|
||||
requestViaScript 2 Y Y -
|
||||
requestViaSendBeacon 3 - Y -
|
||||
requestViaSharedWorker 2 Y - -
|
||||
requestViaVideo 3 - Y -
|
||||
requestViaWebSocket 3 - Y -
|
||||
requestViaWorklet 3 - Y Y
|
||||
requestViaXhr 2 Y Y -
|
||||
-------------------------------- -------- -------- ------- ---------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new iframe, binds load and error events, sets the src attribute and
|
||||
|
@ -274,40 +436,23 @@ function requestViaIframe(url, additionalAttributes) {
|
|||
* @param {string} url The src for the image.
|
||||
* @return {Promise} The promise for success/error events.
|
||||
*/
|
||||
function requestViaImage(url) {
|
||||
return createRequestViaElement("img", {"src": url}, document.body);
|
||||
function requestViaImage(url, additionalAttributes) {
|
||||
const img = createElement(
|
||||
"img",
|
||||
// crossOrigin attribute is added to read the pixel data of the response.
|
||||
Object.assign({"src": url, "crossOrigin": "Anonymous"}, additionalAttributes),
|
||||
document.body, true);
|
||||
return img.eventPromise.then(() => wrapResult(decodeImageData(img)));
|
||||
}
|
||||
|
||||
// Helpers for requestViaImageForReferrerPolicy().
|
||||
function loadImageInWindow(src, attributes, w) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var image = new w.Image();
|
||||
image.crossOrigin = "Anonymous";
|
||||
image.onload = function() {
|
||||
resolve(image);
|
||||
};
|
||||
// Helper for requestViaImage().
|
||||
function decodeImageData(img) {
|
||||
var canvas = document.createElement("canvas");
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(img, 0, 0);
|
||||
var imgData = context.getImageData(0, 0, img.clientWidth, img.clientHeight);
|
||||
const rgba = imgData.data;
|
||||
|
||||
// Extend element with attributes. (E.g. "referrerPolicy" or "rel")
|
||||
if (attributes) {
|
||||
for (var attr in attributes) {
|
||||
image[attr] = attributes[attr];
|
||||
}
|
||||
}
|
||||
|
||||
image.src = src;
|
||||
w.document.body.appendChild(image)
|
||||
});
|
||||
}
|
||||
|
||||
function extractImageData(img) {
|
||||
var canvas = document.createElement("canvas");
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(img, 0, 0);
|
||||
var imgData = context.getImageData(0, 0, img.clientWidth, img.clientHeight);
|
||||
return imgData.data;
|
||||
}
|
||||
|
||||
function decodeImageData(rgba) {
|
||||
let decodedBytes = new Uint8ClampedArray(rgba.length);
|
||||
let decodedLength = 0;
|
||||
|
||||
|
@ -349,62 +494,6 @@ function decodeImageData(rgba) {
|
|||
return JSON.parse(string_data);
|
||||
}
|
||||
|
||||
// A variant of requestViaImage for referrer policy tests.
|
||||
// This tests many patterns of <iframe>s to test referrer policy inheritance.
|
||||
// TODO(https://crbug.com/906850): Merge this into requestViaImage().
|
||||
// <iframe>-related code should be moved outside requestViaImage*().
|
||||
function requestViaImageForReferrerPolicy(url, attributes, referrerPolicy) {
|
||||
// For images, we'll test:
|
||||
// - images in a `srcdoc` frame to ensure that it uses the referrer
|
||||
// policy of its parent,
|
||||
// - images in a top-level document,
|
||||
// - and images in a `srcdoc` frame with its own referrer policy to
|
||||
// override its parent.
|
||||
|
||||
var iframeWithoutOwnPolicy = document.createElement('iframe');
|
||||
var noSrcDocPolicy = new Promise((resolve, reject) => {
|
||||
iframeWithoutOwnPolicy.srcdoc = "Hello, world.";
|
||||
iframeWithoutOwnPolicy.onload = resolve;
|
||||
document.body.appendChild(iframeWithoutOwnPolicy);
|
||||
})
|
||||
.then(() => {
|
||||
var nextUrl = url + "&cache_destroyer2=" + (new Date()).getTime();
|
||||
return loadImageInWindow(nextUrl, attributes,
|
||||
iframeWithoutOwnPolicy.contentWindow);
|
||||
})
|
||||
.then(function (img) {
|
||||
return decodeImageData(extractImageData(img));
|
||||
});
|
||||
|
||||
// Give a srcdoc iframe a referrer policy different from the top-level page's policy.
|
||||
var iframePolicy = (referrerPolicy === "no-referrer") ? "unsafe-url" : "no-referrer";
|
||||
var iframeWithOwnPolicy = document.createElement('iframe');
|
||||
var srcDocPolicy = new Promise((resolve, reject) => {
|
||||
iframeWithOwnPolicy.srcdoc = "<meta name='referrer' content='" + iframePolicy + "'>Hello world.";
|
||||
iframeWithOwnPolicy.onload = resolve;
|
||||
document.body.appendChild(iframeWithOwnPolicy);
|
||||
})
|
||||
.then(() => {
|
||||
var nextUrl = url + "&cache_destroyer3=" + (new Date()).getTime();
|
||||
return loadImageInWindow(nextUrl, null,
|
||||
iframeWithOwnPolicy.contentWindow);
|
||||
})
|
||||
.then(function (img) {
|
||||
return decodeImageData(extractImageData(img));
|
||||
});
|
||||
|
||||
var pagePolicy = loadImageInWindow(url, attributes, window)
|
||||
.then(function (img) {
|
||||
return decodeImageData(extractImageData(img));
|
||||
});
|
||||
|
||||
return Promise.all([noSrcDocPolicy, srcDocPolicy, pagePolicy]).then(values => {
|
||||
assert_equals(values[0].headers.referer, values[2].headers.referer, "Referrer inside 'srcdoc' without its own policy should be the same as embedder's referrer.");
|
||||
assert_equals((iframePolicy === "no-referrer" ? undefined : document.location.href), values[1].headers.referer, "Referrer inside 'srcdoc' should use the iframe's policy if it has one");
|
||||
return wrapResult(values[2]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a new XHR GET request to provided URL.
|
||||
* @param {string} url The endpoint URL for the XHR.
|
||||
|
@ -745,6 +834,14 @@ function requestViaWebSocket(url) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@typedef SubresourceType
|
||||
@type {string}
|
||||
|
||||
Represents how a subresource is sent.
|
||||
The keys of `subresourceMap` below are the valid values.
|
||||
*/
|
||||
|
||||
// Subresource paths and invokers.
|
||||
const subresourceMap = {
|
||||
"a-tag": {
|
||||
|
@ -778,7 +875,6 @@ const subresourceMap = {
|
|||
"img-tag": {
|
||||
path: "/common/security-features/subresource/image.py",
|
||||
invoker: requestViaImage,
|
||||
invokerForReferrerPolicy: requestViaImageForReferrerPolicy,
|
||||
},
|
||||
"link-css-tag": {
|
||||
path: "/common/security-features/subresource/empty.py",
|
||||
|
@ -854,6 +950,35 @@ for (const workletType of ['animation', 'audio', 'layout', 'paint']) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@typedef RedirectionType
|
||||
@type {string}
|
||||
|
||||
Represents what redirects should occur to the subresource request
|
||||
after initial request.
|
||||
See preprocess_redirection() in
|
||||
/common/security-features/subresource/subresource.py for valid values.
|
||||
*/
|
||||
|
||||
/**
|
||||
Construct subresource (and related) URLs.
|
||||
|
||||
@param {SubresourceType} subresourceType
|
||||
@param {OriginType} originType
|
||||
@param {RedirectionType} redirectionType
|
||||
@returns {object} with following properties:
|
||||
{string} testUrl
|
||||
The subresource request URL.
|
||||
{string} announceUrl
|
||||
{string} assertUrl
|
||||
The URLs to be used for detecting whether `testUrl` is actually sent
|
||||
to the server.
|
||||
1. Fetch `announceUrl` first,
|
||||
2. then possibly fetch `testUrl`, and
|
||||
3. finally fetch `assertUrl`.
|
||||
The fetch result of `assertUrl` should indicate whether
|
||||
`testUrl` is actually sent to the server or not.
|
||||
*/
|
||||
function getRequestURLs(subresourceType, originType, redirectionType) {
|
||||
const key = guid();
|
||||
const value = guid();
|
||||
|
@ -875,6 +1000,122 @@ function getRequestURLs(subresourceType, originType, redirectionType) {
|
|||
};
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// Source Context
|
||||
// ===============================================================
|
||||
// Requests can be sent from several source contexts,
|
||||
// such as the main documents, iframes, workers, or so,
|
||||
// possibly nested, and possibly with <meta>/http headers added.
|
||||
// invokeRequest() and invokeFrom*() functions handles
|
||||
// SourceContext-related setup in client-side.
|
||||
|
||||
/**
|
||||
invokeRequest() invokes a subresource request
|
||||
(specified as `subresource`)
|
||||
from a (possibly nested) environment settings object
|
||||
(specified as `sourceContextList`).
|
||||
|
||||
For nested contexts, invokeRequest() calls an invokeFrom*() function
|
||||
that creates a nested environment settings object using
|
||||
/common/security-features/scope/, which calls invokeRequest()
|
||||
again inside the nested environment settings object.
|
||||
This cycle continues until all specified
|
||||
nested environment settings object are created, and
|
||||
finally invokeRequest() calls a requestVia*() function to start the
|
||||
subresource request from the inner-most environment settings object.
|
||||
|
||||
@param {Subresource} subresource
|
||||
@param {Array<SourceContext>} sourceContextList
|
||||
|
||||
@returns {Promise} A promise that is resolved with an RequestResult object.
|
||||
`sourceContextUrl` is always set. For whether other properties are set,
|
||||
see the comments for requestVia*() above.
|
||||
*/
|
||||
function invokeRequest(subresource, sourceContextList) {
|
||||
if (sourceContextList.length === 0) {
|
||||
// No further nested global objects. Send the subresource request here.
|
||||
|
||||
const additionalAttributes = {};
|
||||
/** @type {PolicyDelivery} policyDelivery */
|
||||
for (const policyDelivery of (subresource.policyDeliveries || [])) {
|
||||
// Depending on the delivery method, extend the subresource element with
|
||||
// these attributes.
|
||||
if (policyDelivery.deliveryType === "attr") {
|
||||
additionalAttributes[policyDelivery.key] = policyDelivery.value;
|
||||
} else if (policyDelivery.deliveryType === "rel-noref") {
|
||||
additionalAttributes["rel"] = "noreferrer";
|
||||
}
|
||||
}
|
||||
|
||||
return subresourceMap[subresource.subresourceType].invoker(
|
||||
subresource.url,
|
||||
additionalAttributes)
|
||||
.then(result => Object.assign(
|
||||
{sourceContextUrl: location.toString()},
|
||||
result));
|
||||
}
|
||||
|
||||
// Defines invokers for each valid SourceContext.sourceContextType.
|
||||
const sourceContextMap = {
|
||||
"srcdoc": { // <iframe srcdoc></iframe>
|
||||
invoker: invokeFromIframe,
|
||||
},
|
||||
"iframe": { // <iframe src="same-origin-URL"></iframe>
|
||||
invoker: invokeFromIframe,
|
||||
},
|
||||
};
|
||||
|
||||
return sourceContextMap[sourceContextList[0].sourceContextType].invoker(
|
||||
subresource, sourceContextList);
|
||||
}
|
||||
|
||||
/**
|
||||
invokeFrom*() functions are helper functions with the same parameters
|
||||
and return values as invokeRequest(), that are tied to specific types
|
||||
of top-most environment settings objects.
|
||||
For example, invokeFromIframe() is the helper function for the cases where
|
||||
sourceContextList[0] is an iframe.
|
||||
*/
|
||||
|
||||
function invokeFromIframe(subresource, sourceContextList) {
|
||||
const currentSourceContext = sourceContextList.shift();
|
||||
const frameUrl =
|
||||
"/common/security-features/scope/document.py?policyDeliveries=" +
|
||||
encodeURIComponent(JSON.stringify(
|
||||
currentSourceContext.policyDeliveries || []));
|
||||
|
||||
let promise;
|
||||
if (currentSourceContext.sourceContextType === 'srcdoc') {
|
||||
promise = fetch(frameUrl)
|
||||
.then(r => r.text())
|
||||
.then(srcdoc => {
|
||||
return createElement("iframe", {srcdoc: srcdoc}, document.body, true);
|
||||
});
|
||||
} else if (currentSourceContext.sourceContextType === 'iframe') {
|
||||
promise = Promise.resolve(
|
||||
createElement("iframe", {src: frameUrl}, document.body, true));
|
||||
}
|
||||
|
||||
return promise
|
||||
.then(iframe => {
|
||||
return iframe.eventPromise
|
||||
.then(() => {
|
||||
const promise = bindEvents2(
|
||||
window, "message", iframe, "error", window, "error");
|
||||
iframe.contentWindow.postMessage(
|
||||
{subresource: subresource,
|
||||
sourceContextList: sourceContextList},
|
||||
"*");
|
||||
return promise;
|
||||
})
|
||||
.then(event => {
|
||||
if (event.data.error)
|
||||
return Promise.reject(event.data.error);
|
||||
return event.data;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// SanityChecker does nothing in release mode. See sanity-checker.js for debug
|
||||
// mode.
|
||||
function SanityChecker() {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue