Release 1.1.1: remove gcm permission and dead token flow
This commit is contained in:
@@ -1,95 +1,11 @@
|
|||||||
// Let Chrome open the panel when the toolbar icon is clicked
|
// Let Chrome open the panel when the toolbar icon is clicked
|
||||||
// Guard: some Chromium variants may not expose sidePanel
|
// Guard: some Chromium variants may not expose sidePanel
|
||||||
const hasSidePanel = !!chrome.sidePanel?.setOptions;
|
const hasSidePanel = !!chrome.sidePanel?.setOptions;
|
||||||
const GCM_PROJECT_NUMBER = '1088502361802';
|
|
||||||
const EXT_TOKEN_KEY = 'dewemojiExtToken';
|
|
||||||
const GCM_LOCK_KEY = 'dewemojiExtTokenLockTs';
|
|
||||||
const GCM_LAST_ERR_KEY = 'dewemojiExtTokenLastError';
|
|
||||||
const GCM_LAST_ERR_TS_KEY = 'dewemojiExtTokenLastErrorTs';
|
|
||||||
const GCM_LOCK_WINDOW_MS = 60000;
|
|
||||||
let gcmRegisterPromise = null;
|
|
||||||
let gcmInMemoryLockTs = 0;
|
|
||||||
|
|
||||||
async function storeExtensionToken(token) {
|
|
||||||
try { await chrome.storage.local.set({ [EXT_TOKEN_KEY]: token }); } catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getStoredToken() {
|
|
||||||
try {
|
|
||||||
const got = await chrome.storage.local.get([EXT_TOKEN_KEY]);
|
|
||||||
return got[EXT_TOKEN_KEY] || null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerGcmToken() {
|
|
||||||
if (gcmRegisterPromise) return gcmRegisterPromise;
|
|
||||||
if (!chrome?.gcm?.register) return Promise.resolve(null);
|
|
||||||
gcmRegisterPromise = new Promise((resolve) => {
|
|
||||||
(async () => {
|
|
||||||
if (gcmInMemoryLockTs && Date.now() - gcmInMemoryLockTs < GCM_LOCK_WINDOW_MS) {
|
|
||||||
return resolve(null);
|
|
||||||
}
|
|
||||||
// Avoid repeated register attempts within a short window
|
|
||||||
const lock = await chrome.storage.local.get([GCM_LOCK_KEY]);
|
|
||||||
const lastTs = Number(lock[GCM_LOCK_KEY] || 0);
|
|
||||||
if (Date.now() - lastTs < GCM_LOCK_WINDOW_MS) {
|
|
||||||
return resolve(null);
|
|
||||||
}
|
|
||||||
const now = Date.now();
|
|
||||||
gcmInMemoryLockTs = now;
|
|
||||||
await chrome.storage.local.set({ [GCM_LOCK_KEY]: now });
|
|
||||||
})().then(() => {
|
|
||||||
chrome.gcm.register([GCM_PROJECT_NUMBER], async (registrationId) => {
|
|
||||||
if (chrome.runtime.lastError || !registrationId) {
|
|
||||||
const msg = chrome.runtime.lastError?.message || 'no registrationId';
|
|
||||||
try { await chrome.storage.local.set({ [GCM_LAST_ERR_KEY]: msg, [GCM_LAST_ERR_TS_KEY]: Date.now() }); } catch {}
|
|
||||||
if (!/asynchronous operation is pending/i.test(msg)) {
|
|
||||||
console.warn('GCM register failed', msg);
|
|
||||||
}
|
|
||||||
// back off on pending errors
|
|
||||||
if (/asynchronous operation is pending/i.test(msg)) {
|
|
||||||
const now = Date.now();
|
|
||||||
gcmInMemoryLockTs = now;
|
|
||||||
try { await chrome.storage.local.set({ [GCM_LOCK_KEY]: now }); } catch {}
|
|
||||||
}
|
|
||||||
return resolve(null);
|
|
||||||
}
|
|
||||||
try { await chrome.storage.local.remove([GCM_LAST_ERR_KEY, GCM_LAST_ERR_TS_KEY]); } catch {}
|
|
||||||
await storeExtensionToken(registrationId);
|
|
||||||
console.log('GCM token stored', registrationId.slice(0, 8) + '…');
|
|
||||||
resolve(registrationId);
|
|
||||||
});
|
|
||||||
}).catch(() => resolve(null));
|
|
||||||
}).finally(() => {
|
|
||||||
gcmRegisterPromise = null;
|
|
||||||
});
|
|
||||||
return gcmRegisterPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener(() => {
|
chrome.runtime.onInstalled.addListener(() => {
|
||||||
if (hasSidePanel) chrome.sidePanel.setPanelBehavior?.({ openPanelOnActionClick: true });
|
if (hasSidePanel) chrome.sidePanel.setPanelBehavior?.({ openPanelOnActionClick: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Intentionally do NOT auto-register on startup to avoid concurrent GCM calls.
|
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
|
|
||||||
if (msg?.type !== 'dewemoji_get_ext_token') return;
|
|
||||||
(async () => {
|
|
||||||
const force = !!msg.force;
|
|
||||||
let token = await getStoredToken();
|
|
||||||
if (!token || force) {
|
|
||||||
await registerGcmToken();
|
|
||||||
// best-effort wait for storage to be populated
|
|
||||||
await new Promise(r => setTimeout(r, 300));
|
|
||||||
token = await getStoredToken();
|
|
||||||
}
|
|
||||||
sendResponse({ ok: !!token, token });
|
|
||||||
})();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If you still want to ensure the correct path on click, setOptions ONLY:
|
// If you still want to ensure the correct path on click, setOptions ONLY:
|
||||||
chrome.action.onClicked.addListener(async () => {
|
chrome.action.onClicked.addListener(async () => {
|
||||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "Dewemoji - Emojis Made Effortless",
|
"name": "Dewemoji - Emojis Made Effortless",
|
||||||
"description": "Find and copy emojis instantly. Connect your account to use private keywords across web and extension.",
|
"description": "Find and copy emojis instantly. Connect your account to use private keywords across web and extension.",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"offline_enabled": false,
|
"offline_enabled": false,
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
"scripting",
|
"scripting",
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"sidePanel",
|
"sidePanel"
|
||||||
"gcm"
|
|
||||||
],
|
],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
"<all_urls>",
|
"<all_urls>",
|
||||||
|
|||||||
@@ -136,6 +136,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
||||||
<script src="panel.js?ver=1.1.0"></script>
|
<script src="panel.js?ver=1.1.1"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
41
panel.js
41
panel.js
@@ -160,47 +160,6 @@ function categoryComparator(a, b) {
|
|||||||
return a.localeCompare(b, undefined, { sensitivity: "base" }); // both not preferred → A–Z
|
return a.localeCompare(b, undefined, { sensitivity: "base" }); // both not preferred → A–Z
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Extension verification token (GCM registration) ===
|
|
||||||
const EXT_TOKEN_KEY = 'dewemojiExtToken';
|
|
||||||
const EXT_TOKEN_COOLDOWN_MS = 60000;
|
|
||||||
let extTokenPromise = null;
|
|
||||||
let extTokenLastAttempt = 0;
|
|
||||||
|
|
||||||
async function getExtensionToken(force=false) {
|
|
||||||
if (extTokenPromise) return extTokenPromise;
|
|
||||||
extTokenPromise = (async () => {
|
|
||||||
try {
|
|
||||||
const got = await chrome.storage.local.get([EXT_TOKEN_KEY]);
|
|
||||||
if (got[EXT_TOKEN_KEY] && !force) return got[EXT_TOKEN_KEY];
|
|
||||||
if (!force && extTokenLastAttempt && Date.now() - extTokenLastAttempt < EXT_TOKEN_COOLDOWN_MS) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
extTokenLastAttempt = Date.now();
|
|
||||||
const res = await chrome.runtime.sendMessage({ type: 'dewemoji_get_ext_token', force });
|
|
||||||
if (res?.token) {
|
|
||||||
await chrome.storage.local.set({ [EXT_TOKEN_KEY]: res.token });
|
|
||||||
return res.token;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Token retrieval failed:', err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})().finally(() => {
|
|
||||||
extTokenPromise = null;
|
|
||||||
});
|
|
||||||
return extTokenPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getExtensionTokenCached() {
|
|
||||||
try {
|
|
||||||
const got = await chrome.storage.local.get([EXT_TOKEN_KEY]);
|
|
||||||
return got[EXT_TOKEN_KEY] || null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadCategories() {
|
async function loadCategories() {
|
||||||
// Try live endpoint; fall back silently to local list (no subs)
|
// Try live endpoint; fall back silently to local list (no subs)
|
||||||
let ok = false;
|
let ok = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user