2022-03-09 14:37:30 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2022-06-07 01:46:24 +03:00
|
|
|
const lazy = {};
|
|
|
|
|
2022-07-21 01:34:21 +03:00
|
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
|
|
Snapshots: "resource:///modules/Snapshots.sys.mjs",
|
|
|
|
SnapshotGroups: "resource:///modules/SnapshotGroups.sys.mjs",
|
2022-03-09 14:37:30 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A builder for snapshot groups based on pinned snapshots.
|
|
|
|
*/
|
2022-07-21 01:34:20 +03:00
|
|
|
export const PinnedGroupBuilder = new (class PinnedGroupBuilder {
|
2022-03-09 14:37:30 +03:00
|
|
|
/**
|
|
|
|
* @type {Map<string, object>}
|
|
|
|
* A map of domains to snapshot group data for groups that are currently in
|
|
|
|
* the database.
|
|
|
|
*/
|
|
|
|
#group = null;
|
|
|
|
|
2022-03-09 14:37:30 +03:00
|
|
|
/**
|
|
|
|
* @type {string}
|
|
|
|
* The name of the builder recorded in the groups.
|
|
|
|
*/
|
|
|
|
name = "pinned";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {boolean}
|
|
|
|
* This will cause the minimum snapshot size check to be skipped.
|
|
|
|
*/
|
|
|
|
skipMinimumSize = true;
|
|
|
|
|
2022-03-09 14:37:30 +03:00
|
|
|
/**
|
|
|
|
* Rebuilds the group from the complete list of snapshots.
|
|
|
|
*
|
|
|
|
* @param {Snapshot[]} snapshots
|
|
|
|
* The current array of snapshots in the database.
|
|
|
|
*/
|
|
|
|
async rebuild(snapshots) {
|
|
|
|
await this.#maybeLoadGroup();
|
|
|
|
|
|
|
|
let urls = snapshots
|
2022-06-07 01:46:24 +03:00
|
|
|
.filter(s => s.userPersisted == lazy.Snapshots.USER_PERSISTED.PINNED)
|
2022-03-09 14:37:30 +03:00
|
|
|
.map(u => u.url);
|
|
|
|
if (
|
|
|
|
urls.length == this.#group.urls.size &&
|
|
|
|
urls.every(u => this.#group.urls.has(u))
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.#group.urls = new Set(urls);
|
|
|
|
await this.#updateGroup(this.#group.urls);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the group based on the added and removed urls.
|
|
|
|
*
|
|
|
|
* @param {object} options
|
|
|
|
* @param {Set<object>} options.addedItems
|
|
|
|
* The added items to handle in this update. A set of objects with
|
|
|
|
* properties of url and userPersisted.
|
|
|
|
* @param {Set<string>} options.removedUrls
|
|
|
|
* The removed urls to handle in this update.
|
|
|
|
*/
|
|
|
|
async update({ addedItems, removedUrls }) {
|
|
|
|
await this.#maybeLoadGroup();
|
|
|
|
|
|
|
|
let changed = false;
|
|
|
|
for (let { url, userPersisted } of addedItems.values()) {
|
2022-06-07 01:46:24 +03:00
|
|
|
if (userPersisted != lazy.Snapshots.USER_PERSISTED.PINNED) {
|
2022-03-09 14:37:30 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.#group.urls.has(url)) {
|
|
|
|
changed = true;
|
|
|
|
this.#group.urls.add(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let url of removedUrls.values()) {
|
|
|
|
if (this.#group.urls.has(url)) {
|
|
|
|
changed = true;
|
|
|
|
this.#group.urls.delete(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!changed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
await this.#updateGroup(this.#group.urls);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the group in the database. This should only be called when there
|
|
|
|
* have been changes made to the list of URLs.
|
|
|
|
*/
|
|
|
|
async #updateGroup() {
|
|
|
|
// Don't create the group if it hasn't got any items.
|
|
|
|
if (this.#group.id == undefined && !this.#group.urls.size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.#group.id == undefined) {
|
2022-06-07 01:46:24 +03:00
|
|
|
let id = await lazy.SnapshotGroups.add(this.#group, this.#group.urls);
|
2022-03-09 14:37:30 +03:00
|
|
|
this.#group.id = id;
|
|
|
|
} else {
|
|
|
|
// For this group, we allow it to continue to exist if the pins have
|
|
|
|
// reduced to zero, SnapshotGroups will filter it out.
|
2022-06-07 01:46:24 +03:00
|
|
|
await lazy.SnapshotGroups.updateUrls(this.#group.id, this.#group.urls);
|
2022-03-09 14:37:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the current domain snapshot groups and all the snapshot urls from
|
|
|
|
* the database, and inserts them into #groups.
|
|
|
|
*/
|
|
|
|
async #maybeLoadGroup() {
|
|
|
|
if (this.#group) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-06-07 01:46:24 +03:00
|
|
|
let groups = await lazy.SnapshotGroups.query({
|
2022-03-09 14:37:30 +03:00
|
|
|
builder: this.name,
|
2022-03-09 14:37:30 +03:00
|
|
|
limit: -1,
|
|
|
|
skipMinimum: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!groups.length) {
|
|
|
|
this.#group = this.#generateEmptyGroup();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (groups.length > 1) {
|
|
|
|
console.error("Should only be one pinned group in the database");
|
|
|
|
}
|
|
|
|
|
|
|
|
this.#group = groups[0];
|
|
|
|
this.#group.urls = new Set(
|
2022-06-07 01:46:24 +03:00
|
|
|
await lazy.SnapshotGroups.getUrls({ id: this.#group.id, hidden: true })
|
2022-03-09 14:37:30 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates an empty pinned group.
|
|
|
|
*
|
|
|
|
* @returns {SnapshotGroup}
|
|
|
|
*/
|
|
|
|
#generateEmptyGroup() {
|
|
|
|
return {
|
|
|
|
builder: "pinned",
|
|
|
|
builderMetadata: {
|
|
|
|
fluentTitle: { id: "snapshot-group-pinned-header" },
|
|
|
|
},
|
|
|
|
urls: new Set(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used for tests to delete the group and reset this object.
|
|
|
|
*/
|
|
|
|
async reset() {
|
2022-06-07 01:46:24 +03:00
|
|
|
await lazy.SnapshotGroups.delete(this.#group.id);
|
2022-03-09 14:37:30 +03:00
|
|
|
this.#group = null;
|
|
|
|
}
|
|
|
|
})();
|