| Index: lib/requestBlocker.js | 
| =================================================================== | 
| --- a/lib/requestBlocker.js | 
| +++ b/lib/requestBlocker.js | 
| @@ -180,27 +180,46 @@ | 
| return; | 
|  | 
| let type = resourceTypes.get(details.type) || "OTHER"; | 
| let [docDomain, sitekey, specificOnly] = getDocumentInfo(page, frame, | 
| originUrl); | 
| let [filter, thirdParty] = matchRequest(url, type, docDomain, | 
| sitekey, specificOnly); | 
|  | 
| +  let result; | 
| +  let rewrittenUrl; | 
| + | 
| +  if (filter instanceof BlockingFilter) | 
| +  { | 
| +    if (filter.rewrite) | 
| +    { | 
| +      rewrittenUrl = filter.rewriteUrl(details.url); | 
| +      // If no rewrite happened (error, different origin), we'll | 
| +      // return undefined in order to avoid an "infinite" loop. | 
| +      if (rewrittenUrl != details.url) | 
| +        result = {redirectUrl: rewrittenUrl}; | 
| +    } | 
| +    else | 
| +      result = {cancel: true}; | 
| +  } | 
| + | 
| getRelatedTabIds(details).then(tabIds => | 
| { | 
| logRequest( | 
| tabIds, | 
| -      {url: details.url, type, docDomain, thirdParty, sitekey, specificOnly}, | 
| +      { | 
| +        url: details.url, type, docDomain, thirdParty, | 
| +        sitekey, specificOnly, rewrittenUrl | 
| +      }, | 
| filter | 
| ); | 
| }); | 
|  | 
| -  if (filter instanceof BlockingFilter) | 
| -    return {cancel: true}; | 
| +  return result; | 
| }, {urls: ["<all_urls>"]}, ["blocking"]); | 
|  | 
| port.on("filters.collapse", (message, sender) => | 
| { | 
| let {page, frame} = sender; | 
|  | 
| if (checkWhitelisted(page, frame)) | 
| return false; | 
|  |