Improve locked vault browser workflow

This commit is contained in:
Joe Julian
2026-04-23 20:37:49 -07:00
parent 4afbc3c933
commit d60a8d2fbf
5 changed files with 69 additions and 4 deletions
+14 -3
View File
@@ -292,6 +292,16 @@ function approvalHintForState(state) {
return state.pendingMessage || "Approve or deny the fill request in KeePassGO.";
}
function shouldContinueWatchingState(state) {
if (!state?.pageHasLoginForm) {
return false;
}
if (state?.pendingFill) {
return true;
}
return Boolean(state?.status?.locked);
}
function schedulePendingPoll(tabId, pageUrl) {
if (!Number.isInteger(tabId)) {
return;
@@ -492,7 +502,7 @@ async function refreshPageState(tabId, pageUrl, options = {}) {
state.matches = [];
state.updatedAt = Date.now();
const saved = await setPageState(tabId, state);
if (saved.pendingFill) {
if (shouldContinueWatchingState(saved)) {
schedulePendingPoll(tabId, resolvedURL);
} else {
clearPendingPoll(tabId);
@@ -502,7 +512,7 @@ async function refreshPageState(tabId, pageUrl, options = {}) {
if (shouldReuseMatches(state, force)) {
const saved = await setPageState(tabId, state);
if (saved.pendingFill) {
if (shouldContinueWatchingState(saved)) {
schedulePendingPoll(tabId, resolvedURL);
} else {
clearPendingPoll(tabId);
@@ -529,7 +539,7 @@ async function refreshPageState(tabId, pageUrl, options = {}) {
updatedAt: Date.now()
};
const saved = await setPageState(tabId, state);
if (saved.pendingFill) {
if (shouldContinueWatchingState(saved)) {
schedulePendingPoll(tabId, resolvedURL);
} else {
clearPendingPoll(tabId);
@@ -657,6 +667,7 @@ const backgroundTestExports = {
normalizePageState,
actionPresentationForState,
shouldReuseMatches,
shouldContinueWatchingState,
tokenPendingApprovalCount,
defaultSettings
};
+18
View File
@@ -49,6 +49,24 @@ test("tokenPendingApprovalCount reads token-scoped approval state", () => {
assert.equal(background.tokenPendingApprovalCount({}), 0);
});
test("shouldContinueWatchingState keeps polling locked login pages", () => {
assert.equal(background.shouldContinueWatchingState({
pageHasLoginForm: true,
pendingFill: false,
status: { locked: true }
}), true);
assert.equal(background.shouldContinueWatchingState({
pageHasLoginForm: true,
pendingFill: true,
status: { locked: false }
}), true);
assert.equal(background.shouldContinueWatchingState({
pageHasLoginForm: true,
pendingFill: false,
status: { locked: false }
}), false);
});
test("default settings include a blank bearer token that can be overridden by harness patching", () => {
assert.equal(background.defaultSettings.bearerToken, "");
});
+5 -1
View File
@@ -429,6 +429,7 @@ function shouldShowInlineOverlay(state, hasTarget, suppressed, idleHidden) {
state?.pageHasLoginForm &&
(
state?.pendingFill ||
(state?.configured && state?.success && state?.status?.locked) ||
(state?.configured && state?.success && !state?.status?.locked && Array.isArray(state?.matches) && state.matches.length > 0)
)
);
@@ -727,10 +728,13 @@ if (isNodeTestEnv) {
ensureRootMounted();
dock.style.display = "block";
trigger.dataset.tone = pageState.pendingFill ? "warning" : (pageState.error ? "error" : "ready");
trigger.dataset.tone = pageState.pendingFill || pageState.status?.locked ? "warning" : (pageState.error ? "error" : "ready");
if (pageState.pendingFill) {
meta.textContent = "Approval needed in KeePassGO";
panelCopy.textContent = pageState.pendingMessage || "Approve or deny the fill request in KeePassGO.";
} else if (pageState.status?.locked) {
meta.textContent = "Unlock KeePassGO";
panelCopy.textContent = "Unlock KeePassGO to turn this field back into live login suggestions.";
} else {
const count = Array.isArray(pageState.matches) ? pageState.matches.length : 0;
meta.textContent = count === 1 ? "1 login ready" : `${count} logins ready`;
+13
View File
@@ -94,6 +94,19 @@ test("shouldShowInlineOverlay hides the page overlay after it is suppressed", ()
assert.equal(content.shouldShowInlineOverlay(state, true, true, false), false);
});
test("shouldShowInlineOverlay stays visible for locked login pages", () => {
const state = {
pageHasLoginForm: true,
configured: true,
success: true,
status: { locked: true },
matches: [],
pendingFill: false
};
assert.equal(content.shouldShowInlineOverlay(state, true, false, false), true);
});
test("shouldShowInlineOverlay hides the page overlay after idle expiry", () => {
const state = {
pageHasLoginForm: true,