diff --git a/jsconfig.json b/jsconfig.json index 0d9ecd0..225b6b4 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -5,5 +5,5 @@ "@/*": ["src/*"] } }, - "include": ["src", "public/scripts/background.js", "public/scripts/content.js"] + "include": ["src", "src/background.js", "src/content.js"] } \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index 914f2e3..4ee4c06 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -4,15 +4,12 @@ "version": "4.0", "description": "Rellena automáticamente el código 2FA en la Universidad de Sevilla.", "permissions": [ - "activeTab", - "scripting", - "tabs", "storage" ], "background": { - "service_worker": "background.js", + "service_worker": "scripts/background.js", "type": "module", - "scripts": ["background.js"] + "scripts": ["scripts/background.js"] }, "action": { "default_popup": "index.html" @@ -22,9 +19,9 @@ }, "content_scripts": [ { - "matches": ["https://sso.us.es/*"], + "matches": ["*://sso.us.es/*"], "js": ["scripts/content.js"], - "run_at": "document_start" + "run_at": "document_idle" } ], "host_permissions": [ diff --git a/public/scripts/content.js b/public/scripts/content.js deleted file mode 100644 index 0239b3f..0000000 --- a/public/scripts/content.js +++ /dev/null @@ -1,39 +0,0 @@ -(async function() { - // eslint-disable-next-line no-undef - const api = typeof browser !== "undefined" ? browser : chrome; - - const fillCode = (code) => { - const input = document.getElementById("input2factor"); - const button = document.getElementById('btn-login') || document.querySelector("#notification_2factor_button_ok"); - const error = document.querySelector("#otp_authn_wrong_code")?.offsetHeight > 0; - - if (!input || error) return; - - input.value = code; - input.dispatchEvent(new Event('input', { bubbles: true })); - - setTimeout(() => { - if (button) button.click(); - }, 200); - console.log("Autofill"); - }; - - api.runtime.onMessage.addListener((request, sender, sendResponse) => { - if (request.action === "autofill") { - fillCode(request.code); - sendResponse({ status: "ok" }); - } - }); - - const data = await api.storage.local.get(['shasecret']); - if (data.shasecret) { - const input = document.getElementById("input2factor"); - if (input && input.value.length === 0) { - api.runtime.sendMessage({ action: "GENERATE_TOKEN" }, response => { - if (response?.token) { - fillCode(response.token); - } - }); - } - } -})(); \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index c38e2d6..9b50695 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -48,6 +48,8 @@ const App = () => { }).catch(() => {}); } }); + } else { + console.debug("DevEnv"); } } catch (err) { diff --git a/public/scripts/background.js b/src/background.js similarity index 100% rename from public/scripts/background.js rename to src/background.js diff --git a/src/content.js b/src/content.js new file mode 100644 index 0000000..fb24d11 --- /dev/null +++ b/src/content.js @@ -0,0 +1,66 @@ +(async function() { + // eslint-disable-next-line no-undef + const api = typeof browser !== "undefined" ? browser : chrome; + + const fillAndSubmit = (code) => { + const input = document.getElementById("input2factor"); + const button = document.getElementById("notification_2factor_button_ok"); + + const errorMsg = document.querySelector(".ui-state-error"); + const isErrorVisible = errorMsg && errorMsg.style.display !== "none"; + + if (!input || input.value.length > 0 || isErrorVisible) { + return; + } + + console.log("Autofill"); + + input.focus(); + input.value = code; + ['input', 'change', 'keyup', 'keydown'].forEach(evt => { + input.dispatchEvent(new Event(evt, { bubbles: true })); + }); + + setTimeout(() => { + if (button) { + console.log("Clicking 'Aceptar'"); + const clickEvent = new MouseEvent('click', { + view: window, + bubbles: true, + cancelable: true + }); + button.dispatchEvent(clickEvent); + } + }, 400); + }; + + const tryAutofill = async () => { + const data = await api.storage.local.get(['shasecret']); + if (data.shasecret) { + api.runtime.sendMessage({ action: "GENERATE_TOKEN" }, response => { + if (response?.token) { + fillAndSubmit(response.token); + } + }); + } + }; + + const observer = new MutationObserver(() => { + if (document.getElementById("input2factor")) { + tryAutofill(); + } + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); + + api.runtime.onMessage.addListener((request) => { + if (request.action === "autofill") { + fillAndSubmit(request.code); + } + }); + + tryAutofill(); +})(); \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index e077371..c998e98 100644 --- a/vite.config.js +++ b/vite.config.js @@ -6,24 +6,26 @@ export default defineConfig({ plugins: [react()], build: { rollupOptions: { - input: [ - resolve(__dirname, 'index.html'), - ], + input: { + main: resolve(__dirname, 'index.html'), + content: resolve(__dirname, 'src/content.js'), + background: resolve(__dirname, 'src/background.js'), + }, output: { + format: 'es', entryFileNames: (chunkInfo) => { + if (chunkInfo.name === 'content' || chunkInfo.name === 'background') { + return 'scripts/[name].js'; + } return 'assets/[name]-[hash].js'; }, + manualChunks: undefined, }, }, }, - server: { - port: 3000, - }, resolve: { alias: { - '@/': '/src/', + '@': resolve(__dirname, './src'), }, }, - publicDir: 'public', -}); - +}); \ No newline at end of file