Restrict new windows in replay + improved service worker loading + better error messages (#126)
* embeds: - support target rewriting with named iframe as per webrecorder/wombat#94 - refactor sw init: detect additional errors, such as CORS issues in nested iframes - support cross-origin replaybase for embeds - add 'requirecrossoriginiframe' to restrict embed to only be loaded in subdomain iframes, otherwise showing - rename noSandbox -> sandbox, not enabled by default init: set appName on service worker init docs: - add example embed to embedding doc - update docs for noSandbox -> sandbox - add warning if deprecated 'noSandbox' flag is used, explaining that it is now deprecated - update embedding and CHANGES.md with latest features - add tweet-example.wacz - add embed.html to test embeds bump to 1.7.0-beta.1
This commit is contained in:
+6
-2
@@ -1,13 +1,17 @@
|
||||
## CHANGES
|
||||
|
||||
v1.7.0 Beta 0
|
||||
v1.7.0
|
||||
- UI: Support showing WACZ verification stats on info tab, showing hashes verified, observer domain (or creation software), and certificate fingerprint, and WACZ package digest
|
||||
- Embed UI: Add `replay-with-info` embed mode which provides an information dropdown above replay, including verification info and link to download.
|
||||
- Embed UI: Add `hideOffscreen` attribute to enable hiding embed when offscreen (previously always enabled).
|
||||
- Embeds: add `newWindowBase" for configuring base replay for loading pages in new windows (default: https://replayweb.page/ or current page with deep links)
|
||||
- Embeds: Set `noCache` and `noWebWorker` automatically if needed based on browser features (eg. Safari)
|
||||
- Errors: More error messages, such as due to cross-origin iframes lacking service-worker support and Firefox-specific messages
|
||||
- Embeds: Rename 'noSandbox' -> 'sandbox', don't make default to support window target reuse
|
||||
- Fidelity/Embeds: Redirect new windows from links / `window.open` to existing replay frame (only possible w/o 'sandbox').
|
||||
- Embeds: Add 'requireSubdomainIframe' embed attribute to only allow embed if loaded from a cross-origin / subdomain iframe.
|
||||
- UI: improved formatting on 404 not found page.
|
||||
- Dependencies: update to wabac.js 2.13.0 to support verification, latest wombat
|
||||
- Dependencies: update to wabac.js 2.13.0 to support verification, latest wombat (3.3.9)
|
||||
|
||||
v1.6.5
|
||||
- Loading: Don't ignore hashtag, eg. #.wacz to specify file type when loading (via wabac.js)
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "replaywebpage",
|
||||
"productName": "ReplayWeb.page",
|
||||
"version": "1.7.0-beta.0",
|
||||
"version": "1.7.0-beta.1",
|
||||
"description": "Serverless Web Archive Replay",
|
||||
"repository": "https://github.com/webrecorder/replayweb.page",
|
||||
"homepage": "https://replayweb.page/",
|
||||
@@ -9,7 +9,7 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"@webrecorder/wabac": "^2.13.0-beta.0",
|
||||
"@webrecorder/wabac": "github:webrecorder/wabac.js",
|
||||
"bulma": "^0.9.3",
|
||||
"electron-log": "^4.4.1",
|
||||
"electron-updater": "^4.3.9",
|
||||
|
||||
Binary file not shown.
+18
-5
@@ -4,7 +4,6 @@ title: Embedding ReplayWeb.page
|
||||
nav_order: 3
|
||||
permalink: /docs/embedding
|
||||
---
|
||||
|
||||
## Embedding Web Archives with ReplayWeb.page
|
||||
|
||||
A key goal of ReplayWeb.page is to make embedding web archives into other sites as easy as it is to embed media files like images and PDFs.
|
||||
@@ -13,7 +12,7 @@ To make this possible ReplayWeb.page provides the `<replay-web-page>` HTML web c
|
||||
|
||||
For the web component to work you need to load the *frontend* user interface and the *backend* service worker into your web page, and then point a `<replay-web-page>` component at your WACZ file. The *frontend* defines the `<replay-web-page>` web component itself, and the backend service worker is responsible for retrieving data on demand from your web archive file. The backend pulls resources from the WACZ file *on-demand* as they are requested, so full retrieval of the WACZ to the browser is *not* required. The frontend and backend are just static JavaScript assets which you can choose to load from a Content Delivery Network (CDN) or directly from your website if you would like to host them yourself.
|
||||
|
||||
For example, to embed a WACZ web archive stored at `https://replayweb.page/docs/assets/example.wacz` you first need to add the following snippet to your HTML page to load the user interface and use the `<replay-web-page>` component to point to the WACZ:
|
||||
For example, to embed a WACZ web archive stored at `https://replayweb.page/docs/assets/tweet-example.wacz` you first need to add the following snippet to your HTML page to load the user interface and use the `<replay-web-page>` component to point to the WACZ:
|
||||
|
||||
{: .bg-blue-000 .text-grey-lt-000 .cap-header}
|
||||
my-web-archive-embed.html
|
||||
@@ -21,8 +20,8 @@ my-web-archive-embed.html
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/replaywebpage@{{ site.data.package.version }}/ui.js"></script>
|
||||
|
||||
<replay-web-page source="https://replayweb.page/docs/assets/example.wacz"
|
||||
url="https://webrecorder.net"></replay-web-page>
|
||||
<replay-web-page source="https://replayweb.page/docs/assets/tweet-example.wacz"
|
||||
url="https://oembed.link/https://twitter.com/webrecorder_io/status/1565881026215219200"></replay-web-page>
|
||||
```
|
||||
|
||||
The first line loads version {{ site.data.package.version }} of the ui from the jsDelivr content delivery network. And the second instantiates the ReplayWebPage component using the `source` attribute to point to the location of the WACZ file on the web (in this case published on AWS S3). The `url` attribute is used to indicate what URL to display from the archive after the component loads.
|
||||
@@ -82,6 +81,19 @@ Then you adjust your HTML to reference the new resources:
|
||||
<replay-web-page replayBase="/js/" source="/wacz/example.wacz" url="https://webrecorder.net"></replay-web-page>
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Here is an example embed added directly to this page:
|
||||
</summary>
|
||||
|
||||
<script src="../ui.js"></script>
|
||||
|
||||
<replay-web-page style="height: 600px" embed="replay-with-info" replaybase="../" source="./assets/tweet-example.wacz"
|
||||
url="https://oembed.link/https://twitter.com/webrecorder_io/status/1565881026215219200"></replay-web-page>
|
||||
</details>
|
||||
|
||||
For a working example of hosting multiple web archives take a look at our *example-webarchive* [repository](https://github.com/webrecorder/example-webarchive/) and [static website](https://webrecorder.github.io/example-webarchive) which hosted on Github pages. It may give you ideas for how to integrate the ReplayWeb.page component into your site You may also be interested in [Web Replay Gen](https://github.com/webrecorder/web-replay-gen) which is an 11ty based static site builder for a web archive of WACZ files.
|
||||
|
||||
### Embedding Options
|
||||
@@ -98,11 +110,12 @@ The `<replay-web-page>` tag is a web component that supports a number of additio
|
||||
| `replayBase` | Location of the `sw.js` file, defaults to `./replay/` as mentioned above, but can be overridden. |
|
||||
| `coll` | Internal id for this collection, usually generated automatically.
|
||||
| `config` | Extra per collection config options (such as custom fuzzy matching rules, TODO add more info!) |
|
||||
| `noSandbox` | if set, don't wrap iframe in `sandbox`. Used as extra precaution to avoid escaping iframe, but prevents PDFs from loading in embed archive. Set for archives of known/trusted sites. |
|
||||
| `sandbox` | if set, will iframe in `sandbox`. Provides extra isolation, but prevents PDFs from loading in an embed, and may result in links opening in new windows. |
|
||||
| `noWebWorker`| if set, will not use Web Worker for loading, only Service Worker. May be useful for certain loading edge cases. |
|
||||
| `noCache` | if set, will not cache any loaded content HTTP responses locally, always loading from original source. |
|
||||
| `hideOffscreen` | if set, will unload the embed when it is not visible and reload when scrolled into view. Useful if multiple embeds per-page to avoid loading all at once. |
|
||||
| `newWindowBase` | set base replay URL loaded when a page opens a new window, defaults to `https://replayweb.page/` if `deepLink` not enabled, otherwise, to current page with new link. |
|
||||
| `requireSubdomainIframe` | if set, will only load embed in an iframe loaded from a subdomain, for increased origin isolation. |
|
||||
|
||||
|
||||
### Versioning
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="ui.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: lightgrey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<replay-web-page replaybase="./" embed="replay-with-info" src="./docs/assets/tweet-example.wacz" url="page:0"></replay-web-page>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "replaywebpage",
|
||||
"productName": "ReplayWeb.page",
|
||||
"version": "1.7.0-beta.0",
|
||||
"version": "1.7.0-beta.1",
|
||||
"description": "Serverless Web Archive Replay",
|
||||
"repository": "https://github.com/webrecorder/replayweb.page",
|
||||
"homepage": "https://replayweb.page/",
|
||||
@@ -9,7 +9,7 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"@webrecorder/wabac": "^2.13.0-beta.0",
|
||||
"@webrecorder/wabac": "github:webrecorder/wabac.js",
|
||||
"bulma": "^0.9.3",
|
||||
"electron-log": "^4.4.1",
|
||||
"electron-updater": "^4.3.9",
|
||||
|
||||
+10
-6
@@ -1,11 +1,10 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { wrapCss, rwpLogo, IS_APP, VERSION, clickOnSpacebarPress } from "./misc";
|
||||
|
||||
import { registerSW } from "./pageutils";
|
||||
|
||||
import fasHelp from "@fortawesome/fontawesome-free/svgs/solid/question-circle.svg";
|
||||
import fasArrowLeft from "@fortawesome/fontawesome-free/svgs/solid/arrow-left.svg";
|
||||
import fasArrowRight from "@fortawesome/fontawesome-free/svgs/solid/arrow-right.svg";
|
||||
import { SWManager } from "./swmanager";
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
@@ -28,9 +27,8 @@ class ReplayWebApp extends LitElement
|
||||
|
||||
this.loadInfo = null;
|
||||
|
||||
if (swName) {
|
||||
registerSW(swName);
|
||||
}
|
||||
this.swmanager = new SWManager({name: swName, appName: this.appName});
|
||||
this.swmanager.register().catch(() => this.swErrorMsg = this.swmanager.renderErrorReport(this.mainLogo));
|
||||
|
||||
this.safariKeyframes();
|
||||
}
|
||||
@@ -56,7 +54,9 @@ class ReplayWebApp extends LitElement
|
||||
collPageUrl: { type: String },
|
||||
pageTitle: { type: String },
|
||||
pageReplay: { type: Boolean },
|
||||
source: { type: String }
|
||||
source: { type: String },
|
||||
|
||||
swErrorMsg: { type: Object },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -248,6 +248,10 @@ class ReplayWebApp extends LitElement
|
||||
return html``;
|
||||
}
|
||||
|
||||
if (this.embed && this.swErrorMsg) {
|
||||
return this.swErrorMsg;
|
||||
}
|
||||
|
||||
return html`
|
||||
${!this.embed || this.embed === "full" ? this.renderNavBar() : ""}
|
||||
|
||||
|
||||
+41
-19
@@ -1,9 +1,8 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { registerSW } from "./pageutils";
|
||||
|
||||
import { wrapCss, rwpLogo } from "./misc";
|
||||
import { SWManager } from "./swmanager";
|
||||
|
||||
|
||||
var scriptSrc = document.currentScript && document.currentScript.src;
|
||||
@@ -23,6 +22,7 @@ class Embed extends LitElement
|
||||
// eslint-disable-next-line no-undef
|
||||
this.swName = __SW_NAME__;
|
||||
this.mainElementName = "replay-app-main";
|
||||
this.appName = "ReplayWeb.page";
|
||||
this.view = "replay";
|
||||
this.ts = "";
|
||||
this.url = "";
|
||||
@@ -33,12 +33,14 @@ class Embed extends LitElement
|
||||
this.paramString = null;
|
||||
this.deepLink = false;
|
||||
this.newWindowBase = "";
|
||||
this.swInited = false;
|
||||
this.inited = false;
|
||||
this.embed = null;
|
||||
this.reloadCount = 0;
|
||||
this.noSandbox = false;
|
||||
this.sandbox = false;
|
||||
this.noWebWorker = false;
|
||||
this.noCache = false;
|
||||
// deprecated;
|
||||
this.noSandbox = null;
|
||||
this.logo = rwpLogo;
|
||||
}
|
||||
|
||||
@@ -66,12 +68,13 @@ class Embed extends LitElement
|
||||
coll: { type: String },
|
||||
config: { type: String },
|
||||
|
||||
swInited: { type: Boolean },
|
||||
inited: { type: Boolean },
|
||||
|
||||
paramString: { type: String },
|
||||
hashString: { type: String },
|
||||
|
||||
deepLink: { type: Boolean },
|
||||
sandbox: { type: Boolean },
|
||||
noSandbox: { type: Boolean },
|
||||
noWebWorker: { type: Boolean },
|
||||
noCache: { type: Boolean },
|
||||
@@ -79,16 +82,34 @@ class Embed extends LitElement
|
||||
|
||||
newWindowBase: { type: String },
|
||||
|
||||
errorMessage: { type: String }
|
||||
errorMessage: { type: String },
|
||||
|
||||
requireSubdomainIframe: {type: Boolean}
|
||||
};
|
||||
}
|
||||
|
||||
async doRegister() {
|
||||
const replaybaseURL = new URL(this.replaybase, window.location.href);
|
||||
|
||||
this.isCrossOrigin = replaybaseURL.origin !== window.location.origin;
|
||||
|
||||
if (this.isCrossOrigin) {
|
||||
this.inited = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const name = this.swName;
|
||||
const appName = this.appName;
|
||||
const scope = this.replaybase;
|
||||
const requireSubdomainIframe = this.requireSubdomainIframe;
|
||||
|
||||
this.swmanager = new SWManager({name, scope, requireSubdomainIframe, appName});
|
||||
|
||||
try {
|
||||
await registerSW(this.swName, this.replaybase);
|
||||
this.swInited = true;
|
||||
await this.swmanager.register();
|
||||
this.inited = true;
|
||||
} catch (e) {
|
||||
this.errorMessage = e;
|
||||
this.errorMessage = this.swmanager.renderErrorReport(this.logo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +137,9 @@ class Embed extends LitElement
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
if (this.noSandbox) {
|
||||
console.warn("The noSandbox flag is deprecated. ReplayWeb.page does not add a sandbox by default. To enable sandboxing, use 'sandbox' flag instead. This may result in PDFs not loading and pages opening in new windows, but may be more secure in some situations");
|
||||
}
|
||||
this.doRegister();
|
||||
|
||||
window.addEventListener("message", (event) => this.handleMessage(event));
|
||||
@@ -257,8 +281,8 @@ class Embed extends LitElement
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this.paramString && this.hashString && this.swInited ? html`
|
||||
<iframe sandbox="${ifDefined(!this.noSandbox ?
|
||||
${this.paramString && this.hashString && this.inited ? html`
|
||||
<iframe sandbox="${ifDefined(this.sandbox ?
|
||||
"allow-downloads allow-modals allow-orientation-lock allow-pointer-lock\
|
||||
allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts\
|
||||
allow-same-origin allow-forms" : undefined)}"
|
||||
@@ -268,17 +292,15 @@ class Embed extends LitElement
|
||||
|
||||
` : html``}
|
||||
|
||||
${this.errorMessage ? html`
|
||||
<section class="full-width">
|
||||
<div class="has-text-centered">
|
||||
<fa-icon class="logo" id="wrlogo" size="2.5rem" .svg=${this.logo} aria-hidden="true"></fa-icon>
|
||||
</div>
|
||||
<div class="error">${this.errorMessage}</div>
|
||||
</section>
|
||||
`: ""}`;
|
||||
${this.errorMessage}
|
||||
`;
|
||||
}
|
||||
|
||||
onLoad(event) {
|
||||
if (this.isCrossOrigin) {
|
||||
return;
|
||||
}
|
||||
|
||||
const win = event.target.contentWindow;
|
||||
const doc = event.target.contentDocument;
|
||||
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@ import { wrapCss, IS_APP } from "./misc";
|
||||
|
||||
import prettyBytes from "pretty-bytes";
|
||||
|
||||
import { getSWErrorMsg, parseURLSchemeHostPath } from "./pageutils";
|
||||
import { parseURLSchemeHostPath } from "./pageutils";
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
@@ -125,11 +125,11 @@ class Loader extends LitElement
|
||||
|
||||
this.percent = this.currentSize = this.totalSize = 0;
|
||||
|
||||
const noSWError = getSWErrorMsg();
|
||||
// const noSWError = getSWErrorMsg();
|
||||
|
||||
if (noSWError) {
|
||||
if (this.loadInfo && this.loadInfo.swError) {
|
||||
this.state = "errored";
|
||||
this.error = noSWError;
|
||||
this.error = this.loadInfo.swError;
|
||||
this.errorAllowRetry = false;
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-58
@@ -1,59 +1,3 @@
|
||||
import { register } from "register-service-worker";
|
||||
|
||||
let appName = "ReplayWeb.page";
|
||||
|
||||
// ===========================================================================
|
||||
function setAppName(newAppName) {
|
||||
appName = newAppName;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
function registerSW(name = "sw.js", scope = "./") {
|
||||
let resolve, reject;
|
||||
|
||||
const p = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
const errMsg = getSWErrorMsg();
|
||||
|
||||
if (errMsg) {
|
||||
console.error(errMsg);
|
||||
reject(errMsg);
|
||||
}
|
||||
|
||||
register(scope + name, {
|
||||
registrationOptions: { scope },
|
||||
registered () {
|
||||
console.log("Service worker is registered");
|
||||
resolve();
|
||||
},
|
||||
|
||||
error (error) {
|
||||
console.error("Error during service worker registration:", error);
|
||||
reject(`${appName} could not be loaded due to the following error:\n${error.toString()}`);
|
||||
}
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function getSWErrorMsg() {
|
||||
if (navigator.serviceWorker) {
|
||||
return null;
|
||||
}
|
||||
if (window.location.protocol === "http:") {
|
||||
return `\
|
||||
Sorry, the ${appName} system must be loaded from an HTTPS URL, but was loaded from: ${window.location.host}.
|
||||
Please try loading this page from an HTTPS URL`;
|
||||
} else {
|
||||
return `Sorry, ${appName} won't work in this browser as Service Workers are not supported.
|
||||
Please try a different browser.
|
||||
(Service Workers are disabled in Firefox in Private Mode. If Using Private Mode in Firefox, try regular mode)`;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
async function digestMessage(message, hashtype) {
|
||||
const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array
|
||||
@@ -155,5 +99,4 @@ function parseURLSchemeHostPath(url) {
|
||||
}
|
||||
|
||||
|
||||
export { digestMessage, tsToDate, getTS, getPageDateTS, getReplayLink, sourceToId, parseURLSchemeHostPath,
|
||||
registerSW, getSWErrorMsg, setAppName };
|
||||
export { digestMessage, tsToDate, getTS, getPageDateTS, getReplayLink, sourceToId, parseURLSchemeHostPath };
|
||||
|
||||
+1
-1
@@ -298,7 +298,7 @@ class Replay extends LitElement
|
||||
</div>` : html`
|
||||
|
||||
<div class="iframe-container">
|
||||
<iframe class="iframe-main" @message="${this.onReplayMessage}" allow="autoplay 'self'; fullscreen" allowfullscreen
|
||||
<iframe class="iframe-main" name="___wb_replay_top_frame" @message="${this.onReplayMessage}" allow="autoplay 'self'; fullscreen" allowfullscreen
|
||||
src="${this.iframeUrl}" title="${title}"></iframe>
|
||||
|
||||
${this.showAuth ? html`
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
import { html } from "lit";
|
||||
import { register } from "register-service-worker";
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
export class SWManager
|
||||
{
|
||||
constructor({name = "sw.js", scope = "./", appName = "ReplayWeb.page", requireSubdomainIframe = false} = {}) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.appName = appName;
|
||||
this.requireSubdomainIframe = requireSubdomainIframe;
|
||||
|
||||
this.errorMsg = null;
|
||||
}
|
||||
|
||||
setAppName(newAppName) {
|
||||
this.appName = newAppName;
|
||||
}
|
||||
|
||||
register() {
|
||||
let resolve, reject;
|
||||
|
||||
const p = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
this.errorMsg = this.getSWErrorMsg();
|
||||
|
||||
if (this.errorMsg) {
|
||||
console.error(this.errorMsg);
|
||||
reject(this.errorMsg);
|
||||
}
|
||||
|
||||
const handleError = (error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
this.errorMsg = this.getCrossOriginIframeMsg();
|
||||
if (!this.errorMsg) {
|
||||
this.errorMsg = `${this.appName} could not be loaded due to the following error:\n${error.toString()}`;
|
||||
}
|
||||
|
||||
reject(this.errorMsg);
|
||||
};
|
||||
|
||||
register(this.scope + this.name, {
|
||||
registrationOptions: { scope: this.scope },
|
||||
registered () {
|
||||
console.log("Service worker is registered");
|
||||
resolve();
|
||||
},
|
||||
|
||||
error(errMsg) { handleError(errMsg); }
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
getCrossOriginIframeMsg() {
|
||||
if (this.isCrossOriginIframe()) {
|
||||
return `\
|
||||
Sorry, Service Workers can not be used in cross-origin iframes.
|
||||
This web archive embed is loaded from ${window.location.origin} but the top page is on a different origin.
|
||||
The embed must be loaded from the same origin or a subdomain.`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
isCrossOriginIframe() {
|
||||
if (window.parent === window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return window.top.location.href === "";
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
getSWErrorMsg() {
|
||||
if (navigator.serviceWorker) {
|
||||
|
||||
// must be loaded from a cross-origin (eg. subdomain)
|
||||
if (this.requireSubdomainIframe && !this.isCrossOriginIframe()) {
|
||||
return `Sorry, due to security settings, this ${this.appName} embed only be viewed within a subdomain iframe.`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// loaded from a cross-origin iframe that's *not* a subdomain
|
||||
const msg = this.getCrossOriginIframeMsg();
|
||||
if (msg) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (!window.isSecureContext) {
|
||||
return `
|
||||
Sorry, the ${this.appName} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${window.location.host}.
|
||||
Please try loading this page from an HTTPS URL`;
|
||||
}
|
||||
|
||||
// Detect firefox private mode
|
||||
if ("MozAppearance" in document.documentElement.style) {
|
||||
return "Sorry, Service Workers are disabled in Firefox in Private Mode. Please try loading this page in regular mode instead.";
|
||||
}
|
||||
|
||||
return `Sorry, ${this.appName} won't work in this browser as Service Workers are not supported in this window.
|
||||
Please try a different browser.`;
|
||||
|
||||
}
|
||||
|
||||
renderErrorReport(logo, override) {
|
||||
const msg = this.errorMsg || override;
|
||||
|
||||
if (!msg) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return html`
|
||||
<section class="is-fullwidth">
|
||||
<div class="has-text-centered">
|
||||
<fa-icon style="margin: 1em;flex-grow: 1;" id="wrlogo" size="2.5rem" .svg=${logo} aria-hidden="true"></fa-icon>
|
||||
</div>
|
||||
<div style="white-space: pre-wrap; text-align: center" >${msg}</div>
|
||||
</section>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,10 +1124,9 @@
|
||||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.5.2.tgz#ea584b637ff63c5a477f6f21604b5a205b72c9ec"
|
||||
integrity sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==
|
||||
|
||||
"@webrecorder/wabac@^2.13.0-beta.0":
|
||||
version "2.13.0-beta.0"
|
||||
resolved "https://registry.yarnpkg.com/@webrecorder/wabac/-/wabac-2.13.0-beta.0.tgz#79b6c884b74fe328cc48b9b4ff1948bf1b55309c"
|
||||
integrity sha512-2NwhrtJnFbyseErWplZQiJ/3HN3fWAJsM/aC+Znz3Bn+Z1gWkdVaKu2ah3OaS3sfQZuw2rWqTWvHJYTd/l+ZVA==
|
||||
"@webrecorder/wabac@github:webrecorder/wabac.js":
|
||||
version "2.13.0-beta.1"
|
||||
resolved "https://codeload.github.com/webrecorder/wabac.js/tar.gz/3f9fbabb185d1d8c14cfb34505b81abc2c133bc7"
|
||||
dependencies:
|
||||
"@peculiar/asn1-ecc" "^2.3.0"
|
||||
"@peculiar/asn1-schema" "^2.3.0"
|
||||
@@ -1152,10 +1151,10 @@
|
||||
stream-browserify "^3.0.0"
|
||||
warcio "^1.5.1"
|
||||
|
||||
"@webrecorder/wombat@^3.3.8":
|
||||
version "3.3.8"
|
||||
resolved "https://registry.yarnpkg.com/@webrecorder/wombat/-/wombat-3.3.8.tgz#de9d5de46bad8be208a260165c1204b6edf50c9b"
|
||||
integrity sha512-X876dIJTqqIpjf/uDQHFmZ2HzO3Vz2oyZ6XdDUqFSn30OHIMs5N9K8dx2+g1OCRDglpOKo4KnzCs7hTHYFm9RA==
|
||||
"@webrecorder/wombat@^3.3.9":
|
||||
version "3.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@webrecorder/wombat/-/wombat-3.3.9.tgz#c60f9ac14a955e0ed5471974cc77e81528612754"
|
||||
integrity sha512-tiE/EnYWgZ5zZ1cXDMgEf2cEr4IZxP/h4TWudp4smsNHxPQI+sGo/ouGWJBEUKHzRV63o7eQddpJMnhbJoElnw==
|
||||
dependencies:
|
||||
warcio "^1.5.1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user