no message

This commit is contained in:
yinjun.chen1
2026-09-16 15:47:36 +08:00
parent 0f2ceda59e
commit 49c809f513
3 changed files with 71 additions and 14 deletions
+4
View File
@@ -34,6 +34,7 @@ async function migrateLegacyVault() {
// 无 vault 明文模式:确保 session 有 environments(从 local 加载或创建预设) // 无 vault 明文模式:确保 session 有 environments(从 local 加载或创建预设)
async function ensurePlainEnvironments() { async function ensurePlainEnvironments() {
if (await CryptoStore.hasVault()) return; // 加密模式不处理
const data = await chrome.storage.local.get("environments"); const data = await chrome.storage.local.get("environments");
let envs = data.environments; let envs = data.environments;
if (!Array.isArray(envs) || envs.length === 0) { if (!Array.isArray(envs) || envs.length === 0) {
@@ -54,6 +55,9 @@ async function ensurePlainEnvironments() {
} }
} }
// SW 启动即初始化明文环境到 session,供 content script 自动登录读取
ensurePlainEnvironments().catch((err) => console.warn("[AutoLogin] 启动初始化失败:", err));
function resetAutoLockTimer() { function resetAutoLockTimer() {
if (autoLockTimer) clearTimeout(autoLockTimer); if (autoLockTimer) clearTimeout(autoLockTimer);
+64 -14
View File
@@ -71,11 +71,28 @@ function setNativeValue(el, value) {
el.dispatchEvent(new Event("change", { bubbles: true })); el.dispatchEvent(new Event("change", { bubbles: true }));
} }
function deepQuerySelectorAll(selector, root) {
const result = [];
const stack = [root || document];
while (stack.length) {
const r = stack.pop();
result.push(...r.querySelectorAll(selector));
for (const el of r.querySelectorAll("*")) {
if (el.shadowRoot) stack.push(el.shadowRoot);
}
}
return result;
}
function deepQuerySelector(selector, root) {
return deepQuerySelectorAll(selector, root)[0] || null;
}
function resolveElement(value, multiple) { function resolveElement(value, multiple) {
if (!value) return null; if (!value) return null;
const trimmed = value.trim(); const trimmed = value.trim();
if (!trimmed.startsWith("<")) { if (!trimmed.startsWith("<")) {
return multiple ? Array.from(document.querySelectorAll(trimmed)) : document.querySelector(trimmed); return multiple ? deepQuerySelectorAll(trimmed) : deepQuerySelector(trimmed);
} }
const doc = new DOMParser().parseFromString(trimmed, "text/html"); const doc = new DOMParser().parseFromString(trimmed, "text/html");
const el = doc.body.firstElementChild; const el = doc.body.firstElementChild;
@@ -94,10 +111,10 @@ function resolveElement(value, multiple) {
candidates.push(tag); candidates.push(tag);
for (const sel of candidates) { for (const sel of candidates) {
if (multiple) { if (multiple) {
const els = Array.from(document.querySelectorAll(sel)); const els = deepQuerySelectorAll(sel);
if (els.length) return els; if (els.length) return els;
} else { } else {
const found = document.querySelector(sel); const found = deepQuerySelector(sel);
if (found) return found; if (found) return found;
} }
} }
@@ -123,7 +140,7 @@ function findUsernameField(config) {
]; ];
for (const sel of selectors) { for (const sel of selectors) {
const inputs = searchScope.querySelectorAll(sel); const inputs = deepQuerySelectorAll(sel, searchScope);
for (const input of inputs) { for (const input of inputs) {
if (input.offsetParent !== null || input.offsetWidth > 0) { if (input.offsetParent !== null || input.offsetWidth > 0) {
const name = (input.name || "").toLowerCase(); const name = (input.name || "").toLowerCase();
@@ -148,8 +165,9 @@ function findUsernameField(config) {
} }
} }
const allInputs = searchScope.querySelectorAll( const allInputs = deepQuerySelectorAll(
"input[type='text'], input[type='email'], input:not([type='password']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='checkbox']):not([type='radio'])" "input[type='text'], input[type='email'], input:not([type='password']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='checkbox']):not([type='radio'])",
searchScope
); );
for (const input of allInputs) { for (const input of allInputs) {
if (input.offsetParent !== null || input.offsetWidth > 0) { if (input.offsetParent !== null || input.offsetWidth > 0) {
@@ -166,14 +184,26 @@ function findPasswordField(config) {
if (el) return el; if (el) return el;
} }
const passwordInputs = document.querySelectorAll("input[type='password']"); const passwordInputs = deepQuerySelectorAll("input[type='password']");
for (const input of passwordInputs) { for (const input of passwordInputs) {
if (input.offsetParent !== null || input.offsetWidth > 0) { if (input.offsetParent !== null || input.offsetWidth > 0) {
return input; return input;
} }
} }
if (passwordInputs.length > 0) return passwordInputs[0];
return passwordInputs.length > 0 ? passwordInputs[0] : null; const allInputs = deepQuerySelectorAll("input");
for (const input of allInputs) {
if (input.type === "password") return input;
const sig = (
(input.name || "") + " " + (input.id || "") + " " +
(input.placeholder || "") + " " + (input.getAttribute("autocomplete") || "")
).toLowerCase();
if (sig.includes("password") || sig.includes("passwd") || sig.includes("pwd")) {
if (input.offsetParent !== null || input.offsetWidth > 0) return input;
}
}
return null;
} }
function findSubmitButton(config, passwordField) { function findSubmitButton(config, passwordField) {
@@ -205,7 +235,7 @@ function findSubmitButton(config, passwordField) {
]; ];
for (const sel of submitSelectors) { for (const sel of submitSelectors) {
const btns = searchScope.querySelectorAll(sel); const btns = deepQuerySelectorAll(sel, searchScope);
for (const btn of btns) { for (const btn of btns) {
if (btn.offsetParent !== null || btn.offsetWidth > 0) { if (btn.offsetParent !== null || btn.offsetWidth > 0) {
const text = (btn.textContent || btn.value || "").toLowerCase().trim(); const text = (btn.textContent || btn.value || "").toLowerCase().trim();
@@ -222,13 +252,13 @@ function findSubmitButton(config, passwordField) {
} }
for (const sel of submitSelectors) { for (const sel of submitSelectors) {
const btn = searchScope.querySelector(sel); const btn = deepQuerySelector(sel, searchScope);
if (btn && (btn.offsetParent !== null || btn.offsetWidth > 0)) { if (btn && (btn.offsetParent !== null || btn.offsetWidth > 0)) {
return btn; return btn;
} }
} }
const allButtons = searchScope.querySelectorAll("button, input[type='button'], a[role='button']"); const allButtons = deepQuerySelectorAll("button, input[type='button'], a[role='button']", searchScope);
for (const btn of allButtons) { for (const btn of allButtons) {
if (btn.offsetParent !== null || btn.offsetWidth > 0) { if (btn.offsetParent !== null || btn.offsetWidth > 0) {
const text = (btn.textContent || btn.value || "").toLowerCase().trim(); const text = (btn.textContent || btn.value || "").toLowerCase().trim();
@@ -390,7 +420,14 @@ async function loadAllConfigs() {
} }
async function autoFillOnLoad() { async function autoFillOnLoad() {
const allConfigs = await loadAllConfigs(); let allConfigs = await loadAllConfigs();
if (allConfigs.length === 0) {
// session 可能为空(明文模式 SW 重启后未初始化),触发 background 加载后重试
try {
await chrome.runtime.sendMessage({ action: "getVaultStatus" });
allConfigs = await loadAllConfigs();
} catch {}
}
if (allConfigs.length === 0) return; if (allConfigs.length === 0) return;
// 每个配置有独立开关 enabled // 每个配置有独立开关 enabled
@@ -556,10 +593,23 @@ function showEnvPicker(configs) {
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "manualFill" && message.config) { if (message.action === "manualFill" && message.config) {
// 手动触发填充,重置失败计数
resetDomainAttempts(message.config.envId, message.config.domain); resetDomainAttempts(message.config.envId, message.config.domain);
const filled = fillForm(message.config, true); const filled = fillForm(message.config, true);
sendResponse({ success: filled }); if (filled) {
sendResponse({ success: true });
} else {
const inputs = deepQuerySelectorAll("input");
const pwdInputs = deepQuerySelectorAll("input[type='password']");
sendResponse({
success: false,
diag: {
total: inputs.length,
pwd: pwdInputs.length,
forms: document.querySelectorAll("form").length,
sample: inputs.slice(0, 10).map((i) => `type=${i.type || "?"}|name=${(i.name || i.id || i.placeholder || "?").slice(0, 20)}`),
},
});
}
} else if (message.action === "manualFillMulti" && Array.isArray(message.configs)) { } else if (message.action === "manualFillMulti" && Array.isArray(message.configs)) {
showEnvPicker(message.configs); showEnvPicker(message.configs);
sendResponse({ success: true }); sendResponse({ success: true });
+3
View File
@@ -1006,6 +1006,9 @@ document.addEventListener("DOMContentLoaded", () => {
}); });
if (resp && resp.success) { if (resp && resp.success) {
showToast(t("toastFilled")); showToast(t("toastFilled"));
} else if (resp && resp.diag) {
const d = resp.diag;
showToast(`input=${d.total} pwd=${d.pwd} form=${d.forms} | ${d.sample.join(", ")}`);
} else { } else {
showToast(t("toastFilledNoForm")); showToast(t("toastFilledNoForm"));
} }