How to use wssRawPort method in wpt

Best JavaScript code snippet using wpt

common.sub.js

Source:common.sub.js Github

copy

Full Screen

1/**2 * @fileoverview Utilities for mixed-content in web-platform-tests.3 * @author burnik@google.com (Kristijan Burnik)4 * Disclaimer: Some methods of other authors are annotated in the corresponding5 * method's JSDoc.6 */7// ===============================================================8// Types9// ===============================================================10// Objects of the following types are used to represent what kind of11// subresource requests should be sent with what kind of policies,12// from what kind of possibly nested source contexts.13// The objects are represented as JSON objects (not JavaScript/Python classes14// in a strict sense) to be passed between JavaScript/Python code.15//16// See also common/security-features/Types.md for high-level description.17/**18 @typedef PolicyDelivery19 @type {object}20 Referrer policy etc. can be applied/delivered in several ways.21 A PolicyDelivery object specifies what policy is delivered and how.22 @property {string} deliveryType23 Specifies how the policy is delivered.24 The valid deliveryType are:25 "attr"26 [A] DOM attributes e.g. referrerPolicy.27 "rel-noref"28 [A] <link rel="noreferrer"> (referrer-policy only).29 "http-rp"30 [B] HTTP response headers.31 "meta"32 [B] <meta> elements.33 @property {string} key34 @property {string} value35 Specifies what policy to be delivered. The valid keys are:36 "referrerPolicy"37 Referrer Policy38 https://w3c.github.io/webappsec-referrer-policy/39 Valid values are those listed in40 https://w3c.github.io/webappsec-referrer-policy/#referrer-policy41 (except that "" is represented as null/None)42 A PolicyDelivery can be specified in several ways:43 - (for [A]) Associated with an individual subresource request and44 specified in `Subresource.policies`,45 e.g. referrerPolicy attributes of DOM elements.46 This is handled in invokeRequest().47 - (for [B]) Associated with an nested environmental settings object and48 specified in `SourceContext.policies`,49 e.g. HTTP referrer-policy response headers of HTML/worker scripts.50 This is handled in server-side under /common/security-features/scope/.51 - (for [B]) Associated with the top-level HTML document.52 This is handled by the generators.d53*/54/**55 @typedef Subresource56 @type {object}57 A Subresource represents how a subresource request is sent.58 @property{SubresourceType} subresourceType59 How the subresource request is sent,60 e.g. "img-tag" for sending a request via <img src>.61 See the keys of `subresourceMap` for valid values.62 @property{string} url63 subresource's URL.64 Typically this is constructed by getRequestURLs() below.65 @property{PolicyDelivery} policyDeliveries66 Policies delivered specific to the subresource request.67*/68/**69 @typedef SourceContext70 @type {object}71 @property {string} sourceContextType72 Kind of the source context to be used.73 Valid values are the keys of `sourceContextMap` below.74 @property {Array<PolicyDelivery>} policyDeliveries75 A list of PolicyDelivery applied to the source context.76*/77// ===============================================================78// General utility functions79// ===============================================================80function timeoutPromise(t, ms) {81 return new Promise(resolve => { t.step_timeout(resolve, ms); });82}83/**84 * Normalizes the target port for use in a URL. For default ports, this is the85 * empty string (omitted port), otherwise it's a colon followed by the port86 * number. Ports 80, 443 and an empty string are regarded as default ports.87 * @param {number} targetPort The port to use88 * @return {string} The port portion for using as part of a URL.89 */90function getNormalizedPort(targetPort) {91 return ([80, 443, ""].indexOf(targetPort) >= 0) ? "" : ":" + targetPort;92}93/**94 * Creates a GUID.95 * See: https://en.wikipedia.org/wiki/Globally_unique_identifier96 * Original author: broofa (http://www.broofa.com/)97 * Sourced from: http://stackoverflow.com/a/2117523/494971598 * @return {string} A pseudo-random GUID.99 */100function guid() {101 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {102 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);103 return v.toString(16);104 });105}106/**107 * Initiates a new XHR via GET.108 * @param {string} url The endpoint URL for the XHR.109 * @param {string} responseType Optional - how should the response be parsed.110 * Default is "json".111 * See: https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetype112 * @return {Promise} A promise wrapping the success and error events.113 */114function xhrRequest(url, responseType) {115 return new Promise(function(resolve, reject) {116 var xhr = new XMLHttpRequest();117 xhr.open('GET', url, true);118 xhr.responseType = responseType || "json";119 xhr.addEventListener("error", function() {120 reject(Error("Network Error"));121 });122 xhr.addEventListener("load", function() {123 if (xhr.status != 200)124 reject(Error(xhr.statusText));125 else126 resolve(xhr.response);127 });128 xhr.send();129 });130}131/**132 * Sets attributes on a given DOM element.133 * @param {DOMElement} element The element on which to set the attributes.134 * @param {object} An object with keys (serving as attribute names) and values.135 */136function setAttributes(el, attrs) {137 attrs = attrs || {}138 for (var attr in attrs) {139 if (attr !== 'src')140 el.setAttribute(attr, attrs[attr]);141 }142 // Workaround for Chromium: set <img>'s src attribute after all other143 // attributes to ensure the policy is applied.144 for (var attr in attrs) {145 if (attr === 'src')146 el.setAttribute(attr, attrs[attr]);147 }148}149/**150 * Binds to success and error events of an object wrapping them into a promise151 * available through {@code element.eventPromise}. The success event152 * resolves and error event rejects.153 * This method adds event listeners, and then removes all the added listeners154 * when one of listened event is fired.155 * @param {object} element An object supporting events on which to bind the156 * promise.157 * @param {string} resolveEventName [="load"] The event name to bind resolve to.158 * @param {string} rejectEventName [="error"] The event name to bind reject to.159 */160function bindEvents(element, resolveEventName, rejectEventName) {161 element.eventPromise =162 bindEvents2(element, resolveEventName, element, rejectEventName);163}164// Returns a promise wrapping success and error events of objects.165// This is a variant of bindEvents that can accept separate objects for each166// events and two events to reject, and doesn't set `eventPromise`.167//168// When `resolveObject`'s `resolveEventName` event (default: "load") is169// fired, the promise is resolved with the event.170//171// When `rejectObject`'s `rejectEventName` event (default: "error") or172// `rejectObject2`'s `rejectEventName2` event (default: "error") is173// fired, the promise is rejected.174//175// `rejectObject2` is optional.176function bindEvents2(resolveObject, resolveEventName, rejectObject, rejectEventName, rejectObject2, rejectEventName2) {177 return new Promise(function(resolve, reject) {178 const actualResolveEventName = resolveEventName || "load";179 const actualRejectEventName = rejectEventName || "error";180 const actualRejectEventName2 = rejectEventName2 || "error";181 const resolveHandler = function(event) {182 cleanup();183 resolve(event);184 };185 const rejectHandler = function(event) {186 // Chromium starts propagating errors from worker.onerror to187 // window.onerror. This handles the uncaught exceptions in tests.188 event.preventDefault();189 cleanup();190 reject(event);191 };192 const cleanup = function() {193 resolveObject.removeEventListener(actualResolveEventName, resolveHandler);194 rejectObject.removeEventListener(actualRejectEventName, rejectHandler);195 if (rejectObject2) {196 rejectObject2.removeEventListener(actualRejectEventName2, rejectHandler);197 }198 };199 resolveObject.addEventListener(actualResolveEventName, resolveHandler);200 rejectObject.addEventListener(actualRejectEventName, rejectHandler);201 if (rejectObject2) {202 rejectObject2.addEventListener(actualRejectEventName2, rejectHandler);203 }204 });205}206/**207 * Creates a new DOM element.208 * @param {string} tagName The type of the DOM element.209 * @param {object} attrs A JSON with attributes to apply to the element.210 * @param {DOMElement} parent Optional - an existing DOM element to append to211 * If not provided, the returned element will remain orphaned.212 * @param {boolean} doBindEvents Optional - Whether to bind to load and error213 * events and provide the promise wrapping the events via the element's214 * {@code eventPromise} property. Default value evaluates to false.215 * @return {DOMElement} The newly created DOM element.216 */217function createElement(tagName, attrs, parentNode, doBindEvents) {218 var element = document.createElement(tagName);219 if (doBindEvents) {220 bindEvents(element);221 if (element.tagName == "IFRAME" && !('srcdoc' in attrs || 'src' in attrs)) {222 // If we're loading a frame, ensure we spin the event loop after load to223 // paper over the different event timing in Gecko vs Blink/WebKit224 // see https://github.com/whatwg/html/issues/4965225 element.eventPromise = element.eventPromise.then(() => {226 return new Promise(resolve => setTimeout(resolve, 0))227 });228 }229 }230 // We set the attributes after binding to events to catch any231 // event-triggering attribute changes. E.g. form submission.232 //233 // But be careful with images: unlike other elements they will start the load234 // as soon as the attr is set, even if not in the document yet, and sometimes235 // complete it synchronously, so the append doesn't have the effect we want.236 // So for images, we want to set the attrs after appending, whereas for other237 // elements we want to do it before appending.238 var isImg = (tagName == "img");239 if (!isImg)240 setAttributes(element, attrs);241 if (parentNode)242 parentNode.appendChild(element);243 if (isImg)244 setAttributes(element, attrs);245 return element;246}247function createRequestViaElement(tagName, attrs, parentNode) {248 return createElement(tagName, attrs, parentNode, true).eventPromise;249}250function wrapResult(server_data) {251 if (typeof(server_data) === "string") {252 throw server_data;253 }254 return {255 referrer: server_data.headers.referer,256 headers: server_data.headers257 }258}259// ===============================================================260// Subresources261// ===============================================================262/**263 @typedef RequestResult264 @type {object}265 Represents the result of sending an request.266 All properties are optional. See the comments for267 requestVia*() and invokeRequest() below to see which properties are set.268 @property {Array<Object<string, string>>} headers269 HTTP request headers sent to server.270 @property {string} referrer - Referrer.271 @property {string} location - The URL of the subresource.272 @property {string} sourceContextUrl273 the URL of the global object where the actual request is sent.274*/275/**276 requestVia*(url, additionalAttributes) functions send a subresource277 request from the current environment settings object.278 @param {string} url279 The URL of the subresource.280 @param {Object<string, string>} additionalAttributes281 Additional attributes set to DOM elements282 (element-initiated requests only).283 @returns {Promise} that are resolved with a RequestResult object284 on successful requests.285 - Category 1:286 `headers`: set.287 `referrer`: set via `document.referrer`.288 `location`: set via `document.location`.289 See `template/document.html.template`.290 - Category 2:291 `headers`: set.292 `referrer`: set to `headers.referer` by `wrapResult()`.293 `location`: not set.294 - Category 3:295 All the keys listed above are NOT set.296 `sourceContextUrl` is not set here.297 -------------------------------- -------- --------------------------298 Function name Category Used in299 -------- ------- ---------300 referrer mixed- upgrade-301 policy content insecure-302 policy content request303 -------------------------------- -------- -------- ------- ---------304 requestViaAnchor 1 Y Y -305 requestViaArea 1 Y Y -306 requestViaAudio 3 - Y -307 requestViaDedicatedWorker 2 Y Y Y308 requestViaFetch 2 Y Y -309 requestViaForm 2 - Y -310 requestViaIframe 1 Y Y -311 requestViaImage 2 Y Y -312 requestViaLinkPrefetch 3 - Y -313 requestViaLinkStylesheet 3 - Y -314 requestViaObject 3 - Y -315 requestViaPicture 3 - Y -316 requestViaScript 2 Y Y -317 requestViaSendBeacon 3 - Y -318 requestViaSharedWorker 2 Y Y Y319 requestViaVideo 3 - Y -320 requestViaWebSocket 3 - Y -321 requestViaWorklet 3 - Y Y322 requestViaXhr 2 Y Y -323 -------------------------------- -------- -------- ------- ---------324*/325/**326 * Creates a new iframe, binds load and error events, sets the src attribute and327 * appends it to {@code document.body} .328 * @param {string} url The src for the iframe.329 * @return {Promise} The promise for success/error events.330 */331function requestViaIframe(url, additionalAttributes) {332 const iframe = createElement(333 "iframe",334 Object.assign({"src": url}, additionalAttributes),335 document.body,336 false);337 return bindEvents2(window, "message", iframe, "error", window, "error")338 .then(event => {339 if (event.source !== iframe.contentWindow)340 return Promise.reject(new Error('Unexpected event.source'));341 return event.data;342 });343}344/**345 * Creates a new image, binds load and error events, sets the src attribute and346 * appends it to {@code document.body} .347 * @param {string} url The src for the image.348 * @return {Promise} The promise for success/error events.349 */350function requestViaImage(url, additionalAttributes) {351 const img = createElement(352 "img",353 // crossOrigin attribute is added to read the pixel data of the response.354 Object.assign({"src": url, "crossOrigin": "Anonymous"}, additionalAttributes),355 document.body, true);356 return img.eventPromise.then(() => wrapResult(decodeImageData(img)));357}358// Helper for requestViaImage().359function decodeImageData(img) {360 var canvas = document.createElement("canvas");361 var context = canvas.getContext('2d');362 context.drawImage(img, 0, 0);363 var imgData = context.getImageData(0, 0, img.clientWidth, img.clientHeight);364 const rgba = imgData.data;365 let decodedBytes = new Uint8ClampedArray(rgba.length);366 let decodedLength = 0;367 for (var i = 0; i + 12 <= rgba.length; i += 12) {368 // A single byte is encoded in three pixels. 8 pixel octets (among369 // 9 octets = 3 pixels * 3 channels) are used to encode 8 bits,370 // the most significant bit first, where `0` and `255` in pixel values371 // represent `0` and `1` in bits, respectively.372 // This encoding is used to avoid errors due to different color spaces.373 const bits = [];374 for (let j = 0; j < 3; ++j) {375 bits.push(rgba[i + j * 4 + 0]);376 bits.push(rgba[i + j * 4 + 1]);377 bits.push(rgba[i + j * 4 + 2]);378 // rgba[i + j * 4 + 3]: Skip alpha channel.379 }380 // The last one element is not used.381 bits.pop();382 // Decode a single byte.383 let byte = 0;384 for (let j = 0; j < 8; ++j) {385 byte <<= 1;386 if (bits[j] >= 128)387 byte |= 1;388 }389 // Zero is the string terminator.390 if (byte == 0)391 break;392 decodedBytes[decodedLength++] = byte;393 }394 // Remove trailing nulls from data.395 decodedBytes = decodedBytes.subarray(0, decodedLength);396 var string_data = (new TextDecoder("ascii")).decode(decodedBytes);397 return JSON.parse(string_data);398}399/**400 * Initiates a new XHR GET request to provided URL.401 * @param {string} url The endpoint URL for the XHR.402 * @return {Promise} The promise for success/error events.403 */404function requestViaXhr(url) {405 return xhrRequest(url).then(result => wrapResult(result));406}407/**408 * Initiates a new GET request to provided URL via the Fetch API.409 * @param {string} url The endpoint URL for the Fetch.410 * @return {Promise} The promise for success/error events.411 */412function requestViaFetch(url) {413 return fetch(url)414 .then(res => res.json())415 .then(j => wrapResult(j));416}417function dedicatedWorkerUrlThatFetches(url) {418 return `data:text/javascript,419 fetch('${url}')420 .then(r => r.json())421 .then(j => postMessage(j))422 .catch((e) => postMessage(e.message));`;423}424function workerUrlThatImports(url) {425 return `/common/security-features/subresource/static-import.py` +426 `?import_url=${encodeURIComponent(url)}`;427}428function workerDataUrlThatImports(url) {429 return `data:text/javascript,import '${url}';`;430}431/**432 * Creates a new Worker, binds message and error events wrapping them into.433 * {@code worker.eventPromise} and posts an empty string message to start434 * the worker.435 * @param {string} url The endpoint URL for the worker script.436 * @param {object} options The options for Worker constructor.437 * @return {Promise} The promise for success/error events.438 */439function requestViaDedicatedWorker(url, options) {440 var worker;441 try {442 worker = new Worker(url, options);443 } catch (e) {444 return Promise.reject(e);445 }446 worker.postMessage('');447 return bindEvents2(worker, "message", worker, "error")448 .then(event => wrapResult(event.data));449}450function requestViaSharedWorker(url, options) {451 var worker;452 try {453 worker = new SharedWorker(url, options);454 } catch(e) {455 return Promise.reject(e);456 }457 const promise = bindEvents2(worker.port, "message", worker, "error")458 .then(event => wrapResult(event.data));459 worker.port.start();460 return promise;461}462// Returns a reference to a worklet object corresponding to a given type.463function get_worklet(type) {464 if (type == 'animation')465 return CSS.animationWorklet;466 if (type == 'layout')467 return CSS.layoutWorklet;468 if (type == 'paint')469 return CSS.paintWorklet;470 if (type == 'audio')471 return new OfflineAudioContext(2,44100*40,44100).audioWorklet;472 throw new Error('unknown worklet type is passed.');473}474function requestViaWorklet(type, url) {475 try {476 return get_worklet(type).addModule(url);477 } catch (e) {478 return Promise.reject(e);479 }480}481/**482 * Creates a navigable element with the name `navigableElementName`483 * (<a>, <area>, or <form>) under `parentNode`, and484 * performs a navigation by `trigger()` (e.g. clicking <a>).485 * To avoid navigating away from the current execution context,486 * a target attribute is set to point to a new helper iframe.487 * @param {string} navigableElementName488 * @param {object} additionalAttributes The attributes of the navigable element.489 * @param {DOMElement} parentNode490 * @param {function(DOMElement} trigger A callback called after the navigable491 * element is inserted and should trigger navigation using the element.492 * @return {Promise} The promise for success/error events.493 */494function requestViaNavigable(navigableElementName, additionalAttributes,495 parentNode, trigger) {496 const name = guid();497 const iframe =498 createElement("iframe", {"name": name, "id": name}, parentNode, false);499 const navigable = createElement(500 navigableElementName,501 Object.assign({"target": name}, additionalAttributes),502 parentNode, false);503 const promise =504 bindEvents2(window, "message", iframe, "error", window, "error")505 .then(event => {506 if (event.source !== iframe.contentWindow)507 return Promise.reject(new Error('Unexpected event.source'));508 return event.data;509 });510 trigger(navigable);511 return promise;512}513/**514 * Creates a new anchor element, appends it to {@code document.body} and515 * performs the navigation.516 * @param {string} url The URL to navigate to.517 * @return {Promise} The promise for success/error events.518 */519function requestViaAnchor(url, additionalAttributes) {520 return requestViaNavigable(521 "a",522 Object.assign({"href": url, "innerHTML": "Link to resource"},523 additionalAttributes),524 document.body, a => a.click());525}526/**527 * Creates a new area element, appends it to {@code document.body} and performs528 * the navigation.529 * @param {string} url The URL to navigate to.530 * @return {Promise} The promise for success/error events.531 */532function requestViaArea(url, additionalAttributes) {533 // TODO(kristijanburnik): Append to map and add image.534 return requestViaNavigable(535 "area",536 Object.assign({"href": url}, additionalAttributes),537 document.body, area => area.click());538}539/**540 * Creates a new script element, sets the src to url, and appends it to541 * {@code document.body}.542 * @param {string} url The src URL.543 * @return {Promise} The promise for success/error events.544 */545function requestViaScript(url, additionalAttributes) {546 const script = createElement(547 "script",548 Object.assign({"src": url}, additionalAttributes),549 document.body,550 false);551 return bindEvents2(window, "message", script, "error", window, "error")552 .then(event => wrapResult(event.data));553}554/**555 * Creates a new script element that performs a dynamic import to `url`, and556 * appends the script element to {@code document.body}.557 * @param {string} url The src URL.558 * @return {Promise} The promise for success/error events.559 */560function requestViaDynamicImport(url, additionalAttributes) {561 const scriptUrl = `data:text/javascript,import("${url}");`;562 const script = createElement(563 "script",564 Object.assign({"src": scriptUrl}, additionalAttributes),565 document.body,566 false);567 return bindEvents2(window, "message", script, "error", window, "error")568 .then(event => wrapResult(event.data));569}570/**571 * Creates a new form element, sets attributes, appends it to572 * {@code document.body} and submits the form.573 * @param {string} url The URL to submit to.574 * @return {Promise} The promise for success/error events.575 */576function requestViaForm(url, additionalAttributes) {577 return requestViaNavigable(578 "form",579 Object.assign({"action": url, "method": "POST"}, additionalAttributes),580 document.body, form => form.submit());581}582/**583 * Creates a new link element for a stylesheet, binds load and error events,584 * sets the href to url and appends it to {@code document.head}.585 * @param {string} url The URL for a stylesheet.586 * @return {Promise} The promise for success/error events.587 */588function requestViaLinkStylesheet(url) {589 return createRequestViaElement("link",590 {"rel": "stylesheet", "href": url},591 document.head);592}593/**594 * Creates a new link element for a prefetch, binds load and error events, sets595 * the href to url and appends it to {@code document.head}.596 * @param {string} url The URL of a resource to prefetch.597 * @return {Promise} The promise for success/error events.598 */599function requestViaLinkPrefetch(url) {600 var link = document.createElement('link');601 if (link.relList && link.relList.supports && link.relList.supports("prefetch")) {602 return createRequestViaElement("link",603 {"rel": "prefetch", "href": url},604 document.head);605 } else {606 return Promise.reject("This browser does not support 'prefetch'.");607 }608}609/**610 * Initiates a new beacon request.611 * @param {string} url The URL of a resource to prefetch.612 * @return {Promise} The promise for success/error events.613 */614async function requestViaSendBeacon(url) {615 function wait(ms) {616 return new Promise(resolve => step_timeout(resolve, ms));617 }618 if (!navigator.sendBeacon(url)) {619 // If mixed-content check fails, it should return false.620 throw new Error('sendBeacon() fails.');621 }622 // We don't have a means to see the result of sendBeacon() request623 // for sure. Let's wait for a while and let the generic test function624 // ask the server for the result.625 await wait(500);626 return 'allowed';627}628/**629 * Creates a new media element with a child source element, binds loadeddata and630 * error events, sets attributes and appends to document.body.631 * @param {string} type The type of the media element (audio/video/picture).632 * @param {object} media_attrs The attributes for the media element.633 * @param {object} source_attrs The attributes for the child source element.634 * @return {DOMElement} The newly created media element.635 */636function createMediaElement(type, media_attrs, source_attrs) {637 var mediaElement = createElement(type, {});638 var sourceElement = createElement("source", {});639 mediaElement.eventPromise = new Promise(function(resolve, reject) {640 mediaElement.addEventListener("loadeddata", function (e) {641 resolve(e);642 });643 // Safari doesn't fire an `error` event when blocking mixed content.644 mediaElement.addEventListener("stalled", function(e) {645 reject(e);646 });647 sourceElement.addEventListener("error", function(e) {648 reject(e);649 });650 });651 setAttributes(mediaElement, media_attrs);652 setAttributes(sourceElement, source_attrs);653 mediaElement.appendChild(sourceElement);654 document.body.appendChild(mediaElement);655 return mediaElement;656}657/**658 * Creates a new video element, binds loadeddata and error events, sets659 * attributes and source URL and appends to {@code document.body}.660 * @param {string} url The URL of the video.661 * @return {Promise} The promise for success/error events.662 */663function requestViaVideo(url) {664 return createMediaElement("video",665 {},666 {"src": url}).eventPromise;667}668/**669 * Creates a new audio element, binds loadeddata and error events, sets670 * attributes and source URL and appends to {@code document.body}.671 * @param {string} url The URL of the audio.672 * @return {Promise} The promise for success/error events.673 */674function requestViaAudio(url) {675 return createMediaElement("audio",676 {},677 {"type": "audio/wav", "src": url}).eventPromise;678}679/**680 * Creates a new picture element, binds loadeddata and error events, sets681 * attributes and source URL and appends to {@code document.body}. Also682 * creates new image element appending it to the picture683 * @param {string} url The URL of the image for the source and image elements.684 * @return {Promise} The promise for success/error events.685 */686function requestViaPicture(url) {687 var picture = createMediaElement("picture", {}, {"srcset": url,688 "type": "image/png"});689 return createRequestViaElement("img", {"src": url}, picture);690}691/**692 * Creates a new object element, binds load and error events, sets the data to693 * url, and appends it to {@code document.body}.694 * @param {string} url The data URL.695 * @return {Promise} The promise for success/error events.696 */697function requestViaObject(url) {698 return createRequestViaElement("object", {"data": url, "type": "text/html"}, document.body);699}700/**701 * Creates a new WebSocket pointing to {@code url} and sends a message string702 * "echo". The {@code message} and {@code error} events are triggering the703 * returned promise resolve/reject events.704 * @param {string} url The URL for WebSocket to connect to.705 * @return {Promise} The promise for success/error events.706 */707function requestViaWebSocket(url) {708 return new Promise(function(resolve, reject) {709 var websocket = new WebSocket(url);710 websocket.addEventListener("message", function(e) {711 resolve(e.data);712 });713 websocket.addEventListener("open", function(e) {714 websocket.send("echo");715 });716 websocket.addEventListener("error", function(e) {717 reject(e)718 });719 })720 .then(data => {721 return JSON.parse(data);722 });723}724/**725 @typedef SubresourceType726 @type {string}727 Represents how a subresource is sent.728 The keys of `subresourceMap` below are the valid values.729*/730// Subresource paths and invokers.731const subresourceMap = {732 "a-tag": {733 path: "/common/security-features/subresource/document.py",734 invoker: requestViaAnchor,735 },736 "area-tag": {737 path: "/common/security-features/subresource/document.py",738 invoker: requestViaArea,739 },740 "audio-tag": {741 path: "/common/security-features/subresource/audio.py",742 invoker: requestViaAudio,743 },744 "beacon": {745 path: "/common/security-features/subresource/empty.py",746 invoker: requestViaSendBeacon,747 },748 "fetch": {749 path: "/common/security-features/subresource/xhr.py",750 invoker: requestViaFetch,751 },752 "form-tag": {753 path: "/common/security-features/subresource/document.py",754 invoker: requestViaForm,755 },756 "iframe-tag": {757 path: "/common/security-features/subresource/document.py",758 invoker: requestViaIframe,759 },760 "img-tag": {761 path: "/common/security-features/subresource/image.py",762 invoker: requestViaImage,763 },764 "link-css-tag": {765 path: "/common/security-features/subresource/empty.py",766 invoker: requestViaLinkStylesheet,767 },768 "link-prefetch-tag": {769 path: "/common/security-features/subresource/empty.py",770 invoker: requestViaLinkPrefetch,771 },772 "object-tag": {773 path: "/common/security-features/subresource/empty.py",774 invoker: requestViaObject,775 },776 "picture-tag": {777 path: "/common/security-features/subresource/image.py",778 invoker: requestViaPicture,779 },780 "script-tag": {781 path: "/common/security-features/subresource/script.py",782 invoker: requestViaScript,783 },784 "script-tag-dynamic-import": {785 path: "/common/security-features/subresource/script.py",786 invoker: requestViaDynamicImport,787 },788 "video-tag": {789 path: "/common/security-features/subresource/video.py",790 invoker: requestViaVideo,791 },792 "xhr": {793 path: "/common/security-features/subresource/xhr.py",794 invoker: requestViaXhr,795 },796 "worker-classic": {797 path: "/common/security-features/subresource/worker.py",798 invoker: url => requestViaDedicatedWorker(url),799 },800 "worker-module": {801 path: "/common/security-features/subresource/worker.py",802 invoker: url => requestViaDedicatedWorker(url, {type: "module"}),803 },804 "worker-import": {805 path: "/common/security-features/subresource/worker.py",806 invoker: url =>807 requestViaDedicatedWorker(workerUrlThatImports(url), {type: "module"}),808 },809 "worker-import-data": {810 path: "/common/security-features/subresource/worker.py",811 invoker: url =>812 requestViaDedicatedWorker(workerDataUrlThatImports(url), {type: "module"}),813 },814 "sharedworker-classic": {815 path: "/common/security-features/subresource/shared-worker.py",816 invoker: url => requestViaSharedWorker(url),817 },818 "sharedworker-module": {819 path: "/common/security-features/subresource/shared-worker.py",820 invoker: url => requestViaSharedWorker(url, {type: "module"}),821 },822 "sharedworker-import": {823 path: "/common/security-features/subresource/shared-worker.py",824 invoker: url =>825 requestViaSharedWorker(workerUrlThatImports(url), {type: "module"}),826 },827 "sharedworker-import-data": {828 path: "/common/security-features/subresource/shared-worker.py",829 invoker: url =>830 requestViaSharedWorker(workerDataUrlThatImports(url), {type: "module"}),831 },832 "websocket": {833 path: "/stash_responder",834 invoker: requestViaWebSocket,835 },836};837for (const workletType of ['animation', 'audio', 'layout', 'paint']) {838 subresourceMap[`worklet-${workletType}`] = {839 path: "/common/security-features/subresource/worker.py",840 invoker: url => requestViaWorklet(workletType, url)841 };842 subresourceMap[`worklet-${workletType}-import-data`] = {843 path: "/common/security-features/subresource/worker.py",844 invoker: url =>845 requestViaWorklet(workletType, workerDataUrlThatImports(url))846 };847}848/**849 @typedef RedirectionType850 @type {string}851 Represents what redirects should occur to the subresource request852 after initial request.853 See preprocess_redirection() in854 /common/security-features/subresource/subresource.py for valid values.855*/856/**857 Construct subresource (and related) origin.858 @param {string} originType859 @returns {object} the origin of the subresource.860*/861function getSubresourceOrigin(originType) {862 const httpProtocol = "http";863 const httpsProtocol = "https";864 const wsProtocol = "ws";865 const wssProtocol = "wss";866 const sameOriginHost = "{{host}}";867 const crossOriginHost = "{{domains[www1]}}";868 // These values can evaluate to either empty strings or a ":port" string.869 const httpPort = getNormalizedPort(parseInt("{{ports[http][0]}}", 10));870 const httpsRawPort = parseInt("{{ports[https][0]}}", 10);871 const httpsPort = getNormalizedPort(httpsRawPort);872 const wsPort = getNormalizedPort(parseInt("{{ports[ws][0]}}", 10));873 const wssRawPort = parseInt("{{ports[wss][0]}}", 10);874 const wssPort = getNormalizedPort(wssRawPort);875 /**876 @typedef OriginType877 @type {string}878 Represents the origin of the subresource request URL.879 The keys of `originMap` below are the valid values.880 Note that there can be redirects from the specified origin881 (see RedirectionType), and thus the origin of the subresource882 response URL might be different from what is specified by OriginType.883 */884 const originMap = {885 "same-https": httpsProtocol + "://" + sameOriginHost + httpsPort,886 "same-http": httpProtocol + "://" + sameOriginHost + httpPort,887 "cross-https": httpsProtocol + "://" + crossOriginHost + httpsPort,888 "cross-http": httpProtocol + "://" + crossOriginHost + httpPort,889 "same-wss": wssProtocol + "://" + sameOriginHost + wssPort,890 "same-ws": wsProtocol + "://" + sameOriginHost + wsPort,891 "cross-wss": wssProtocol + "://" + crossOriginHost + wssPort,892 "cross-ws": wsProtocol + "://" + crossOriginHost + wsPort,893 // The following origin types are used for upgrade-insecure-requests tests:894 // These rely on some unintuitive cleverness due to WPT's test setup:895 // 'Upgrade-Insecure-Requests' does not upgrade the port number,896 // so we use URLs in the form `http://[domain]:[https-port]`,897 // which will be upgraded to `https://[domain]:[https-port]`.898 // If the upgrade fails, the load will fail, as we don't serve HTTP over899 // the secure port.900 "same-http-downgrade":901 httpProtocol + "://" + sameOriginHost + ":" + httpsRawPort,902 "cross-http-downgrade":903 httpProtocol + "://" + crossOriginHost + ":" + httpsRawPort,904 "same-ws-downgrade":905 wsProtocol + "://" + sameOriginHost + ":" + wssRawPort,906 "cross-ws-downgrade":907 wsProtocol + "://" + crossOriginHost + ":" + wssRawPort,908 };909 return originMap[originType];910}911/**912 Construct subresource (and related) URLs.913 @param {SubresourceType} subresourceType914 @param {OriginType} originType915 @param {RedirectionType} redirectionType916 @returns {object} with following properties:917 {string} testUrl918 The subresource request URL.919 {string} announceUrl920 {string} assertUrl921 The URLs to be used for detecting whether `testUrl` is actually sent922 to the server.923 1. Fetch `announceUrl` first,924 2. then possibly fetch `testUrl`, and925 3. finally fetch `assertUrl`.926 The fetch result of `assertUrl` should indicate whether927 `testUrl` is actually sent to the server or not.928*/929function getRequestURLs(subresourceType, originType, redirectionType) {930 const key = guid();931 const value = guid();932 // We use the same stash path for both HTTP/S and WS/S stash requests.933 const stashPath = encodeURIComponent("/mixed-content");934 const stashEndpoint = "/common/security-features/subresource/xhr.py?key=" +935 key + "&path=" + stashPath;936 return {937 testUrl:938 getSubresourceOrigin(originType) +939 subresourceMap[subresourceType].path +940 "?redirection=" + encodeURIComponent(redirectionType) +941 "&action=purge&key=" + key +942 "&path=" + stashPath,943 announceUrl: stashEndpoint + "&action=put&value=" + value,944 assertUrl: stashEndpoint + "&action=take",945 };946}947// ===============================================================948// Source Context949// ===============================================================950// Requests can be sent from several source contexts,951// such as the main documents, iframes, workers, or so,952// possibly nested, and possibly with <meta>/http headers added.953// invokeRequest() and invokeFrom*() functions handles954// SourceContext-related setup in client-side.955/**956 invokeRequest() invokes a subresource request957 (specified as `subresource`)958 from a (possibly nested) environment settings object959 (specified as `sourceContextList`).960 For nested contexts, invokeRequest() calls an invokeFrom*() function961 that creates a nested environment settings object using962 /common/security-features/scope/, which calls invokeRequest()963 again inside the nested environment settings object.964 This cycle continues until all specified965 nested environment settings object are created, and966 finally invokeRequest() calls a requestVia*() function to start the967 subresource request from the inner-most environment settings object.968 @param {Subresource} subresource969 @param {Array<SourceContext>} sourceContextList970 @returns {Promise} A promise that is resolved with an RequestResult object.971 `sourceContextUrl` is always set. For whether other properties are set,972 see the comments for requestVia*() above.973*/974function invokeRequest(subresource, sourceContextList) {975 if (sourceContextList.length === 0) {976 // No further nested global objects. Send the subresource request here.977 const additionalAttributes = {};978 /** @type {PolicyDelivery} policyDelivery */979 for (const policyDelivery of (subresource.policyDeliveries || [])) {980 // Depending on the delivery method, extend the subresource element with981 // these attributes.982 if (policyDelivery.deliveryType === "attr") {983 additionalAttributes[policyDelivery.key] = policyDelivery.value;984 } else if (policyDelivery.deliveryType === "rel-noref") {985 additionalAttributes["rel"] = "noreferrer";986 }987 }988 return subresourceMap[subresource.subresourceType].invoker(989 subresource.url,990 additionalAttributes)991 .then(result => Object.assign(992 {sourceContextUrl: location.toString()},993 result));994 }995 // Defines invokers for each valid SourceContext.sourceContextType.996 const sourceContextMap = {997 "srcdoc": { // <iframe srcdoc></iframe>998 invoker: invokeFromIframe,999 },1000 "iframe": { // <iframe src="same-origin-URL"></iframe>1001 invoker: invokeFromIframe,1002 },1003 "iframe-blank": { // <iframe></iframe>1004 invoker: invokeFromIframe,1005 },1006 "worker-classic": {1007 // Classic dedicated worker loaded from same-origin.1008 invoker: invokeFromWorker.bind(undefined, "worker", false, {}),1009 },1010 "worker-classic-data": {1011 // Classic dedicated worker loaded from data: URL.1012 invoker: invokeFromWorker.bind(undefined, "worker", true, {}),1013 },1014 "worker-module": {1015 // Module dedicated worker loaded from same-origin.1016 invoker: invokeFromWorker.bind(undefined, "worker", false, {type: 'module'}),1017 },1018 "worker-module-data": {1019 // Module dedicated worker loaded from data: URL.1020 invoker: invokeFromWorker.bind(undefined, "worker", true, {type: 'module'}),1021 },1022 "sharedworker-classic": {1023 // Classic shared worker loaded from same-origin.1024 invoker: invokeFromWorker.bind(undefined, "sharedworker", false, {}),1025 },1026 "sharedworker-classic-data": {1027 // Classic shared worker loaded from data: URL.1028 invoker: invokeFromWorker.bind(undefined, "sharedworker", true, {}),1029 },1030 "sharedworker-module": {1031 // Module shared worker loaded from same-origin.1032 invoker: invokeFromWorker.bind(undefined, "sharedworker", false, {type: 'module'}),1033 },1034 "sharedworker-module-data": {1035 // Module shared worker loaded from data: URL.1036 invoker: invokeFromWorker.bind(undefined, "sharedworker", true, {type: 'module'}),1037 },1038 };1039 return sourceContextMap[sourceContextList[0].sourceContextType].invoker(1040 subresource, sourceContextList);1041}1042// Quick hack to expose invokeRequest when common.sub.js is loaded either1043// as a classic or module script.1044self.invokeRequest = invokeRequest;1045/**1046 invokeFrom*() functions are helper functions with the same parameters1047 and return values as invokeRequest(), that are tied to specific types1048 of top-most environment settings objects.1049 For example, invokeFromIframe() is the helper function for the cases where1050 sourceContextList[0] is an iframe.1051*/1052/**1053 @param {string} workerType1054 "worker" (for dedicated worker) or "sharedworker".1055 @param {boolean} isDataUrl1056 true if the worker script is loaded from data: URL.1057 Otherwise, the script is loaded from same-origin.1058 @param {object} workerOptions1059 The `options` argument for Worker constructor.1060 Other parameters and return values are the same as those of invokeRequest().1061*/1062function invokeFromWorker(workerType, isDataUrl, workerOptions,1063 subresource, sourceContextList) {1064 const currentSourceContext = sourceContextList[0];1065 let workerUrl =1066 "/common/security-features/scope/worker.py?policyDeliveries=" +1067 encodeURIComponent(JSON.stringify(1068 currentSourceContext.policyDeliveries || []));1069 if (workerOptions.type === 'module') {1070 workerUrl += "&type=module";1071 }1072 let promise;1073 if (isDataUrl) {1074 promise = fetch(workerUrl)1075 .then(r => r.text())1076 .then(source => {1077 return 'data:text/javascript;base64,' + btoa(source);1078 });1079 } else {1080 promise = Promise.resolve(workerUrl);1081 }1082 return promise1083 .then(url => {1084 if (workerType === "worker") {1085 const worker = new Worker(url, workerOptions);1086 worker.postMessage({subresource: subresource,1087 sourceContextList: sourceContextList.slice(1)});1088 return bindEvents2(worker, "message", worker, "error", window, "error");1089 } else if (workerType === "sharedworker") {1090 const worker = new SharedWorker(url, workerOptions);1091 worker.port.start();1092 worker.port.postMessage({subresource: subresource,1093 sourceContextList: sourceContextList.slice(1)});1094 return bindEvents2(worker.port, "message", worker, "error", window, "error");1095 } else {1096 throw new Error('Invalid worker type: ' + workerType);1097 }1098 })1099 .then(event => {1100 if (event.data.error)1101 return Promise.reject(event.data.error);1102 return event.data;1103 });1104}1105function invokeFromIframe(subresource, sourceContextList) {1106 const currentSourceContext = sourceContextList[0];1107 const frameUrl =1108 "/common/security-features/scope/document.py?policyDeliveries=" +1109 encodeURIComponent(JSON.stringify(1110 currentSourceContext.policyDeliveries || []));1111 let iframe;1112 let promise;1113 if (currentSourceContext.sourceContextType === 'srcdoc') {1114 promise = fetch(frameUrl)1115 .then(r => r.text())1116 .then(srcdoc => {1117 iframe = createElement(1118 "iframe", {srcdoc: srcdoc}, document.body, true);1119 return iframe.eventPromise;1120 });1121 } else if (currentSourceContext.sourceContextType === 'iframe') {1122 iframe = createElement("iframe", {src: frameUrl}, document.body, true);1123 promise = iframe.eventPromise;1124 } else if (currentSourceContext.sourceContextType === 'iframe-blank') {1125 let frameContent;1126 promise = fetch(frameUrl)1127 .then(r => r.text())1128 .then(t => {1129 frameContent = t;1130 iframe = createElement("iframe", {}, document.body, true);1131 return iframe.eventPromise;1132 })1133 .then(() => {1134 // Reinitialize `iframe.eventPromise` with a new promise1135 // that catches the load event for the document.write() below.1136 bindEvents(iframe);1137 iframe.contentDocument.write(frameContent);1138 iframe.contentDocument.close();1139 return iframe.eventPromise;1140 });1141 }1142 return promise1143 .then(() => {1144 const promise = bindEvents2(1145 window, "message", iframe, "error", window, "error");1146 iframe.contentWindow.postMessage(1147 {subresource: subresource,1148 sourceContextList: sourceContextList.slice(1)},1149 "*");1150 return promise;1151 })1152 .then(event => {1153 if (event.data.error)1154 return Promise.reject(event.data.error);1155 return event.data;1156 });1157}1158// SanityChecker does nothing in release mode. See sanity-checker.js for debug1159// mode.1160function SanityChecker() {}1161SanityChecker.prototype.checkScenario = function() {};1162SanityChecker.prototype.setFailTimeout = function(test, timeout) {};...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var wssRawPort = wptools.wssRawPort;3var wss = wptools.wss;4var wssPort = wptools.wssPort;5wssRawPort('wikipedia.org', function(port) {6 console.log('Raw port: ' + port);7});8wss('wikipedia.org', function(url) {9 console.log('Raw url: ' + url);10});11wssPort('wikipedia.org', function(port) {12 console.log('Raw port: ' + port);13});14var wptools = require('wptools');15var wssRawPort = wptools.wssRawPort;16var wss = wptools.wss;17var wssPort = wptools.wssPort;18wssRawPort('wikipedia.org', function(port) {19 console.log('Raw port: ' + port);20});21wss('wikipedia.org', function(url) {22 console.log('Raw url: ' + url);23});24wssPort('wikipedia.org', function(port) {25 console.log('Raw port: ' + port);26});27var wptools = require('wptools');28var wssRawPort = wptools.wssRawPort;29var wss = wptools.wss;30var wssPort = wptools.wssPort;31wssRawPort('wikipedia.org', function(port) {32 console.log('Raw port: ' + port);33});34wss('wikipedia.org', function(url) {35 console.log('Raw url: ' + url);36});37wssPort('wikipedia.org

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var wssRawPort = new wptools.wssRawPort(8080);3wssRawPort.listen();4var wptools = require('wptools');5var wssRawPort = new wptools.wssRawPort(8081);6wssRawPort.listen();7var wptools = require('wptools');8var wssRawPort = new wptools.wssRawPort(8082);9wssRawPort.listen();10var wptools = require('wptools');11var wssRawPort = new wptools.wssRawPort(8083);12wssRawPort.listen();13var wptools = require('wptools');14var wssRawPort = new wptools.wssRawPort(8084);15wssRawPort.listen();16var wptools = require('wptools');17var wssRawPort = new wptools.wssRawPort(8085);18wssRawPort.listen();19var wptools = require('wptools');20var wssRawPort = new wptools.wssRawPort(8086);21wssRawPort.listen();22var wptools = require('

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require('wptoolkit');2var port = wptoolkit.wssRawPort();3console.log(port);4var wptoolkit = require('wptoolkit');5var wpapi = wptoolkit.wpapi();6console.log(wpapi);7var wptoolkit = require('wptoolkit');8var wpapi = wptoolkit.wpapi();9console.log(wpapi);10var wptoolkit = require('wptoolkit');11var wpapi = wptoolkit.wpapi();12console.log(wpapi);13var wptoolkit = require('wptoolkit');14var wpapi = wptoolkit.wpapi();15console.log(wpapi);16var wptoolkit = require('wptoolkit');17var wpapi = wptoolkit.wpapi();18console.log(wpapi);19var wptoolkit = require('wptoolkit');20var wpapi = wptoolkit.wpapi();21console.log(wpapi);22var wptoolkit = require('wptoolkit');23var wpapi = wptoolkit.wpapi();24console.log(wpapi);25var wptoolkit = require('wptoolkit');26var wpapi = wptoolkit.wpapi();27console.log(wpapi);28var wptoolkit = require('wptoolkit');29var wpapi = wptoolkit.wpapi();30console.log(wpapi);31var wptoolkit = require('wptoolkit');

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptb = require('wptb');2var wss = wptb.wssRawPort(8080, true);3var wptb = require('wptb');4var wss = wptb.wssPort(8080, true);5var wptb = require('wptb');6var wss = wptb.wssPort(8080, true);7var wptb = require('wptb');8var wss = wptb.wssPort(8080, true);9var wptb = require('wptb');10var wss = wptb.wssPort(8080, true);11var wptb = require('wptb');12var wss = wptb.wssPort(8080, true);13var wptb = require('wptb');14var wss = wptb.wssPort(8080, true);15var wptb = require('wptb');16var wss = wptb.wssPort(8080, true);17var wptb = require('wptb');18var wss = wptb.wssPort(8080, true);19var wptb = require('wptb

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt.js');2var port = wpt.wssRawPort(8080);3port.postMessage("hello");4port.onmessage = function(e) {5 console.log(e.data);6}7port.close();8var wpt = require('wpt.js');9var port = wpt.wssRawPort(8080);10port.postMessage("hello");11port.onmessage = function(e) {12 console.log(e.data);13}14port.close();15var wpt = require('wpt.js');16var port = wpt.wssRawPort(8080);17port.postMessage("hello");18port.onmessage = function(e) {19 console.log(e.data);20}21port.close();22var wpt = require('wpt.js');23var port = wpt.wssRawPort(8080);

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful