@@ -81,7 +81,7 @@ browser.webRequest.onBeforeRequest.addListener(async (details) => {
81
81
// so we will rewrite any non-web-initiated navigation,
82
82
// including bookmarks, auto-completed URLs and full URLs with "http:" prefix.
83
83
84
- let { tabId, url : requestedUrl } = details ;
84
+ let { tabId, url : requestedUrl , requestedId } = details ;
85
85
86
86
if ( ! prefsReady ) {
87
87
await prefsReadyPromise ;
@@ -146,6 +146,11 @@ browser.webRequest.onBeforeRequest.addListener(async (details) => {
146
146
147
147
if ( tabCreationTimes . has ( tabId ) ) {
148
148
var pendingRedirectInfo = tabPendingRedirectInfos . get ( tabId ) ;
149
+ if ( pendingRedirectInfo && pendingRedirectInfo . redirectedRequestId === requestedId ) {
150
+ // Don't rewrite redirects. Redirects are triggered by a server response, and
151
+ // are certainly not the result of a manually typed URL.
152
+ return ;
153
+ }
149
154
if ( pendingRedirectInfo && pendingRedirectInfo . url === requestedUrl &&
150
155
currentTab && currentTab . status === 'loading' ) {
151
156
// The previous HTTP->HTTPS navigation hasn't started, and the HTTP navigation is
@@ -283,21 +288,54 @@ function isDerivedURL(currentUrl, requestedUrl) {
283
288
//
284
289
// The caller should make sure that tabId refers to a valid tab.
285
290
function registerRedirectInfo ( tabId , requestedUrl ) {
291
+ let redirectInfo = {
292
+ url : requestedUrl ,
293
+ redirectedRequestId : null ,
294
+ unregister,
295
+ } ;
286
296
function unregister ( ) {
287
- browser . webRequest . onHeadersReceived . removeListener ( unregister ) ;
297
+ browser . webRequest . onHeadersReceived . removeListener ( onHeadersReceived ) ;
298
+ browser . webRequest . onResponseStarted . removeListener ( unregister ) ;
288
299
browser . webRequest . onErrorOccurred . removeListener ( unregister ) ;
289
300
tabPendingRedirectInfos . delete ( tabId ) ;
290
301
}
291
302
303
+ function onHeadersReceived ( { requestedId, statusCode} ) {
304
+ if ( statusCode !== 301 && statusCode !== 302 && statusCode !== 303 &&
305
+ statusCode !== 307 && statusCode !== 308 ) {
306
+ unregister ( ) ;
307
+ return ;
308
+ }
309
+ if ( tabPendingRedirectInfos . get ( tabId ) !== redirectInfo ) {
310
+ // unregister() has been invoked between the queued webRequest event and the
311
+ // actual dispatch. This is not expected to happen, but can happen in theory.
312
+ // Exit now to avoid registering and leaking a webRequest event handler.
313
+ return ;
314
+ }
315
+
316
+ // When a request is restarted, the requestedId is preserved.
317
+ redirectInfo . redirectedRequestId = requestedId ;
318
+
319
+ // If the response did not have a valid Location header, the request won't be restarted.
320
+ // Detect the successful response body via webRequest.onResponseStarted.
321
+ // The onHeadersReceived event can fire multiple times throughout a request, but it is safe
322
+ // to call addListener because the event handler won't be registered twice.
323
+ browser . webRequest . onResponseStarted . addListener ( unregister , {
324
+ urls : [ '*://*/*' ] ,
325
+ types : [ 'main_frame' ] ,
326
+ tabId,
327
+ } ) ;
328
+ }
329
+
292
330
unregisterRedirectInfo ( tabId ) ;
293
331
294
332
// A request was successfully received for the main frame, so clear the registered redirection
295
333
// URL. This is not necessarily a response for |requestedUrl|, any response will do.
296
- browser . webRequest . onHeadersReceived . addListener ( unregister , {
334
+ browser . webRequest . onHeadersReceived . addListener ( onHeadersReceived , {
297
335
urls : [ '*://*/*' ] ,
298
336
types : [ 'main_frame' ] ,
299
337
tabId,
300
- } ) ;
338
+ } , [ 'blocking' ] ) ;
301
339
302
340
// The server is not reachable via HTTPs, and the URL can be unregistered because
303
341
// tab.url will show the URL of the attempted navigation:
@@ -309,10 +347,7 @@ function registerRedirectInfo(tabId, requestedUrl) {
309
347
310
348
// Expose the unregister function so that if somehow neither of the above events happen,
311
349
// that the listener is removed when the tab is removed (via tabs.onRemoved):
312
- tabPendingRedirectInfos . set ( tabId , {
313
- url : requestedUrl ,
314
- unregister,
315
- } ) ;
350
+ tabPendingRedirectInfos . set ( tabId , redirectInfo ) ;
316
351
}
317
352
318
353
function unregisterRedirectInfo ( tabId ) {
0 commit comments