如何防止在chrome扩展中接收响应头时下载

时间:2014-03-23 16:39:29

标签: javascript google-chrome google-chrome-extension

由于这个问题Block downloading by Content-Type via Chrome Extension对我不起作用,我正在提出一个新问题。 我使用以下代码来阻止基于内容类型标题的下载:

chrome.webRequest.onHeadersReceived.addListener(function(details) {
    preventDownload = false;
    details.responseHeaders.push({name:"X-Content-Options",value: "no-sniff"});  // Hack 1
    details.statusLine = "HTTP/1.1 302 Moved Temporarily"; // Hack 2
    for (var i = 0; i < details.responseHeaders.length; ++i) 
    {
       if (details.responseHeaders[i].name == 'Content-Type')
        {
            var contentType = details.responseHeaders[i].value;
            if (contentType.indexOf("application/xyz")!=-1)
            {
                preventDownload = true;
            details.responseHeaders[i].value = 'text/plain'; //Hack 3
            }
            else
            {
                return {responseHeaders: details.responseHeaders};
            }
        }

    }
    if(preventDownload)
    {
        if (details.frameId === 0) // Top frame, yay!
        { 
            var scheme = /^https/.test(details.url) ? "https" : "http";
            chrome.tabs.update(details.tabId, {
            url: scheme + "://robwu.nl/204"});
            return;   //return {cancel: true}; should be used but it displays block page
        }
        return {cancel: true};
    }
    return {responseHeaders: details.responseHeaders};
}, {urls: ["<all_urls>"],types: ["main_frame", "sub_frame"]}, ['blocking', 'responseHeaders']);

我成功阻止了下载,但出现了一个错误的Web阻止页面。我需要将用户保留在上一页而不重新加载以显示此错误页面,或者在显示后以某种方式从该服务页面返回。

我在上面的代码中使用过hack但它不会阻止下载。

1 个答案:

答案 0 :(得分:2)

details是一个提供给您的扩展程序的对象,其中包含有关请求的信息。更改其值确实对请求没有任何影响。

Since Chrome 35.0.1911.0 ,您只需重定向到回复状态代码为204的页面,以防止上一页被卸载:

chrome.webRequest.onHeadersReceived.addListener(function(details) {
    // ... your code that checks whether the request should be blocked ...
    //  (omitted for brevity)
    var scheme = /^https/.test(details.url) ? "https" : "http";
    return {redirectUrl: scheme + "://robwu.nl/204" };
}, {
    urls: ["<all_urls>"],
    types: ["main_frame", "sub_frame"]
}, ["responseHeaders", "blocking"]);

如果您使用较旧的Chrome版本(例如34-),则可以使用以下方法:

此外,为防止文件被下载,您需要指示Chrome在标签中呈现该页面。这可以通过修改标题来完成。

  1. Content-Type更改为text/plain(因为它是指示灯格式)。
  2. 添加X-Content-Type-Options: nosniff(以阻止MIME-sniffing)。
  3. 删除Content-Disposition标题(以防止某些类型的下载)。
  4. 使用这些标头,Chrome会尝试在标签中呈现回复。以下是来自其他答案的方法的来源:通过调用chrome.tabs.update指向回复HTTP状态代码204的资源,导航将被取消而不会离开当前页面。

    chrome.webRequest.onHeadersReceived.addListener(function(details) {
        // ... your code that checks whether the request should be blocked ...
        //  (omitted for brevity)
    
        if (details.frameId === 0) { // Top frame, yay!
            // Prevent current page from unloading:
            var scheme = /^https/.test(details.url) ? "https" : "http";
            chrome.tabs.update(details.tabId, {
                url: scheme + "://robwu.nl/204"
            });
    
            // Prevent file from being downloaded via the headers:
            var responseHeaders = details.responseHeaders.filter(function(header) {
                var name = header.name.toLowerCase();
                return name !== 'content-type' &&
                       name !== 'x-content-type-options' &&
                       name !== 'content-disposition';
            }).concat([{
                // Change content type to something non-downloadable
                name: 'Content-Type',
                value: 'text/plain'
            }, {
                // Disable MIME-type sniffing:
                name: 'X-Content-Type-Options',
                value: 'nosniff'
            }]);
            return {
                responseHeaders: responseHeaders
            };
        }
        // else not the top frame...
        return {cancel: true};
    }, {
        urls: ["<all_urls>"],
        types: ["main_frame", "sub_frame"]
    }, ["responseHeaders", "blocking"]);
    

    注意:这是一种hacky方法。您可以将其用于个人用途,但请不要将此类扩展程序上传到Chrome网上应用店。