mirror of
https://github.com/floccusaddon/floccus
synced 2025-04-29 15:47:21 +08:00
First pass migrating to manifest v3
This commit is contained in:
parent
ded6aa36ae
commit
8538e403e4
@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Floccus</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="../../lib/chrome-promise.js"></script>
|
||||
<script src="../js/background-script.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,83 +0,0 @@
|
||||
/*!
|
||||
* chrome-promise 1.0.7
|
||||
* https://github.com/tfoxy/chrome-promise
|
||||
*
|
||||
* Copyright 2015 Tomás Fox
|
||||
* Released under the MIT license
|
||||
*/
|
||||
|
||||
(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory.bind(null, typeof exports === 'object' ? this : root));
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory(this);
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.ChromePromise = factory(root);
|
||||
}
|
||||
}(this, function(root) {
|
||||
'use strict';
|
||||
var push = Array.prototype.push,
|
||||
hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
return ChromePromise;
|
||||
|
||||
////////////////
|
||||
|
||||
function ChromePromise(chrome, Promise) {
|
||||
chrome = chrome || root.chrome;
|
||||
Promise = Promise || root.Promise;
|
||||
|
||||
var runtime = chrome.runtime;
|
||||
|
||||
fillProperties(chrome, this);
|
||||
|
||||
////////////////
|
||||
|
||||
function setPromiseFunction(fn, thisArg) {
|
||||
|
||||
return function() {
|
||||
var args = arguments;
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
function callback() {
|
||||
var err = runtime.lastError;
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve.apply(null, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
push.call(args, callback);
|
||||
|
||||
fn.apply(thisArg, args);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function fillProperties(source, target) {
|
||||
for (var key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
var val = source[key];
|
||||
var type = typeof val;
|
||||
|
||||
if (type === 'object' && !(val instanceof ChromePromise) && key.indexOf('on') != 0) {
|
||||
target[key] = {};
|
||||
fillProperties(val, target[key]);
|
||||
} else if (type === 'function') {
|
||||
target[key] = setPromiseFunction(val, source);
|
||||
} else {
|
||||
target[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"manifest_version": 3,
|
||||
"name": "floccus bookmarks sync",
|
||||
"short_name": "floccus",
|
||||
"version": "4.19.1",
|
||||
@ -19,18 +19,21 @@
|
||||
|
||||
"default_locale": "en",
|
||||
|
||||
"permissions": ["https://*/", "http://*/", "alarms", "bookmarks", "storage", "unlimitedStorage", "tabs", "identity"],
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",
|
||||
"permissions": ["alarms", "bookmarks", "storage", "unlimitedStorage", "tabs", "identity"],
|
||||
"host_permissions": [
|
||||
"*://*/*"
|
||||
],
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self'; object-src 'self';"
|
||||
},
|
||||
|
||||
"options_ui": {
|
||||
"page": "dist/html/options.html",
|
||||
"browser_style": false,
|
||||
"chrome_style": false
|
||||
"browser_style": false
|
||||
},
|
||||
|
||||
"browser_action": {
|
||||
"action": {
|
||||
"browser_style": false,
|
||||
"chrome_style": false,
|
||||
"default_icon": {
|
||||
"48": "icons/logo.png"
|
||||
},
|
||||
@ -39,6 +42,6 @@
|
||||
},
|
||||
|
||||
"background": {
|
||||
"page": "dist/html/background.html"
|
||||
"service_worker": "dist/js/background-script.js"
|
||||
}
|
||||
}
|
||||
|
27
package-lock.json
generated
27
package-lock.json
generated
@ -33,7 +33,6 @@
|
||||
"intl-messageformat": "^9.9.1",
|
||||
"js-base64": "^3.7.5",
|
||||
"lodash": "^4.17.20",
|
||||
"onwakeup": "^0.0.2",
|
||||
"p-queue": "^5.0.0",
|
||||
"punycode": "^2.1.1",
|
||||
"random": "^2.2.0",
|
||||
@ -4498,9 +4497,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001468",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz",
|
||||
"integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==",
|
||||
"version": "1.0.30001491",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001491.tgz",
|
||||
"integrity": "sha512-17EYIi4TLnPiTzVKMveIxU5ETlxbSO3B6iPvMbprqnKh4qJsQGk5Nh1Lp4jIMAE0XfrujsJuWZAM3oJdMHaKBA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -4510,6 +4509,10 @@
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -11269,11 +11272,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/onwakeup": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/onwakeup/-/onwakeup-0.0.2.tgz",
|
||||
"integrity": "sha512-CNRpi/d+0Q9Ep+gn5L8eRLhKj9itLWnPk3cmYMz9SYlgUSB7HffRr0VkYuvPpCQ0tgFLVLFqlhbLvNao+Yqb4g=="
|
||||
},
|
||||
"node_modules/open": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
|
||||
@ -19662,9 +19660,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001468",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz",
|
||||
"integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==",
|
||||
"version": "1.0.30001491",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001491.tgz",
|
||||
"integrity": "sha512-17EYIi4TLnPiTzVKMveIxU5ETlxbSO3B6iPvMbprqnKh4qJsQGk5Nh1Lp4jIMAE0XfrujsJuWZAM3oJdMHaKBA==",
|
||||
"dev": true
|
||||
},
|
||||
"caseless": {
|
||||
@ -24885,11 +24883,6 @@
|
||||
"mimic-fn": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"onwakeup": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/onwakeup/-/onwakeup-0.0.2.tgz",
|
||||
"integrity": "sha512-CNRpi/d+0Q9Ep+gn5L8eRLhKj9itLWnPk3cmYMz9SYlgUSB7HffRr0VkYuvPpCQ0tgFLVLFqlhbLvNao+Yqb4g=="
|
||||
},
|
||||
"open": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
|
||||
|
14
package.json
14
package.json
@ -94,7 +94,6 @@
|
||||
"intl-messageformat": "^9.9.1",
|
||||
"js-base64": "^3.7.5",
|
||||
"lodash": "^4.17.20",
|
||||
"onwakeup": "^0.0.2",
|
||||
"p-queue": "^5.0.0",
|
||||
"punycode": "^2.1.1",
|
||||
"random": "^2.2.0",
|
||||
@ -111,6 +110,17 @@
|
||||
"> 0.25%",
|
||||
"last 2 versions and supports es6-generators",
|
||||
"Firefox ESR",
|
||||
"not dead"
|
||||
"not dead",
|
||||
"not bb >= 0",
|
||||
"not and_chr >= 0",
|
||||
"not and_ff >= 0",
|
||||
"not and_qq >= 0",
|
||||
"not and_uc >= 0",
|
||||
"not ie_mob >= 0",
|
||||
"not op_mini all",
|
||||
"not op_mob >= 0",
|
||||
"not Safari >= 0",
|
||||
"not KaiOS >= 0",
|
||||
"not Samsung >= 0"
|
||||
]
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
import BrowserController from '../lib/browser/BrowserController'
|
||||
|
||||
window.controller = new BrowserController()
|
||||
|
||||
const onload = () => {
|
||||
window.controller.onLoad()
|
||||
}
|
||||
window.addEventListener('load', onload)
|
||||
const controller = new BrowserController()
|
||||
controller.onLoad()
|
||||
|
@ -1,3 +1,2 @@
|
||||
import app from '../ui'
|
||||
|
||||
app()
|
||||
|
@ -8,7 +8,7 @@ import IAccountStorage, { IAccountData, TAccountStrategy } from './interfaces/Ac
|
||||
import { TAdapter } from './interfaces/Adapter'
|
||||
import { IResource, TLocalTree } from './interfaces/Resource'
|
||||
import Controller from './Controller'
|
||||
import { Device } from '@capacitor/device'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import IAccount from './interfaces/Account'
|
||||
import Mappings from './Mappings'
|
||||
|
||||
@ -24,7 +24,7 @@ export default class Account {
|
||||
static singleton : IAccount
|
||||
|
||||
static async getAccountClass(): Promise<IAccount> {
|
||||
if ((await Device.getInfo()).platform === 'web') {
|
||||
if (Capacitor.getPlatform() === 'web') {
|
||||
this.singleton = (await import('./browser/BrowserAccount')).default
|
||||
} else {
|
||||
this.singleton = (await import('./native/NativeAccount')).default
|
||||
@ -109,7 +109,8 @@ export default class Account {
|
||||
|
||||
async setData(data:IAccountData):Promise<void> {
|
||||
const controller = await Controller.getSingleton()
|
||||
await this.storage.setAccountData(data, controller.key)
|
||||
const key = await controller.getKey()
|
||||
await this.storage.setAccountData(data, key)
|
||||
this.server.setData(data)
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,106 @@
|
||||
import { Device } from '@capacitor/device'
|
||||
import IController from './interfaces/Controller'
|
||||
|
||||
export default class Controller {
|
||||
export default class Controller implements IController {
|
||||
static singleton: IController
|
||||
|
||||
static async getSingleton():Promise<IController> {
|
||||
if (!this.singleton) {
|
||||
if ((await Device.getInfo()).platform === 'web') {
|
||||
const browser = (await import('./browser-api')).default
|
||||
const background = await browser.runtime.getBackgroundPage()
|
||||
this.singleton = background.controller
|
||||
} else {
|
||||
const NativeController = await import('./native/NativeController')
|
||||
this.singleton = NativeController.default.getSingleton()
|
||||
}
|
||||
this.singleton = new Controller
|
||||
}
|
||||
return this.singleton
|
||||
}
|
||||
|
||||
cancelSync(accountId, keepEnabled): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'cancelSync', params: [accountId, keepEnabled]})
|
||||
})
|
||||
}
|
||||
|
||||
onStatusChange(listener): () => void {
|
||||
const eventListener = (event) => {
|
||||
const {type} = event.data
|
||||
if (type === 'onStatusChange') {
|
||||
listener()
|
||||
}
|
||||
}
|
||||
navigator.serviceWorker.addEventListener('message', eventListener)
|
||||
return function() {
|
||||
navigator.serviceWorker.removeEventListener('message', eventListener)
|
||||
}
|
||||
}
|
||||
|
||||
scheduleSync(accountId, wait): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'scheduleSync', params: [accountId, wait]})
|
||||
})
|
||||
}
|
||||
|
||||
setEnabled(enabled: boolean): void {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'setEnabled', params: [enabled]})
|
||||
})
|
||||
}
|
||||
|
||||
setKey(key): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'setKey', params: [key]})
|
||||
})
|
||||
}
|
||||
|
||||
syncAccount(accountId, strategy): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'setEnabled', params: [accountId, strategy]})
|
||||
})
|
||||
}
|
||||
|
||||
unlock(key): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'unlock', params: [key]})
|
||||
})
|
||||
}
|
||||
|
||||
unsetKey(): Promise<void> {
|
||||
return navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({type: 'unsetKey', params: []})
|
||||
})
|
||||
}
|
||||
|
||||
getKey(): Promise<string|null> {
|
||||
return new Promise((resolve) => {
|
||||
const eventListener = (event) => {
|
||||
if (event.data.type === 'getKeyResponse') {
|
||||
resolve(event.data.params[0])
|
||||
navigator.serviceWorker.removeEventListener('message', eventListener)
|
||||
}
|
||||
}
|
||||
navigator.serviceWorker.addEventListener('message', eventListener)
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({ type: 'getKey', params: [] })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getUnlocked(): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const eventListener = (event) => {
|
||||
if (event.data.type === 'getUnlockedResponse') {
|
||||
resolve(event.data.params[0])
|
||||
navigator.serviceWorker.removeEventListener('message', eventListener)
|
||||
}
|
||||
}
|
||||
navigator.serviceWorker.addEventListener('message', eventListener)
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
const worker = registration.active
|
||||
worker.postMessage({ type: 'getUnlocked', params: [] })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* global DEBUG */
|
||||
import { Device } from '@capacitor/device'
|
||||
import util from 'util'
|
||||
import * as Parallel from 'async-parallel'
|
||||
import packageJson from '../../package.json'
|
||||
import Crypto from './Crypto'
|
||||
import { Share } from '@capacitor/share'
|
||||
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
|
||||
export default class Logger {
|
||||
static log() {
|
||||
@ -17,7 +17,7 @@ export default class Logger {
|
||||
}
|
||||
|
||||
static async persist() {
|
||||
const Storage = ((await Device.getInfo()).platform === 'web') ? await import('./browser/BrowserAccountStorage') : await import('./native/NativeAccountStorage')
|
||||
const Storage = (Capacitor.getPlatform() === 'web') ? await import('./browser/BrowserAccountStorage') : await import('./native/NativeAccountStorage')
|
||||
await Storage.default.changeEntry(
|
||||
'logs',
|
||||
log => {
|
||||
@ -30,7 +30,7 @@ export default class Logger {
|
||||
}
|
||||
|
||||
static async getLogs() {
|
||||
const Storage = ((await Device.getInfo()).platform === 'web') ? await import('./browser/BrowserAccountStorage') : await import('./native/NativeAccountStorage')
|
||||
const Storage = (Capacitor.getPlatform() === 'web') ? await import('./browser/BrowserAccountStorage') : await import('./native/NativeAccountStorage')
|
||||
return Storage.default.getEntry('logs', [])
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ export default class Logger {
|
||||
}
|
||||
|
||||
static async download(filename, blob) {
|
||||
if ((await Device.getInfo()).platform === 'web') {
|
||||
if (Capacitor.getPlatform() === 'web') {
|
||||
const element = document.createElement('a')
|
||||
|
||||
let objectUrl = URL.createObjectURL(blob)
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
OAuthTokenError
|
||||
} from '../../errors/Error'
|
||||
import { OAuth2Client } from '@byteowls/capacitor-oauth2'
|
||||
import { Device } from '@capacitor/device'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { Http } from '@capacitor-community/http'
|
||||
|
||||
const OAuthConfig = {
|
||||
@ -58,7 +58,7 @@ export default class GoogleDriveAdapter extends CachingAdapter {
|
||||
}
|
||||
|
||||
static async authorize(interactive = true) {
|
||||
const { platform } = await Device.getInfo()
|
||||
const platform = Capacitor.getPlatform()
|
||||
|
||||
if (platform !== 'web') {
|
||||
const result = await OAuth2Client.authenticate(OAuthConfig)
|
||||
@ -134,7 +134,7 @@ export default class GoogleDriveAdapter extends CachingAdapter {
|
||||
}
|
||||
|
||||
async getAccessToken(refreshToken:string) {
|
||||
const {platform} = await Device.getInfo()
|
||||
const platform = Capacitor.getPlatform()
|
||||
const credentialType = platform
|
||||
|
||||
const response = await this.request('POST', 'https://oauth2.googleapis.com/token',
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
SlashError
|
||||
} from '../../errors/Error'
|
||||
import { Http } from '@capacitor-community/http'
|
||||
import { Device } from '@capacitor/device'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import Html from '../serializers/Html'
|
||||
|
||||
const LOCK_INTERVAL = 2 * 60 * 1000 // Lock every 2mins while syncing
|
||||
@ -283,8 +283,7 @@ export default class WebDavAdapter extends CachingAdapter {
|
||||
}
|
||||
|
||||
async uploadFile(url, content_type, data) {
|
||||
const info = await Device.getInfo()
|
||||
if (info.platform === 'web') {
|
||||
if (Capacitor.getPlatform() === 'web') {
|
||||
return this.uploadFileWeb(url, content_type, data)
|
||||
} else {
|
||||
return this.uploadFileNative(url, content_type, data)
|
||||
@ -352,8 +351,7 @@ export default class WebDavAdapter extends CachingAdapter {
|
||||
}
|
||||
|
||||
async downloadFile(url) {
|
||||
const info = await Device.getInfo()
|
||||
if (info.platform === 'web') {
|
||||
if (Capacitor.getPlatform() === 'web') {
|
||||
return this.downloadFileWeb(url)
|
||||
} else {
|
||||
return this.downloadFileNative(url)
|
||||
|
@ -1,4 +1,63 @@
|
||||
/* global ChromePromise chrome browser */
|
||||
/* global chrome browser */
|
||||
|
||||
const ChromePromise = (function(root) {
|
||||
'use strict'
|
||||
var push = Array.prototype.push,
|
||||
hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
|
||||
return ChromePromise
|
||||
|
||||
function ChromePromise(chrome, Promise) {
|
||||
chrome = chrome || root.chrome
|
||||
Promise = Promise || root.Promise
|
||||
|
||||
var runtime = chrome.runtime
|
||||
|
||||
fillProperties(chrome, this)
|
||||
|
||||
/// /////////////
|
||||
|
||||
function setPromiseFunction(fn, thisArg) {
|
||||
return function() {
|
||||
var args = arguments
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
function callback() {
|
||||
var err = runtime.lastError
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve.apply(null, arguments)
|
||||
}
|
||||
}
|
||||
|
||||
push.call(args, callback)
|
||||
|
||||
fn.apply(thisArg, args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function fillProperties(source, target) {
|
||||
for (var key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
var val = source[key]
|
||||
var type = typeof val
|
||||
|
||||
if (type === 'object' && !(val instanceof ChromePromise) && key.indexOf('on') !== 0) {
|
||||
target[key] = {}
|
||||
fillProperties(val, target[key])
|
||||
} else if (type === 'function') {
|
||||
target[key] = setPromiseFunction(val, source)
|
||||
} else {
|
||||
target[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})(this || window || self)
|
||||
|
||||
let b
|
||||
if (typeof browser === 'undefined' && typeof chrome !== 'undefined') {
|
||||
b = new ChromePromise()
|
||||
|
@ -13,12 +13,14 @@ import {
|
||||
UnknownFolderItemOrderError
|
||||
} from '../../errors/Error'
|
||||
import {i18n} from '../native/I18n'
|
||||
import Controller from '../Controller'
|
||||
|
||||
export default class BrowserAccount extends Account {
|
||||
static async get(id:string):Promise<Account> {
|
||||
const storage = new BrowserAccountStorage(id)
|
||||
const background = await browser.runtime.getBackgroundPage()
|
||||
const data = await storage.getAccountData(background.controller.key)
|
||||
const controller = await Controller.getSingleton()
|
||||
const key = await controller.getKey()
|
||||
const data = await storage.getAccountData(key)
|
||||
const tree = new BrowserTree(storage, data.localRoot)
|
||||
return new BrowserAccount(id, storage, await AdapterFactory.factory(data), tree)
|
||||
}
|
||||
@ -28,8 +30,9 @@ export default class BrowserAccount extends Account {
|
||||
const adapter = await AdapterFactory.factory(data)
|
||||
const storage = new BrowserAccountStorage(id)
|
||||
|
||||
const background = await browser.runtime.getBackgroundPage()
|
||||
await storage.setAccountData(data, background.controller.key)
|
||||
const controller = await Controller.getSingleton()
|
||||
const key = await controller.getKey()
|
||||
await storage.setAccountData(data, key)
|
||||
const tree = new BrowserTree(storage, data.localRoot)
|
||||
return new BrowserAccount(id, storage, adapter, tree)
|
||||
}
|
||||
@ -68,8 +71,9 @@ export default class BrowserAccount extends Account {
|
||||
}
|
||||
|
||||
async updateFromStorage():Promise<void> {
|
||||
const background = await browser.runtime.getBackgroundPage()
|
||||
const data = await this.storage.getAccountData(background.controller.key)
|
||||
const controller = await Controller.getSingleton()
|
||||
const key = await controller.getKey()
|
||||
const data = await this.storage.getAccountData(key)
|
||||
this.server.setData(data)
|
||||
this.localTree = new BrowserTree(this.storage, data.localRoot)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import DefunctCryptography from '../DefunctCrypto'
|
||||
import packageJson from '../../../package.json'
|
||||
import BrowserAccountStorage from './BrowserAccountStorage'
|
||||
import uniqBy from 'lodash/uniqBy'
|
||||
import onwakeup from 'onwakeup'
|
||||
|
||||
import PQueue from 'p-queue'
|
||||
import Account from '../Account'
|
||||
@ -64,9 +63,6 @@ export default class BrowserController {
|
||||
this.onchange(localId, details)
|
||||
)
|
||||
|
||||
// Set up onWakeup
|
||||
onwakeup(() => this.onWakeup())
|
||||
|
||||
// Set up the alarms
|
||||
|
||||
browser.alarms.create('checkSync', { periodInMinutes: 1 })
|
||||
@ -114,6 +110,19 @@ export default class BrowserController {
|
||||
|
||||
// Set correct badge after waiting a bit
|
||||
setTimeout(() => this.updateStatus(), 3000)
|
||||
|
||||
// Setup service worker messaging
|
||||
|
||||
this.onStatusChange(async() => {
|
||||
const clientList = await self.clients.matchAll()
|
||||
clientList.forEach(client => client.postMessage({type: 'onStatusChange', params: []}))
|
||||
})
|
||||
|
||||
addEventListener('message', async(event) => {
|
||||
const {type, params} = event.data
|
||||
const result = await this[type](...params)
|
||||
event.source.postMessage({type: type + 'Response', params: [result]})
|
||||
})
|
||||
}
|
||||
|
||||
setEnabled(enabled) {
|
||||
@ -199,6 +208,14 @@ export default class BrowserController {
|
||||
await Promise.all(accounts.map(a => a.setData(a.getData())))
|
||||
}
|
||||
|
||||
getKey() {
|
||||
return Promise.resolve(this.key)
|
||||
}
|
||||
|
||||
getUnlocked() {
|
||||
return Promise.resolve(this.unlocked)
|
||||
}
|
||||
|
||||
async onchange(localId, details) {
|
||||
if (!this.enabled) {
|
||||
return
|
||||
@ -373,13 +390,4 @@ export default class BrowserController {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async onWakeup() {
|
||||
const accounts = await Account.getAllAccounts()
|
||||
await Promise.all(
|
||||
accounts.map(async acc => {
|
||||
await acc.cancelSync()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ export default class BrowserTree implements IResource {
|
||||
})
|
||||
folder.isRoot = isRoot
|
||||
return folder
|
||||
} else if (window.location.protocol === 'moz-extension:' && node.type === 'separator') {
|
||||
} else if (self.location.protocol === 'moz-extension:' && node.type === 'separator') {
|
||||
// Translate mozilla separators to floccus separators
|
||||
return new Tree.Bookmark({
|
||||
location: ItemLocation.LOCAL,
|
||||
@ -121,7 +121,7 @@ export default class BrowserTree implements IResource {
|
||||
return
|
||||
}
|
||||
try {
|
||||
if (window.location.protocol === 'moz-extension:' && url.parse(bookmark.url).hostname === 'separator.floccus.org') {
|
||||
if (self.location.protocol === 'moz-extension:' && url.parse(bookmark.url).hostname === 'separator.floccus.org') {
|
||||
const node = await this.queue.add(() =>
|
||||
browser.bookmarks.create({
|
||||
parentId: bookmark.parentId,
|
||||
@ -150,7 +150,7 @@ export default class BrowserTree implements IResource {
|
||||
return
|
||||
}
|
||||
try {
|
||||
if (window.location.protocol === 'moz-extension:' && url.parse(bookmark.url).hostname === 'separator.floccus.org') {
|
||||
if (self.location.protocol === 'moz-extension:' && url.parse(bookmark.url).hostname === 'separator.floccus.org') {
|
||||
// noop
|
||||
} else {
|
||||
await this.queue.add(() =>
|
||||
|
@ -1,14 +1,12 @@
|
||||
export default interface IController {
|
||||
key: string;
|
||||
setEnabled(): void;
|
||||
setEnabled(enabled:boolean): void;
|
||||
setKey(key):Promise<void>;
|
||||
unlock(key):Promise<void>;
|
||||
unsetKey():Promise<void>;
|
||||
onchange(localId, details):Promise<void>;
|
||||
scheduleSync(accountId, wait):Promise<void>;
|
||||
cancelSync(accountId, keepEnabled):Promise<void>;
|
||||
syncAccount(accountId, strategy):Promise<void>;
|
||||
updateStatus():Promise<void>;
|
||||
onStatusChange(listener):()=>void;
|
||||
onLoad():Promise<void>;
|
||||
getKey():Promise<string|null>;
|
||||
getUnlocked():Promise<boolean>;
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ export default class NativeAccount extends Account {
|
||||
static async get(id:string):Promise<Account> {
|
||||
const storage = new NativeAccountStorage(id)
|
||||
const controller = await Controller.getSingleton()
|
||||
const data = await storage.getAccountData(controller.key)
|
||||
const key = await controller.getKey()
|
||||
const data = await storage.getAccountData(key)
|
||||
const tree = new NativeTree(storage)
|
||||
await tree.load()
|
||||
return new NativeAccount(id, storage, await AdapterFactory.factory(data), tree)
|
||||
@ -32,7 +33,8 @@ export default class NativeAccount extends Account {
|
||||
const storage = new NativeAccountStorage(id)
|
||||
|
||||
const controller = await Controller.getSingleton()
|
||||
await storage.setAccountData(data, controller.key)
|
||||
const key = await controller.getKey()
|
||||
await storage.setAccountData(data, key)
|
||||
const tree = new NativeTree(storage)
|
||||
await tree.load()
|
||||
return new NativeAccount(id, storage, adapter, tree)
|
||||
|
@ -5,7 +5,6 @@ import NativeAccountStorage from './NativeAccountStorage'
|
||||
|
||||
import PQueue from 'p-queue'
|
||||
import Account from '../Account'
|
||||
import onwakeup from 'onwakeup'
|
||||
|
||||
const INACTIVITY_TIMEOUT = 1000 * 7
|
||||
const DEFAULT_SYNC_INTERVAL = 15
|
||||
@ -54,9 +53,6 @@ export default class NativeController {
|
||||
|
||||
this.alarms = new AlarmManager(this)
|
||||
|
||||
// Set up onWakeup
|
||||
onwakeup(() => this.onWakeup())
|
||||
|
||||
// lock accounts when locking is enabled
|
||||
|
||||
Storage.get({key: 'accountsLocked' }).then(async({value: accountsLocked}) => {
|
||||
@ -66,6 +62,19 @@ export default class NativeController {
|
||||
this.key = null
|
||||
}
|
||||
})
|
||||
|
||||
// Setup service worker messaging
|
||||
|
||||
this.onStatusChange(async() => {
|
||||
const clientList = await self.clients.matchAll()
|
||||
clientList.forEach(client => client.postMessage({type: 'onStatusChange', params: []}))
|
||||
})
|
||||
|
||||
addEventListener('message', async(event) => {
|
||||
const {type, params} = event.data
|
||||
const result = await this[type](...params)
|
||||
event.source.postMessage({type: type + 'Response', params: [result]})
|
||||
})
|
||||
}
|
||||
|
||||
setEnabled(enabled) {
|
||||
@ -122,6 +131,14 @@ export default class NativeController {
|
||||
await Promise.all(accounts.map(a => a.setData(a.getData())))
|
||||
}
|
||||
|
||||
getKey() {
|
||||
return Promise.resolve(this.key)
|
||||
}
|
||||
|
||||
getUnlocked() {
|
||||
return Promise.resolve(this.unlocked)
|
||||
}
|
||||
|
||||
async scheduleSync(accountId, wait) {
|
||||
if (wait) {
|
||||
if (this.schedule[accountId]) {
|
||||
@ -206,15 +223,6 @@ export default class NativeController {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async onWakeup() {
|
||||
const accounts = await Account.getAllAccounts()
|
||||
await Promise.all(
|
||||
accounts.map(async acc => {
|
||||
await acc.cancelSync()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let singleton
|
||||
|
@ -7,7 +7,7 @@ class XbelSerializer implements Serializer {
|
||||
}
|
||||
|
||||
deserialize(xbel) {
|
||||
const xmlDoc = new window.DOMParser().parseFromString(
|
||||
const xmlDoc = new DOMParser().parseFromString(
|
||||
xbel,
|
||||
'application/xml'
|
||||
)
|
||||
|
@ -46,7 +46,7 @@ export default class SyncProcess {
|
||||
this.actionsDone = 0
|
||||
this.actionsPlanned = 0
|
||||
this.canceled = false
|
||||
this.isFirefox = window.location.protocol === 'moz-extension:'
|
||||
this.isFirefox = self.location.protocol === 'moz-extension:'
|
||||
}
|
||||
|
||||
async cancel() :Promise<void> {
|
||||
|
@ -1,17 +1,12 @@
|
||||
import { Device } from '@capacitor/device'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { App } from '@capacitor/app'
|
||||
|
||||
let deviceInfo = {}
|
||||
Device.getInfo().then(info => {
|
||||
deviceInfo.platform = info.platform
|
||||
})
|
||||
|
||||
let backButtonListener = null
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
isBrowser() {
|
||||
return deviceInfo.platform === 'web' || !deviceInfo.platform
|
||||
return Capacitor.getPlatform() === 'web' || !Capacitor.getPlatform()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
@ -10,8 +10,10 @@ import { Base64 } from 'js-base64'
|
||||
export const actionsDefinition = {
|
||||
async [actions.LOAD_LOCKED]({ commit, dispatch, state }) {
|
||||
const controller = await Controller.getSingleton()
|
||||
commit(mutations.SET_LOCKED, !controller.unlocked)
|
||||
commit(mutations.SET_SECURED, typeof controller.key === 'string' || !controller.unlocked)
|
||||
const key = await controller.getKey()
|
||||
const unlocked = await controller.getUnlocked()
|
||||
commit(mutations.SET_LOCKED, !unlocked)
|
||||
commit(mutations.SET_SECURED, typeof key === 'string' || !unlocked)
|
||||
},
|
||||
async [actions.UNLOCK]({commit, dispatch, state}, key) {
|
||||
const controller = await Controller.getSingleton()
|
||||
|
Loading…
x
Reference in New Issue
Block a user