forked from mirrors/gecko-dev
Backed out changeset 17d4c013ed92 (bug 1817183) Backed out changeset cfed8d9c23f3 (bug 1817183) Backed out changeset 62fe2f589efe (bug 1817182) Backed out changeset 557bd773fb85 (bug 1817179) Backed out changeset 7f8a7865868b (bug 1816934) Backed out changeset d6c1d4c0d2a0 (bug 1816934)
146 lines
4.8 KiB
JavaScript
146 lines
4.8 KiB
JavaScript
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
const { XPCOMUtils } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
|
);
|
|
const { FxAccounts } = ChromeUtils.import(
|
|
"resource://gre/modules/FxAccounts.jsm"
|
|
);
|
|
const { Weave } = ChromeUtils.importESModule(
|
|
"resource://services-sync/main.sys.mjs"
|
|
);
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs",
|
|
});
|
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
FxAccountsPairingFlow: "resource://gre/modules/FxAccountsPairing.jsm",
|
|
});
|
|
const { require } = ChromeUtils.importESModule(
|
|
"resource://devtools/shared/loader/Loader.sys.mjs"
|
|
);
|
|
const QR = require("devtools/shared/qrcode/index");
|
|
|
|
// This is only for "labor illusion", see
|
|
// https://www.fastcompany.com/3061519/the-ux-secret-that-will-ruin-apps-for-you
|
|
const MIN_PAIRING_LOADING_TIME_MS = 1000;
|
|
|
|
/**
|
|
* Communication between FxAccountsPairingFlow and gFxaPairDeviceDialog
|
|
* is done using an emitter via the following messages:
|
|
* <- [view:SwitchToWebContent] - Notifies the view to navigate to a specific URL.
|
|
* <- [view:Error] - Notifies the view something went wrong during the pairing process.
|
|
* -> [view:Closed] - Notifies the pairing module the view was closed.
|
|
*/
|
|
var gFxaPairDeviceDialog = {
|
|
init() {
|
|
this._resetBackgroundQR();
|
|
// We let the modal show itself before eventually showing a primary-password dialog later.
|
|
Services.tm.dispatchToMainThread(() => this.startPairingFlow());
|
|
},
|
|
|
|
uninit() {
|
|
// When the modal closes we want to remove any query params
|
|
// To prevent refreshes/restores from reopening the dialog
|
|
const browser = window.docShell.chromeEventHandler;
|
|
browser.loadURI(Services.io.newURI("about:preferences#sync"), {
|
|
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
|
});
|
|
|
|
this.teardownListeners();
|
|
this._emitter.emit("view:Closed");
|
|
},
|
|
|
|
async startPairingFlow() {
|
|
this._resetBackgroundQR();
|
|
document
|
|
.getElementById("qrWrapper")
|
|
.setAttribute("pairing-status", "loading");
|
|
this._emitter = new EventEmitter();
|
|
this.setupListeners();
|
|
try {
|
|
if (!Weave.Utils.ensureMPUnlocked()) {
|
|
throw new Error("Master-password locked.");
|
|
}
|
|
// To keep consistent with our accounts.firefox.com counterpart
|
|
// we restyle the parent dialog this is contained in
|
|
this._styleParentDialog();
|
|
|
|
const [, uri] = await Promise.all([
|
|
new Promise(res => setTimeout(res, MIN_PAIRING_LOADING_TIME_MS)),
|
|
FxAccountsPairingFlow.start({ emitter: this._emitter }),
|
|
]);
|
|
const imgData = QR.encodeToDataURI(uri, "L");
|
|
document.getElementById(
|
|
"qrContainer"
|
|
).style.backgroundImage = `url("${imgData.src}")`;
|
|
document
|
|
.getElementById("qrWrapper")
|
|
.setAttribute("pairing-status", "ready");
|
|
} catch (e) {
|
|
this.onError(e);
|
|
}
|
|
},
|
|
|
|
_styleParentDialog() {
|
|
// Since the dialog title is in the above document, we can't query the
|
|
// document in this level and need to go up one
|
|
let dialogParent = window.parent.document;
|
|
|
|
// To allow the firefox icon to go over the dialog
|
|
let dialogBox = dialogParent.querySelector(".dialogBox");
|
|
dialogBox.style.overflow = "visible";
|
|
dialogBox.style.borderRadius = "12px";
|
|
|
|
let dialogTitle = dialogParent.querySelector(".dialogTitleBar");
|
|
dialogTitle.style.borderBottom = "none";
|
|
dialogTitle.classList.add("fxaPairDeviceIcon");
|
|
},
|
|
|
|
_resetBackgroundQR() {
|
|
// The text we encode doesn't really matter as it is un-scannable (blurry and very transparent).
|
|
const imgData = QR.encodeToDataURI(
|
|
"https://accounts.firefox.com/pair",
|
|
"L"
|
|
);
|
|
document.getElementById(
|
|
"qrContainer"
|
|
).style.backgroundImage = `url("${imgData.src}")`;
|
|
},
|
|
|
|
onError(err) {
|
|
console.error(err);
|
|
this.teardownListeners();
|
|
document
|
|
.getElementById("qrWrapper")
|
|
.setAttribute("pairing-status", "error");
|
|
},
|
|
|
|
_switchToUrl(url) {
|
|
const browser = window.docShell.chromeEventHandler;
|
|
browser.fixupAndLoadURIString(url, {
|
|
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
|
|
{}
|
|
),
|
|
});
|
|
},
|
|
|
|
setupListeners() {
|
|
this._switchToWebContent = (_, url) => this._switchToUrl(url);
|
|
this._onError = (_, error) => this.onError(error);
|
|
this._emitter.once("view:SwitchToWebContent", this._switchToWebContent);
|
|
this._emitter.on("view:Error", this._onError);
|
|
},
|
|
|
|
teardownListeners() {
|
|
try {
|
|
this._emitter.off("view:SwitchToWebContent", this._switchToWebContent);
|
|
this._emitter.off("view:Error", this._onError);
|
|
} catch (e) {
|
|
console.warn("Error while tearing down listeners.", e);
|
|
}
|
|
},
|
|
};
|