From 31b8c535618d52fcdfb936d7947fa3ac2cafa037 Mon Sep 17 00:00:00 2001 From: Shmuel Melamud Date: Tue, 24 Mar 2020 23:18:48 +0200 Subject: [PATCH] Commands for caching names. --- src/background.js | 4 ++++ src/data.js | 10 ++++++++-- src/names.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/names.js diff --git a/src/background.js b/src/background.js index d65bb8e..0b44841 100644 --- a/src/background.js +++ b/src/background.js @@ -2,6 +2,7 @@ import browser from 'webextension-polyfill'; import { deleteData, isStorageV1, loadData, migrateStorageToV2, storeData, switchData } from "./data"; import { addTab } from "./tabs"; +import { storeName } from "./names"; const MAX_MATCHING_URLS_SIZE = 100; let matchingUrls = new Map(); @@ -128,6 +129,9 @@ browser.runtime.onMessage.addListener( case "switchData": switchData(sender.tab.id, message.payload); break; + case "storeName": + storeName(sender.tab.id, message.payload); + break; } } ); diff --git a/src/data.js b/src/data.js index bf8ee05..104312a 100644 --- a/src/data.js +++ b/src/data.js @@ -3,6 +3,7 @@ import AsyncLock from 'async-lock'; import ObjectPath from 'object-path'; import { broadcastMessage, getTabClientUrl } from "./tabs"; +import { clearNames, getNames } from "./names"; const DEFAULT_CLIENT_URL = "https://client.moera.org/releases/latest"; @@ -32,7 +33,7 @@ export async function migrateStorageToV2() { await browser.storage.local.set(data); } -function loadedData(homeRoot, clientData, roots) { +function loadedData(homeRoot, clientData, roots, names) { let data = {}; if (homeRoot) { data = {...clientData}; @@ -41,6 +42,9 @@ function loadedData(homeRoot, clientData, roots) { if (roots != null) { data = {...data, roots} } + if (names != null) { + data = {...data, names} + } return { source: "moera", action: "loadedData", @@ -76,7 +80,7 @@ export async function loadData(tabId) { const dataKey = `clientData;${clientUrl};${homeRoot}`; const {[dataKey]: clientData} = await browser.storage.local.get(dataKey); ObjectPath.set(clientData, "home.nodeName", getRootName(roots, homeRoot)); - return loadedData(homeRoot, clientData, roots); + return loadedData(homeRoot, clientData, roots, await getNames(clientUrl)); } export async function storeData(tabId, data) { @@ -138,6 +142,7 @@ export async function deleteData(tabId, location) { let nodeName; if (location === homeRoot) { + await clearNames(clientUrl); if (roots.length === 0) { await browser.storage.local.remove(rootKey); return loadedData(homeRoot, {}, roots); @@ -173,6 +178,7 @@ export async function switchData(tabId, location) { return loadedData(); } await browser.storage.local.set({[rootKey]: location}); + await clearNames(clientUrl); const dataKey = `clientData;${clientUrl};${location}`; const {[dataKey]: clientData} = await browser.storage.local.get(dataKey); diff --git a/src/names.js b/src/names.js new file mode 100644 index 0000000..f0c758c --- /dev/null +++ b/src/names.js @@ -0,0 +1,49 @@ +import browser from 'webextension-polyfill'; +import AsyncLock from 'async-lock'; + +import { broadcastMessage, getTabClientUrl } from "./tabs"; + +const NAME_TTL = 6 * 60 * 60; // seconds +const MAX_NAMES_SIZE = 500; +const namesLock = new AsyncLock(); + +function storedName(details) { + return { + source: "moera", + action: "storedName", + payload: details + }; +} + +export async function getNames(clientUrl) { + const namesKey = `names;${clientUrl}`; + const {[namesKey]: names} = await browser.storage.local.get(namesKey); + return names != null ? names : []; +} + +export async function clearNames(clientUrl) { + await namesLock.acquire("names", async () => { + const namesKey = `names;${clientUrl}`; + await browser.storage.local.remove(namesKey); + }); +} + +export async function storeName(tabId, details) { + const clientUrl = await getTabClientUrl(tabId); + await namesLock.acquire("names", async () => { + const namesKey = `names;${clientUrl}`; + let {[namesKey]: names} = await browser.storage.local.get(namesKey); + if (names == null) { + names = []; + } + const now = Math.round(Date.now() / 1000); + names = names.filter(info => info.name !== details.name && (now - info.updated) <= NAME_TTL); + details.updated = now; + names.push(details); + if (names.length > MAX_NAMES_SIZE) { + names.splice(0, names.length - MAX_NAMES_SIZE); + } + await browser.storage.local.set({[namesKey]: names}); + }); + broadcastMessage(storedName(details), clientUrl); +}