diff --git a/backend/extension-src/manifest.json b/backend/extension-src/manifest.json index 183a46d..6cdbc42 100644 --- a/backend/extension-src/manifest.json +++ b/backend/extension-src/manifest.json @@ -11,6 +11,8 @@ "https://login.newbook.cloud/*" ], + "optional_host_permissions": ["http://*/*", "https://*/*"], + "background": { "service_worker": "background.js" }, diff --git a/backend/extension-src/options/options.js b/backend/extension-src/options/options.js index 6a1d5dc..1336e62 100644 --- a/backend/extension-src/options/options.js +++ b/backend/extension-src/options/options.js @@ -9,9 +9,27 @@ async function load() { // not the popup) so the value can be corrected without regenerating the key. } +// tablet-checkin's own base URL isn't known in advance (dev today, a +// different production URL later), so it can't be pre-declared in the +// manifest's host_permissions — Chrome would need republishing/reloading +// every time the URL changed. Requesting it dynamically here instead (needs +// a user gesture, which this Save click provides) means the extension's own +// fetches bypass CORS entirely for that origin once granted, rather than +// depending on the server sending back Access-Control-Allow-Origin for an +// extension origin ID that isn't fixed/predictable per install anyway. async function save() { const baseUrl = baseUrlInput.value.trim().replace(/\/$/, ''); const apiKey = apiKeyInput.value.trim(); + + if (baseUrl) { + const granted = await chrome.permissions.request({ origins: [`${baseUrl}/*`] }); + if (!granted) { + statusEl.textContent = 'Not saved — permission for that URL was denied. This extension needs it to talk to tablet-checkin.'; + statusEl.style.color = '#dc2626'; + return; + } + } + await chrome.storage.local.set({ baseUrl, apiKey }); statusEl.textContent = 'Saved.'; statusEl.style.color = '#16a34a';