Compare commits
5 commits
main
...
backup-res
Author | SHA1 | Date | |
---|---|---|---|
![]() |
38af2a385f | ||
![]() |
1f2810e3ec | ||
![]() |
1f01f93674 | ||
![]() |
9476b6acf6 | ||
![]() |
3255d23ddf |
4 changed files with 108 additions and 3 deletions
|
@ -215,6 +215,66 @@ const backgroundLogic = {
|
||||||
return browser.tabs.remove(tabIds);
|
return browser.tabs.remove(tabIds);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async backupIdentitiesState() {
|
||||||
|
const identities = await browser.contextualIdentities.query({});
|
||||||
|
return Promise.all(
|
||||||
|
identities.map(async ({ cookieStoreId, color, icon, name }) => {
|
||||||
|
const userContextId = this.getUserContextIdFromCookieStoreId(cookieStoreId);
|
||||||
|
const sitesByContainer = await assignManager.storageArea.getByContainer(userContextId);
|
||||||
|
const sites = Object.values(sitesByContainer).map(site => {
|
||||||
|
site = Object.assign({}, site); // create a copy
|
||||||
|
delete site.userContextId;
|
||||||
|
return site;
|
||||||
|
});
|
||||||
|
return ({ color, icon, name, sites });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
async restoreIdentitiesState(identities) {
|
||||||
|
const backup = await browser.contextualIdentities.query({});
|
||||||
|
let allSucceed = true;
|
||||||
|
const identitiesPromise = identities.map(async ({ color, icon, name, sites }) => {
|
||||||
|
try {
|
||||||
|
const identity = await browser.contextualIdentities.create({ color, icon, name });
|
||||||
|
try {
|
||||||
|
await identityState.storageArea.get(identity.cookieStoreId);
|
||||||
|
const userContextId = this.getUserContextIdFromCookieStoreId(identity.cookieStoreId);
|
||||||
|
for (const site of sites) {
|
||||||
|
const pageUrl = `http://${site.hostname}`; // protocol doesn't really matter here
|
||||||
|
const data = Object.assign({}, site, { userContextId });
|
||||||
|
delete data.hostname;
|
||||||
|
await assignManager.storageArea.set(pageUrl, data);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// TODO warn the user some associations of sites could not be recovered
|
||||||
|
}
|
||||||
|
return identity;
|
||||||
|
} catch (err) {
|
||||||
|
allSucceed = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const created = await Promise.all(identitiesPromise);
|
||||||
|
if (!allSucceed) { // Importation failed, restore previous state
|
||||||
|
await Promise.all(
|
||||||
|
created.map(async (identityOrNull) => {
|
||||||
|
if (identityOrNull) {
|
||||||
|
await identityState.storageArea.remove(identityOrNull.cookieStoreId);
|
||||||
|
await browser.contextualIdentities.remove(identityOrNull.cookieStoreId);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else { // Importation succeed, remove old identities
|
||||||
|
await Promise.all(
|
||||||
|
backup.map(async (identity) => {
|
||||||
|
await identityState.storageArea.remove(identity.cookieStoreId);
|
||||||
|
await browser.contextualIdentities.remove(identity.cookieStoreId);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async queryIdentitiesState(windowId) {
|
async queryIdentitiesState(windowId) {
|
||||||
const identities = await browser.contextualIdentities.query({});
|
const identities = await browser.contextualIdentities.query({});
|
||||||
const identitiesOutput = {};
|
const identitiesOutput = {};
|
||||||
|
|
|
@ -67,6 +67,12 @@ const messageHandler = {
|
||||||
windowId: m.windowId
|
windowId: m.windowId
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "backupIdentitiesState":
|
||||||
|
response = backgroundLogic.backupIdentitiesState();
|
||||||
|
break;
|
||||||
|
case "restoreIdentitiesState":
|
||||||
|
response = backgroundLogic.restoreIdentitiesState(m.identities);
|
||||||
|
break;
|
||||||
case "queryIdentitiesState":
|
case "queryIdentitiesState":
|
||||||
response = backgroundLogic.queryIdentitiesState(m.message.windowId);
|
response = backgroundLogic.queryIdentitiesState(m.message.windowId);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -23,6 +23,34 @@ async function enableDisableSync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function restoreOptions() {
|
async function restoreOptions() {
|
||||||
|
const backupLink = document.getElementById("containers-save-link");
|
||||||
|
document.getElementById("containers-save-button").addEventListener("click", async () => {
|
||||||
|
const content = JSON.stringify(
|
||||||
|
await browser.runtime.sendMessage({
|
||||||
|
method: "backupIdentitiesState"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
backupLink.href = `data:application/json;base64,${btoa(content)}`;
|
||||||
|
backupLink.download = `containers-backup-${(new Date()).toISOString()}.json`;
|
||||||
|
backupLink.click();
|
||||||
|
}, { capture: true, passive: false });
|
||||||
|
|
||||||
|
const restoreInput = document.getElementById("containers-restore-input");
|
||||||
|
restoreInput.addEventListener("change", () => {
|
||||||
|
if (restoreInput.files.length) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = async () => {
|
||||||
|
const identitiesState = JSON.parse(reader.result);
|
||||||
|
await browser.runtime.sendMessage({
|
||||||
|
method: "restoreIdentitiesState",
|
||||||
|
identities: identitiesState
|
||||||
|
});
|
||||||
|
};
|
||||||
|
reader.readAsText(restoreInput.files.item(0));
|
||||||
|
}
|
||||||
|
restoreInput.value = "";
|
||||||
|
});
|
||||||
|
|
||||||
const hasPermission = await browser.permissions.contains({permissions: ["bookmarks"]});
|
const hasPermission = await browser.permissions.contains({permissions: ["bookmarks"]});
|
||||||
const { syncEnabled } = await browser.storage.local.get("syncEnabled");
|
const { syncEnabled } = await browser.storage.local.get("syncEnabled");
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
@ -17,6 +15,19 @@
|
||||||
Enable Sync
|
Enable Sync
|
||||||
</label>
|
</label>
|
||||||
<p>This setting allows you to sync your containers and site assignments across devices.</p>
|
<p>This setting allows you to sync your containers and site assignments across devices.</p>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Restore</legend>
|
||||||
|
<input id="containers-restore-input" type="file">
|
||||||
|
<p><strong>WARNING !</strong> This operation will erase current configuration with the imported one. All cookies will be discarded.</p>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Save</legend>
|
||||||
|
<a id="containers-save-link" href="#" style="display: none;"></a>
|
||||||
|
<button id="containers-save-button">Backup</button>
|
||||||
|
<p>NOTE : Backup containers names, icons and colors, but <em>not</em> containers' cookies.</p>
|
||||||
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<script src="js/options.js"></script>
|
<script src="js/options.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Reference in a new issue