Skip to content

Commit 36b8980

Browse files
committed
Best effort to avoid extra temporary tabs for sidebar detection.
1 parent 8f872a7 commit 36b8980

File tree

2 files changed

+89
-53
lines changed

2 files changed

+89
-53
lines changed

src/bg/RequestGuard.js

Lines changed: 88 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -430,12 +430,76 @@
430430
return (this._tabLess ||= { requests: new Map() });
431431
},
432432

433+
async checkTabLessRequest(request, candidate) {
434+
if (request.tabId !== -1) {
435+
// belts and suspenders
436+
return;
437+
}
438+
// called from an onBeforeSendHeaders listener, with request headers
439+
const tabLess = await this.getTabLess();
440+
if (request.frameId == 0 && request.type == "main_frame") {
441+
if (request.documentUrl) {
442+
// main_frame request from service worker
443+
return;
444+
}
445+
const { url } = request;
446+
if (tabLess.mainUrl == url) {
447+
// same chatbot as before, probably closed & reopened, bailout
448+
return;
449+
}
450+
// filter out requests with wrong headers, e.g. prefetches
451+
for (let h of request.requestHeaders) {
452+
switch(h.name) {
453+
case 'Sec-Fetch-Dest':
454+
if (h.value !== "document") {
455+
return;
456+
}
457+
break;
458+
case 'Sec-Fetch-Mode':
459+
if (h.value !== "navigate") {
460+
return;
461+
}
462+
break;
463+
case 'Sec-Fetch-Site':
464+
if (h.value !== "cross-site") {
465+
return;
466+
}
467+
break;
468+
case 'Sec-Purpose':
469+
// prefetch
470+
return;
471+
}
472+
}
473+
await include("/nscl/service/SidebarUtil.js");
474+
const sidebarWidth = await SidebarUtil.guessSidebarWidth();
475+
if (sidebarWidth < 400) {
476+
// sidebar is closed, bailout
477+
return;
478+
}
479+
tabLess.sidebarWidth = sidebarWidth;
480+
tabLess.requests.clear();
481+
tabLess.mainUrl = url;
482+
} else if (
483+
!tabLess?.requests?.size ||
484+
tabLess.mainUrl !==
485+
(request?.frameAncestors?.length
486+
? request.frameAncestors[
487+
request.frameAncestors?.length - 1]?.url
488+
: request.documentUrl)
489+
) {
490+
// at least one top document needs to be loaded and it must match
491+
return;
492+
}
493+
tabLess.requests.set(candidate.request.key, candidate);
494+
this._session.save();
495+
},
496+
433497
async reportTo(originalRequest, allowed, policyType) {
434-
let { requestId, tabId, frameId, type, url, documentUrl, originUrl } =
498+
const { requestId, tabId, frameId, type, url, documentUrl, originUrl } =
435499
originalRequest;
436-
let pending = pendingRequests.get(requestId); // null if from a CSP report
500+
const pending = pendingRequests.get(requestId); // null if from a CSP report
437501

438-
let request = {
502+
const request = {
439503
key: Policy.requestKey(
440504
url,
441505
type,
@@ -455,18 +519,17 @@
455519
if (
456520
(policyType === "script" || policyType === "fetch") &&
457521
url.startsWith("https://") &&
458-
documentUrl &&
459-
documentUrl.startsWith("https://")
522+
documentUrl?.startsWith("https://")
460523
) {
461524
// service worker request ?
462-
let payload = {
525+
const payload = {
463526
request,
464527
allowed,
465528
policyType,
466529
serviceWorker: Sites.origin(documentUrl),
467530
};
468-
let recipient = { frameId: 0 };
469-
for (let tabId of TabStatus.findTabsByOrigin(payload.serviceWorker)) {
531+
const recipient = { frameId: 0 };
532+
for (const tabId of TabStatus.findTabsByOrigin(payload.serviceWorker)) {
470533
recipient.tabId = tabId;
471534
try {
472535
Messages.send("seen", payload, recipient);
@@ -479,49 +542,15 @@
479542
return;
480543
}
481544
}
482-
if (!(pending && UA.isMozilla)) {
483-
// we don't support tab-less / sidebars outside Firefox
484-
return;
485-
}
486-
487-
// no tab, record as tabLess
488-
const tabLess = await this.getTabLess();
489-
if (frameId == 0 && type == "main_frame") {
490-
if (documentUrl) {
491-
// main_frame request from service worker
492-
return;
493-
}
494-
const { url } = request;
495-
if (tabLess.mainUrl == url) {
496-
// same chatbot as before, probably closed & reopened, bailout
497-
return;
498-
}
499-
await include("/nscl/service/SidebarUtil.js");
500-
const sidebarWidth = await SidebarUtil.guessSidebarWidth();
501-
if (sidebarWidth < 400) {
502-
// sidebar is closed, bailout
503-
return;
504-
}
505-
tabLess.sidebarWidth = sidebarWidth;
506-
tabLess.requests.clear();
507-
tabLess.mainUrl = url;
508-
} else if (
509-
!tabLess?.requests?.size ||
510-
tabLess.mainUrl !==
511-
(originalRequest?.frameAncestors?.length
512-
? originalRequest.frameAncestors[frameAncestors?.length - 1]?.url
513-
: documentUrl)
514-
) {
515-
// at least one top document needs to be loaded and it must match
516-
return;
545+
if ((pending && UA.isMozilla)) {
546+
// we only support tab-less / sidebars in Firefox
547+
pending.tabLessCandidate = {
548+
request,
549+
allowed,
550+
policyType,
551+
tabLess: true,
552+
};
517553
}
518-
tabLess.requests.set(request.key, {
519-
request,
520-
allowed,
521-
policyType,
522-
tabLess: true,
523-
});
524-
this._session.save();
525554
return;
526555
}
527556
if (pending) request.initialUrl = pending.initialUrl;
@@ -795,6 +824,7 @@
795824
return ALLOW;
796825
}
797826

827+
798828
const listeners = {
799829
onBeforeRequest(request) {
800830
try {
@@ -821,12 +851,18 @@
821851
return lanRes;
822852
}
823853
if (lanRes === ABORT) return ABORT;
824-
// redirection loop test
854+
825855
const pending = pendingRequests.get(request.requestId);
856+
// redirection loop test
826857
if (pending?.redirected?.url === request.url) {
827858
return lanRes; // don't go on stripping cookies if we're in a redirection loop
828859
}
829-
const chainNext = r => r === ABORT ? r : TabGuard.onSend(request);
860+
const chainNext = r =>
861+
r === ABORT
862+
? r
863+
: pending.tabLessCandidate
864+
? Content.checkTabLessRequest(request, pending.tabLessCandidate)
865+
: TabGuard.onSend(request);
830866
return lanRes instanceof Promise ? lanRes.then(chainNext) : chainNext(lanRes);
831867
},
832868

src/nscl

0 commit comments

Comments
 (0)