annotate background.js @ 3:48b036902118 version-1

Release version 1
author Guido Berhoerster <guido+set-aside@berhoerster.name>
date Thu, 22 Nov 2018 15:51:28 +0100
parents b0827360b8e4
children 9d699dc7823d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
1 /*
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
2 * Copyright (C) 2018 Guido Berhoerster <guido+set-aside@berhoerster.name>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
3 *
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
4 * This Source Code Form is subject to the terms of the Mozilla Public
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
7 */
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
8
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
9 'use strict';
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
10
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
11 const SUPPORTED_PROTOCOLS = ['https:', 'http:', 'ftp:'];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
12 const GROUP_KEY_RE = /^collection:[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
13 const FIREFOX_VERSION_RE = /^(\d+(?:\.\d+)*)(?:([ab]|pre)(\d+))?$/;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
14 const FIREFOX_RELEASE_TYPES = {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
15 'a': 'alpha',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
16 'b': 'beta',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
17 'pre': 'prerelease',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
18 '': ''
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
19 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
20 const THUMBNAIL_WIDTH = 224;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
21 const THUMBNAIL_HEIGHT = 128;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
22
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
23 var tabCollectionsProxy;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
24
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
25 function generateUuidV4String() {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
26 let uuid = new Uint8Array(16);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
27 window.crypto.getRandomValues(uuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
28 uuid[6] = (uuid[6] & 0x0f) | 0x40;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
29 uuid[8] = (uuid[8] & 0x3f) | 0x80;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
30
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
31 let result = [];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
32 for (let i = 0; i < uuid.length; i++) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
33 if (i == 4 || i == 6 || i == 8 || i == 10) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
34 result.push('-');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
35 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
36 result.push(uuid[i].toString(16).padStart(2, '0'));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
37 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
38
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
39 return result.join('');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
40 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
41
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
42 function parseFirefoxVersion(firefoxVersionString) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
43 let [, versionString, releaseTypeAbbrev = '', releaseNumberString = '0'] =
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
44 FIREFOX_VERSION_RE.exec(firefoxVersionString);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
45
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
46 let releaseType = FIREFOX_RELEASE_TYPES[releaseTypeAbbrev];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
47
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
48 let releaseNumber = parseInt(releaseNumberString);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
49 let [major = 0, minor = 0, patch = 0] = versionString.split('.')
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
50 .map(x => parseInt(x));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
51
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
52 return {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
53 major,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
54 minor,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
55 patch,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
56 releaseType,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
57 releaseNumber,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
58 };
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
59 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
60
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
61 class ObjectStoreDB {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
62 constructor(dbName = 'defaultDatabase', objectStoreName = 'objectStore') {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
63 this.dbName = dbName;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
64 this.objectStoreName = objectStoreName;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
65 this._db = undefined;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
66 this.openingDB = new Promise((resolve, reject) => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
67 let request = indexedDB.open(this.dbName);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
68 request.addEventListener('error', ev => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
69 reject(request.error);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
70 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
71 request.addEventListener('success', ev => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
72 resolve(request.result);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
73 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
74 request.addEventListener('upgradeneeded', ev => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
75 request.result.createObjectStore(this.objectStoreName);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
76 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
77 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
78 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
79
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
80 async _execTransaction(method, ...methodArguments) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
81 if (typeof this._db === 'undefined') {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
82 this._db = await this.openingDB;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
83 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
84 return new Promise((resolve, reject) => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
85 let transaction = this._db.transaction(this.objectStoreName,
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
86 method.startsWith('get') ? 'readonly' : 'readwrite');
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
87 let objectStore = transaction.objectStore(this.objectStoreName);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
88 let request = objectStore[method](...methodArguments);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
89 transaction.addEventListener('complete', ev =>
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
90 method.startsWith('get') ?
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
91 resolve(request.result) :
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
92 resolve());
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
93 transaction.addEventListener('abort', ev =>
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
94 reject(transaction.error));
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
95 transaction.addEventListener('error', ev =>
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
96 reject(transaction.error));
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
97 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
98 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
99
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
100 async get(key) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
101 return key === null || typeof key === 'undefined' ?
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
102 this._execTransaction('getAll') :
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
103 this._execTransaction('get', key);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
104 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
105
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
106 async keys() {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
107 return this._execTransaction('getAllKeys');
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
108 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
109
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
110 async set(key, value) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
111 return this._execTransaction('put', value, key)
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
112 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
113
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
114 async delete(key) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
115 return this._execTransaction('delete', key)
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
116 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
117
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
118 async clear(key) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
119 return this._execTransaction('clear')
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
120 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
121 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
122
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
123 class Tab {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
124 static deserialize(object) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
125 return new Tab(object);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
126 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
127
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
128 constructor({url, title, uuid = generateUuidV4String(), favIcon = null,
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
129 thumbnail = null}) {
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
130 this.uuid = uuid;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
131 this.url = url;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
132 this.title = title;
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
133 this.favIcon = favIcon;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
134 this.thumbnail = thumbnail;
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
135 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
136
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
137 serialize() {
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
138 return Object.assign({}, this, {favIcon: null, thumbnail: null});
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
139 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
140 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
141
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
142 class TabCollection {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
143 static deserialize(object) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
144 object.tabs = Array.from(object.tabs,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
145 ([, tab]) => [tab.uuid, Tab.deserialize(tab)]);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
146 return new TabCollection(object);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
147 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
148
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
149 constructor({tabs, uuid = generateUuidV4String(), date = new Date()}) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
150 this.uuid = uuid;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
151 this.date = new Date(date);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
152 this.tabs = new Map();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
153 // allow any type which allows iteration
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
154 for (let [, tab] of tabs) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
155 this.tabs.set(tab.uuid, tab);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
156 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
157 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
158
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
159 serialize() {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
160 let serializedTabs = [];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
161 for (let [tabUuid, tab] of this.tabs) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
162 serializedTabs.push([tab.uuid, tab.serialize()]);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
163 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
164 return {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
165 uuid: this.uuid,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
166 date: this.date.toJSON(),
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
167 tabs: serializedTabs
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
168 };
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
169 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
170 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
171
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
172 class TabCollectionsStorageProxy {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
173 constructor() {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
174 this.tabCollections = new Map();
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
175 this.objectStoreDB = new ObjectStoreDB('tabCollections');
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
176 this.ports = new Set();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
177 this.browserVersion = undefined;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
178 this.messageQueue = [];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
179 this.isInitialized = false;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
180
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
181 browser.runtime.onConnect.addListener(this.onConnect.bind(this));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
182 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
183
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
184 async init() {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
185 let browserInfo = await browser.runtime.getBrowserInfo();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
186 this.browserVersion = parseFirefoxVersion(browserInfo.version);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
187
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
188 // get all tab collections and deserialize them in a Map
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
189 let storageEntries = Object.entries(await browser.storage.sync.get())
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
190 .filter(([key, value]) => GROUP_KEY_RE.test(key))
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
191 .map(([key, tabCollection]) =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
192 [tabCollection.uuid, TabCollection.deserialize(tabCollection)]);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
193 this.tabCollections = new Map(storageEntries);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
194 console.log('tab collections from storage');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
195 console.table(this.tabCollections);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
196 console.groupEnd();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
197 browser.storage.onChanged.addListener(this.onStorageChanged.bind(this));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
198
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
199 // get favicon and thumbnail data from local database
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
200 let updatingTabData = [];
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
201 for (let tabCollectionUuid of this.tabCollections.keys()) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
202 updatingTabData.push(this.updateTabData(tabCollectionUuid));
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
203 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
204 await Promise.all(updatingTabData);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
205
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
206 // remove stale data from local database
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
207 for (let tabCollectionUuid of await this.objectStoreDB.keys()) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
208 if (!this.tabCollections.has(tabCollectionUuid)) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
209 console.log('removing data for stale tab collection',
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
210 tabCollectionUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
211 this.objectStoreDB.delete(tabCollectionUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
212 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
213 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
214
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
215 this.isInitialized = true;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
216
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
217 while (this.messageQueue.length > 0) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
218 let [message, port] = this.messageQueue.pop();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
219 if (this.ports.has(port)) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
220 this.onMessage(message, port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
221 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
222 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
223 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
224
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
225 async createTabThumbnail(tabId) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
226 let captureUrl = await browser.tabs.captureTab(tabId);
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
227 let thumbnailBlob = await new Promise((resolve, reject) => {
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
228 let image = new Image();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
229 image.addEventListener('load', ev => {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
230 let canvas = document.createElement('canvas');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
231 canvas.width = THUMBNAIL_WIDTH;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
232 canvas.height = THUMBNAIL_HEIGHT;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
233 let dWidth = canvas.width;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
234 let dHeight = dWidth * (image.height / image.width);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
235
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
236 let ctx = canvas.getContext('2d');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
237 ctx.fillStyle = '#fff';
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
238 ctx.fillRect(0, 0, canvas.width, canvas.height);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
239 ctx.drawImage(image, 0, 0, dWidth, dHeight);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
240
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
241 canvas.toBlob(resolve, 'image/jpeg', 0.75);
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
242 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
243 image.addEventListener('error', e => {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
244 reject(e);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
245 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
246 image.src = captureUrl;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
247 });
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
248 return thumbnailBlob;
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
249 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
250
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
251 async createTabCollection(windowId) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
252 let browserTabs = await browser.tabs.query({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
253 windowId,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
254 hidden: false,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
255 pinned:false
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
256 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
257
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
258 // sanity check to prevent saving tabs from incognito windows
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
259 if (browserTabs.length === 0 || browserTabs[0].incognito) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
260 return;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
261 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
262
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
263 // filter out tabs which cannot be restored
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
264 browserTabs = browserTabs.filter(browserTab =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
265 SUPPORTED_PROTOCOLS.includes(new URL(browserTab.url).protocol));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
266 if (browserTabs.length === 0) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
267 return;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
268 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
269
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
270 let tabs = await Promise.all(browserTabs.map(async browserTab => {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
271 // convert favicon data URI to blob
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
272 let favIcon = null;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
273 if (!browserTab.discarded) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
274 try {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
275 let response = await fetch(browserTab.favIconUrl);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
276 favIcon = await response.blob();
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
277 } catch (e) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
278 if (!(e instanceof AbortError)) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
279 throw e;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
280 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
281 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
282 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
283
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
284 let tab = new Tab({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
285 url: browserTab.url,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
286 title: browserTab.title,
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
287 favIcon
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
288 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
289 return [tab.uuid, tab];
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
290 }));
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
291
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
292 // create empty tab which becomes the new active tab
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
293 await browser.tabs.create({active: true});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
294
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
295 // capture tabs, return null for discarded tabs since they can only be
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
296 // captured after they have been restored, e.g. through user
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
297 // interaction, and thus might hang the capture process indefinetly
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
298 let thumbnails = await Promise.all(browserTabs.map(browserTab =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
299 !browserTab.discarded ?
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
300 this.createTabThumbnail(browserTab.id) : null));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
301 for (let [, tab] of tabs) {
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
302 tab.thumbnail = thumbnails.shift();
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
303 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
304
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
305 let tabCollection = new TabCollection({tabs});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
306 console.log('created tab collection:', tabCollection);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
307
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
308 // store tab favicons and thumbnails
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
309 let tabCollectionData = {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
310 uuid: tabCollection.uuid,
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
311 tabs: new Map()
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
312 };
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
313 for (let [uuid, tab] of tabs) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
314 tabCollectionData.tabs.set(uuid, {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
315 favIcon: tab.favIcon,
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
316 thumbnail: tab.thumbnail
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
317 });
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
318 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
319 await this.objectStoreDB.set(tabCollectionData.uuid, tabCollectionData);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
320
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
321 // store tab collection
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
322 console.log('storing tab collection:', tabCollection);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
323 await browser.storage.sync.set({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
324 [`collection:${tabCollection.uuid}`]: tabCollection.serialize()
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
325 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
326
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
327 // remove tabs
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
328 await browser.tabs.remove(browserTabs.map(browserTab => browserTab.id));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
329 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
330
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
331 async removeTab(tabCollectionUuid, tabUuid) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
332 console.log('removing tab %s from collection %s', tabUuid,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
333 tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
334 let tabCollection = this.tabCollections.get(tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
335 // create shallow clone
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
336 let newTabCollection = new TabCollection(tabCollection);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
337 newTabCollection.tabs.delete(tabUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
338 // remove tab collection if there are no more tabs
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
339 if (newTabCollection.tabs.size === 0) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
340 return this.removeTabCollection(tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
341 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
342 await browser.storage.sync.set({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
343 [`collection:${tabCollectionUuid}`]: newTabCollection.serialize()
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
344 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
345 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
346
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
347 async restoreTab(tabCollectionUuid, tabUuid, windowId) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
348 console.log('restoring tab %s from collection %s in window %d', tabUuid,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
349 tabCollectionUuid, windowId);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
350 let tab = this.tabCollections.get(tabCollectionUuid).tabs.get(tabUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
351 let tabProperties = {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
352 active: false,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
353 url: tab.url,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
354 windowId
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
355 };
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
356 if (this.browserVersion.major >= 63) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
357 tabProperties.discarded = true;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
358 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
359 await browser.tabs.create(tabProperties);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
360 await this.removeTab(tabCollectionUuid, tabUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
361 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
362
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
363 async removeTabCollection(tabCollectionUuid) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
364 console.log('removing tab collection %s', tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
365 await browser.storage.sync.remove(`collection:${tabCollectionUuid}`);
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
366 this.objectStoreDB.delete(tabCollectionUuid);
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
367 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
368
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
369 async restoreTabCollection(tabCollectionUuid, windowId) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
370 console.log('restoring tab collection %s in window %s',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
371 tabCollectionUuid, windowId);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
372 let tabProperties = {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
373 active: false,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
374 windowId
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
375 };
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
376 if (this.browserVersion.major >= 63) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
377 tabProperties.discarded = true;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
378 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
379 let creatingTabs =
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
380 Array.from(this.tabCollections.get(tabCollectionUuid).tabs,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
381 ([, tab]) => browser.tabs.create(Object.assign({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
382 url: tab.url
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
383 }, tabProperties)));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
384 await Promise.all(creatingTabs);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
385 await this.removeTabCollection(tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
386 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
387
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
388 async updateTabData(tabCollectionUuid) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
389 let tabCollectionDataObject;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
390 try {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
391 tabCollectionDataObject =
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
392 await this.objectStoreDB.get(tabCollectionUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
393 } catch (e) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
394 console.error(`Failed to get data from database: e.message`);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
395 return;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
396 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
397 if (typeof tabCollectionDataObject === 'undefined') {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
398 // does not exist in database
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
399 console.log('no data stored for tab collection', tabCollectionUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
400 return;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
401 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
402
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
403 console.log(`updating tab collection ${tabCollectionUuid} with data`,
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
404 tabCollectionDataObject);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
405 let tabCollection = this.tabCollections.get(tabCollectionUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
406 for (let [tabUuid, tab] of tabCollection.tabs) {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
407 let tabDataObject = tabCollectionDataObject.tabs.get(tabUuid);
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
408 if (typeof tabDataObject === 'undefined') {
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
409 continue;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
410 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
411 tab.favIcon = tabDataObject.favIcon;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
412 tab.thumbnail = tabDataObject.thumbnail;
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
413 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
414 }
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
415
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
416 async onStorageChanged(changes, areaName) {
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
417 if (areaName !== 'sync') {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
418 return;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
419 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
420
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
421 console.group('sync storage area changed:', changes);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
422 console.table(Object.entries(changes)[0][1])
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
423 console.groupEnd();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
424
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
425 let [key, {oldValue, newValue}] = Object.entries(changes)[0];
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
426 if (!GROUP_KEY_RE.test(key)) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
427 return;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
428 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
429
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
430 let tabCollectionUuid = key.replace('collection:', '');
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
431 if (typeof oldValue === 'undefined') {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
432 // a new collection was created
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
433 let newTabCollection = TabCollection.deserialize(newValue);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
434 this.tabCollections.set(tabCollectionUuid, newTabCollection);
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
435 // try to get tab favicons and thumbnails
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
436 await this.updateTabData(tabCollectionUuid);
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
437
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
438 this.broadcastMessage({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
439 type: 'tabCollectionCreated',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
440 tabCollection: newTabCollection
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
441 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
442 } else if (typeof newValue === 'undefined') {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
443 // a collection has been removed
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
444 this.tabCollections.delete(tabCollectionUuid);
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
445 this.objectStoreDB.delete(tabCollectionUuid);
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
446
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
447 this.broadcastMessage({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
448 type: 'tabCollectionRemoved',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
449 tabCollectionUuid
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
450 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
451 } else {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
452 // a collection has changed
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
453 let newTabCollection = TabCollection.deserialize(newValue);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
454 this.tabCollections.set(tabCollectionUuid, newTabCollection);
1
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
455 // try to get tab favicons and thumbnails
b0827360b8e4 Store favicons and thumbnails in local database
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents: 0
diff changeset
456 await this.updateTabData(tabCollectionUuid);
0
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
457
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
458 this.broadcastMessage({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
459 type: 'tabCollectionChanged',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
460 tabCollection: newTabCollection
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
461 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
462 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
463 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
464
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
465 broadcastMessage(message) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
466 for (let port of this.ports) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
467 port.postMessage(message);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
468 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
469 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
470
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
471 onConnect(port) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
472 console.log('port connected:', port)
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
473 this.ports.add(port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
474 port.onMessage.addListener(this.onMessage.bind(this));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
475 port.onDisconnect.addListener(this.onDisconnect.bind(this));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
476 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
477
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
478 onDisconnect(port) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
479 if (port.error) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
480 console.log(`port connection error: ${port.error}\n`);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
481 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
482 console.log('port disconnected:', port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
483 this.ports.delete(port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
484 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
485
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
486 onMessage(message, port) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
487 if (!this.isInitialized) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
488 console.log('queued message', message, 'from port', port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
489 this.messageQueue.push([message, port]);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
490 return;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
491 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
492
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
493 console.log('received message', message, 'on port', port);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
494 switch (message.type) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
495 case 'getTabCollections':
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
496 port.postMessage({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
497 type: 'tabCollections',
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
498 tabCollections: this.tabCollections
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
499 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
500 break;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
501 case 'removeTab':
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
502 this.removeTab(message.tabCollectionUuid, message.tabUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
503 break;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
504 case 'restoreTab':
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
505 this.restoreTab(message.tabCollectionUuid, message.tabUuid,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
506 message.windowId);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
507 break;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
508 case 'removeTabCollection':
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
509 this.removeTabCollection(message.tabCollectionUuid);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
510 break;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
511 case 'restoreTabCollection':
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
512 this.restoreTabCollection(message.tabCollectionUuid,
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
513 message.windowId);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
514 break;
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
515 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
516 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
517 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
518
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
519 // browser action context menu entry for opening the sidebar
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
520 browser.menus.create({
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
521 contexts: ['browser_action'],
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
522 onclick: (info, tab) => browser.sidebarAction.open(),
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
523 title: browser.i18n.getMessage('showTabsMenuItem')
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
524 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
525
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
526 // disable the browser action for new incognito tabs
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
527 browser.tabs.onCreated.addListener(tab => {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
528 if (tab.incognito) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
529 // this does not work, it seems that the browser action is re-enabled
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
530 // on every update
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
531 browser.browserAction.disable(tab.id);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
532 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
533 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
534
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
535 (async () => {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
536 // disable the browser action for existing incognito tabs
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
537 let tabs = await browser.tabs.query({});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
538 await Promise.all(tabs.filter(tab => tab.incognito)
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
539 .map(tab => browser.browserAction.disable(tab.id)))
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
540
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
541 tabCollectionsProxy = new TabCollectionsStorageProxy();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
542 await tabCollectionsProxy.init();
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
543
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
544 browser.browserAction.onClicked.addListener(async targetTab => {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
545 // prevent browser action from being activated while a collection is
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
546 // being created
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
547 let tabs = await browser.tabs.query({windowId: targetTab.windowId});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
548 await Promise.all(tabs.map(tab =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
549 browser.browserAction.disable(tab.id)));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
550
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
551 try {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
552 await tabCollectionsProxy.createTabCollection(targetTab.windowId);
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
553 } catch (e) {
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
554 tabs = await browser.tabs.query({windowId: targetTab.windowId});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
555 await Promise.all(tabs.map(tab =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
556 browser.browserAction.enable(tab.id)));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
557 throw e
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
558 }
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
559
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
560 tabs = await browser.tabs.query({windowId: targetTab.windowId});
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
561 await Promise.all(tabs.map(tab =>
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
562 browser.browserAction.enable(tab.id)));
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
563 });
d13d59494613 Initial revision
Guido Berhoerster <guido+set-aside@berhoerster.name>
parents:
diff changeset
564 })();