From 8616ea7522b06f158489bed60863956eab415be2 Mon Sep 17 00:00:00 2001 From: Ryosuke Asano Date: Fri, 3 Nov 2023 00:02:05 +0900 Subject: [PATCH] [FB] PWA | Save data to external file --- browser/base/content/browser-pageActions.js | 156 ++++++++++++------ ...SiteSpecificBrowserExternalFileService.jsm | 58 +++++++ .../ssb/SiteSpecificBrowserService.jsm | 49 ++++-- browser/components/ssb/moz.build | 1 + 4 files changed, 202 insertions(+), 62 deletions(-) create mode 100644 browser/components/ssb/SiteSpecificBrowserExternalFileService.jsm diff --git a/browser/base/content/browser-pageActions.js b/browser/base/content/browser-pageActions.js index f72ba2ef..fe179acf 100644 --- a/browser/base/content/browser-pageActions.js +++ b/browser/base/content/browser-pageActions.js @@ -4,63 +4,117 @@ * 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/. */ -let QRCodeGeneratePageActionButton = window.MozXULElement.parseXULToFragment(` - - - - - - - - - - - - - - - -`); +/****************************************************** QR Code ******************************************************/ -function generateCurrentTabQRCode() { - Services.scriptloader.loadSubScript("chrome://browser/content/qr-code-styling/qr-code-styling.js", window); - - let currentTab = gBrowser.selectedTab; - let currentTabURL = currentTab.linkedBrowser.currentURI.spec; - - const qrCode = new QRCodeStyling({ - width: 250, - height: 250, - type: "svg", - data: currentTabURL, - image: "chrome://branding/content/about-logo.png", - dotsOptions: { - color: "#4267b2", - }, - cornersSquareOptions: { - type: "extra-rounded", - }, - backgroundOptions: { - color: "#e9ebee", - }, - imageOptions: { - crossOrigin: "anonymous", - margin: 10 +let gFloorpPageAction = { + qrCode: { + QRCodeGeneratePageActionButton: window.MozXULElement.parseXULToFragment(` + + + + + + + + + + + + + + + + `), + onPopupShowing() { + Services.scriptloader.loadSubScript("chrome://browser/content/qr-code-styling/qr-code-styling.js", window); + + let currentTab = gBrowser.selectedTab; + let currentTabURL = currentTab.linkedBrowser.currentURI.spec; + + const qrCode = new QRCodeStyling({ + width: 250, + height: 250, + type: "svg", + data: currentTabURL, + image: "chrome://branding/content/about-logo.png", + dotsOptions: { + color: "#4267b2", + }, + cornersSquareOptions: { + type: "extra-rounded", + }, + backgroundOptions: { + color: "#e9ebee", + }, + imageOptions: { + crossOrigin: "anonymous", + margin: 10 + } + }); + + //remove old qrcode + let QRCodeBox = document.getElementById("qrcode-img-vbox"); + + while (QRCodeBox.firstChild) { + QRCodeBox.firstChild.remove(); + } + + qrCode.append(QRCodeBox); } -}); + }, - //remove old qrcode - let QRCodeBox = document.getElementById("qrcode-img-vbox"); + Ssb: { + SsbPageActionButton: window.MozXULElement.parseXULToFragment(` + + + + + + + + + + + + + + + + `), - while (QRCodeBox.firstChild) { - QRCodeBox.firstChild.remove(); - } + async onPopupShowing() { + let currentPageUrl = gBrowser.selectedBrowser.currentURI.spec; - qrCode.append(QRCodeBox); + let ssb = await SiteSpecificBrowser.createFromBrowser( + gBrowser.selectedBrowser + ); + }, + + async onCommand(event, buttonNode) { + if (!gBrowser.currentURI.schemeIs("https")) { + return; + } + + let ssb = await SiteSpecificBrowser.createFromBrowser( + gBrowser.selectedBrowser + ); + + // Launching through the UI implies installing. + await ssb.install(); + + // The site's manifest may point to a different start page so explicitly + // open the SSB to the current page. + ssb.launch(gBrowser.selectedBrowser.currentURI); + gBrowser.removeTab(gBrowser.selectedTab, { closeWindowWithLastTab: false }); + } + } } SessionStore.promiseInitialized.then(() => { - document.getElementById("star-button-box").before(QRCodeGeneratePageActionButton); + document.getElementById("star-button-box").before(gFloorpPageAction.qrCode.QRCodeGeneratePageActionButton); + document.getElementById("star-button-box").before(gFloorpPageAction.Ssb.SsbPageActionButton); }); diff --git a/browser/components/ssb/SiteSpecificBrowserExternalFileService.jsm b/browser/components/ssb/SiteSpecificBrowserExternalFileService.jsm new file mode 100644 index 00000000..7be5ffd3 --- /dev/null +++ b/browser/components/ssb/SiteSpecificBrowserExternalFileService.jsm @@ -0,0 +1,58 @@ +/* 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/. */ + +"use strict"; + +const EXPORTED_SYMBOLS = ["SiteSpecificBrowserExternalFileService"]; + +let SiteSpecificBrowserExternalFileService = { + get _saveFile() { + return PathUtils.join(PathUtils.profileDir, "ssb.json"); + }, + + async getCurrentSsbData() { + let fileExists = await IOUtils.exists(this._saveFile); + if (!fileExists) { + IOUtils.writeJSON(this._saveFile, {}); + return {}; + }; + + let result = await IOUtils.readJSON( + this._saveFile + ); + + return result; + }, + + async saveSsbData(ssbData) { + await IOUtils.writeJSON(this._saveFile, ssbData); + }, + + get _saveSsbMap() { + return PathUtils.join(PathUtils.profileDir, "ssb-map.json"); + }, + + async ssbMapFileExists() { + let fileExists = await IOUtils.exists(this._saveSsbMap); + return fileExists; + }, + + async getSsbMapData() { + let fileExists = await IOUtils.exists(this._saveSsbMap); + if (!fileExists) { + IOUtils.writeJSON(this._saveSsbMap, {}); + return null; + }; + + let result = await IOUtils.readUTF8( + this._saveSsbMap + ); + + return result; + }, + + async saveSsbMapData(ssbMapData) { + await IOUtils.writeJSON(this._saveSsbMap, ssbMapData); + }, +} diff --git a/browser/components/ssb/SiteSpecificBrowserService.jsm b/browser/components/ssb/SiteSpecificBrowserService.jsm index 39686f03..507ec3f3 100644 --- a/browser/components/ssb/SiteSpecificBrowserService.jsm +++ b/browser/components/ssb/SiteSpecificBrowserService.jsm @@ -34,15 +34,23 @@ const { Services } = ChromeUtils.import( let { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs" ); + +let { KeyValueService } = ChromeUtils.importESModule( + "resource://gre/modules/kvstore.sys.mjs" +); + const { XPCOMUtils } = ChromeUtils.import( "resource://gre/modules/XPCOMUtils.jsm" ); +const { SiteSpecificBrowserExternalFileService } = ChromeUtils.import( + "resource:///modules/SiteSpecificBrowserExternalFileService.jsm" +); + XPCOMUtils.defineLazyModuleGetters(this, { ManifestObtainer: "resource://gre/modules/ManifestObtainer.jsm", ManifestProcessor: "resource://gre/modules/ManifestProcessor.jsm", - KeyValueService: "resource://gre/modules/kvstore.jsm", ImageTools: "resource:///modules/ssb/ImageTools.jsm", }); @@ -270,17 +278,21 @@ async function buildManifestForBrowser(browser) { */ let SSBMap = new Map(); -if (Services.prefs.prefHasUserValue("browser.ssb.SSBMap")) { - function loadMapFromLocalStorage() { - const mapJson = Services.prefs.getStringPref("browser.ssb.SSBMap"); - const serializedMap = JSON.parse(mapJson); - const map = new Map(serializedMap); - return map; + +async function loadMapFromLocalStorage() { + const mapJson = await SiteSpecificBrowserExternalFileService.getSsbMapData(); + if (!mapJson) { + return new Map(); } - - SSBMap = loadMapFromLocalStorage(); + const serializedMap = JSON.parse(mapJson); + const map = new Map(serializedMap); + return map; } +loadMapFromLocalStorage().then((map) => { + SSBMap = map; +}); + /** * The base contains the data about an SSB instance needed in content processes. @@ -390,8 +402,8 @@ class SiteSpecificBrowser extends SiteSpecificBrowserBase { SSBMap.set(id, this); function saveMapToLocalStorage(map) { - let mapJson = JSON.stringify([...map]); - Services.prefs.setStringPref("browser.ssb.SSBMap", mapJson); + const serializedMap = [...map]; + SiteSpecificBrowserExternalFileService.saveSsbMapData(serializedMap); } saveMapToLocalStorage(SSBMap); @@ -542,6 +554,21 @@ class SiteSpecificBrowser extends SiteSpecificBrowserBase { let kvstore = await SiteSpecificBrowserService.getKVStore(); await kvstore.put(storeKey(this.id), JSON.stringify(data)); + + let ssbData = await SiteSpecificBrowserExternalFileService.getCurrentSsbData(); + + if (!ssbData) { + ssbData = {}; + } + + ssbData[this.startURI.spec] = { + name: this.name, + icon: this.getIcon(128).src, + id: this.id, + startURI: this.startURI.spec, + }; + + await SiteSpecificBrowserExternalFileService.saveSsbData(ssbData); } } diff --git a/browser/components/ssb/moz.build b/browser/components/ssb/moz.build index c0dcc871..606a9841 100644 --- a/browser/components/ssb/moz.build +++ b/browser/components/ssb/moz.build @@ -10,6 +10,7 @@ XPCOM_MANIFESTS += [ ] EXTRA_JS_MODULES += [ + "SiteSpecificBrowserExternalFileService.jsm", "SiteSpecificBrowserIdUtils.jsm", "SiteSpecificBrowserService.jsm", ]