Bug 1901520 - Part 2: Add styles and scripts to the single file archive. r=backup-reviewers,frontend-codestyle-reviewers,kpatenio
Differential Revision: https://phabricator.services.mozilla.com/D213975
This commit is contained in:
@@ -40,6 +40,8 @@ browser/branding/**/firefox-branding.js
|
||||
# Gzipped test file.
|
||||
browser/base/content/test/general/gZipOfflineChild.html
|
||||
browser/base/content/test/urlbar/file_blank_but_not_blank.html
|
||||
# Pre-processed template file
|
||||
browser/components/backup/content/archive.template.html
|
||||
# Test files that are really json not js, and don't need to be linted.
|
||||
browser/components/sessionstore/test/unit/data/sessionstore_valid.js
|
||||
browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
|
||||
|
||||
@@ -1194,6 +1194,10 @@ export class BackupService extends EventTarget {
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async renderTemplate(templateURI, isEncrypted, backupMetadata) {
|
||||
const ARCHIVE_STYLES = "chrome://browser/content/backup/archive.css";
|
||||
const ARCHIVE_SCRIPT = "chrome://browser/content/backup/archive.js";
|
||||
const LOGO = "chrome://branding/content/icon128.png";
|
||||
|
||||
let templateResponse = await fetch(templateURI);
|
||||
let templateString = await templateResponse.text();
|
||||
let templateDOM = new DOMParser().parseFromString(
|
||||
@@ -1214,6 +1218,20 @@ export class BackupService extends EventTarget {
|
||||
let supportLink = templateDOM.querySelector("#support-link");
|
||||
supportLink.href = supportLinkHref;
|
||||
|
||||
// Now insert the logo as a dataURL, since we want the single-file backup
|
||||
// archive to be entirely self-contained.
|
||||
let logoResponse = await fetch(LOGO);
|
||||
let logoBlob = await logoResponse.blob();
|
||||
let logoDataURL = await new Promise((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
reader.addEventListener("load", () => resolve(reader.result));
|
||||
reader.addEventListener("error", reject);
|
||||
reader.readAsDataURL(logoBlob);
|
||||
});
|
||||
|
||||
let logoNode = templateDOM.querySelector("#logo");
|
||||
logoNode.src = logoDataURL;
|
||||
|
||||
let encStateNode = templateDOM.querySelector("#encryption-state");
|
||||
lazy.gDOMLocalization.setAttributes(
|
||||
encStateNode,
|
||||
@@ -1244,8 +1262,33 @@ export class BackupService extends EventTarget {
|
||||
// cause backup creation to fail.
|
||||
}
|
||||
|
||||
// We have to insert styles and scripts after we serialize to XML, otherwise
|
||||
// the XMLSerializer will escape things like descendent selectors in CSS
|
||||
// with >.
|
||||
let stylesResponse = await fetch(ARCHIVE_STYLES);
|
||||
let scriptResponse = await fetch(ARCHIVE_SCRIPT);
|
||||
|
||||
// These days, we don't really support CSS preprocessor directives, so we
|
||||
// can't ifdef out the MPL license header in styles before writing it into
|
||||
// the archive file. Instead, we'll ensure that the license header is there,
|
||||
// and then manually remove it here at runtime.
|
||||
let stylesText = await stylesResponse.text();
|
||||
const MPL_LICENSE = `/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/`;
|
||||
if (!stylesText.includes(MPL_LICENSE)) {
|
||||
throw new Error("Expected the MPL license block within archive.css");
|
||||
}
|
||||
|
||||
stylesText = stylesText.replace(MPL_LICENSE, "");
|
||||
|
||||
let serializer = new XMLSerializer();
|
||||
return serializer.serializeToString(templateDOM);
|
||||
return serializer
|
||||
.serializeToString(templateDOM)
|
||||
.replace("{{styles}}", stylesText)
|
||||
.replace("{{script}}", await scriptResponse.text());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
74
browser/components/backup/content/archive.css
Normal file
74
browser/components/backup/content/archive.css
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
body[is-moz-browser] .other-browser,
|
||||
body:not([is-moz-browser]) .moz-browser {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font: message-box;
|
||||
font-size: 14px;
|
||||
width: 28rem;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0060DF;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
ul > li {
|
||||
list-style-type: none;
|
||||
margin-block: 0.35rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #F0F0F4;
|
||||
border-style: solid;
|
||||
border-width: 1px 0px 0px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ol > li {
|
||||
margin-block: 1.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
color: #fbfbfe;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background-color: #0060df;
|
||||
padding: calc(2 * 0.267rem) calc(4 * 0.267rem);
|
||||
font-size: inherit;
|
||||
margin-inline-start: 18px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0250bb;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: #073072;
|
||||
}
|
||||
20
browser/components/backup/content/archive.js
Normal file
20
browser/components/backup/content/archive.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
#if 0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# This file is used to construct the single-file archive of a backup. This
|
||||
# file is part of our source code, and so this is why we include the license
|
||||
# header above. We do not, however, want to apply the header to backup files
|
||||
# that are generated via this template. This is why we use the pre-processor
|
||||
# mechanism to remove this comment block at build time.
|
||||
#
|
||||
#endif
|
||||
*/
|
||||
|
||||
const UA = navigator.userAgent;
|
||||
const isMozBrowser = /Firefox/.test(UA);
|
||||
|
||||
document.body.toggleAttribute("is-moz-browser", isMozBrowser);
|
||||
@@ -20,8 +20,12 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title data-l10n-id="backup-file-title"></title>
|
||||
<style>
|
||||
{{styles}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img id="logo" role="presentation" />
|
||||
<h1 data-l10n-id="backup-file-header"></h1>
|
||||
<p data-l10n-id="backup-file-intro">
|
||||
<a data-l10n-name="backup-file-support-link" id="support-link" target="_blank"></a>
|
||||
@@ -47,4 +51,7 @@
|
||||
</ol>
|
||||
</section>
|
||||
</body>
|
||||
<script>
|
||||
{{script}}
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -20,3 +20,5 @@ browser.jar:
|
||||
content/browser/backup/restore-from-backup.css (content/restore-from-backup.css)
|
||||
content/browser/backup/restore-from-backup.mjs (content/restore-from-backup.mjs)
|
||||
* content/browser/backup/archive.template.html (content/archive.template.html)
|
||||
content/browser/backup/archive.css (content/archive.css)
|
||||
* content/browser/backup/archive.js (content/archive.js)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<title data-l10n-id="backup-file-title"></title>
|
||||
</head>
|
||||
<body>
|
||||
<img id="logo" role="presentation" />
|
||||
<h1 data-l10n-id="backup-file-header"></h1>
|
||||
<p data-l10n-id="backup-file-intro">
|
||||
<a data-l10n-name="backup-file-support-link" id="support-link"></a>
|
||||
|
||||
Reference in New Issue
Block a user