Reputation: 9445
Since this question Block downloading by Content-Type via Chrome Extension didn't work for me, I am opening a new question. I use the following code to block download based on content-type header:
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']);
I succeed in preventing the download, but an error Web block page appears. I need to keep user on previous page without reloading to displaying this error page OR somehow move back from this service page after it displayed.
I have used a hack in above code but it does not block the download.
Upvotes: 1
Views: 3983
Reputation: 348972
details
is an object supplied to your extension with information about the request. Changing its value does indeed not have any effect on the request.
Since Chrome 35.0.1911.0, you can simply redirect to a page that replies with status code 204 to prevent the previous page from unloading:
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"]);
If you're using an older Chrome version (e.g 34-), then the following method can be used instead:
Further, to prevent the file from being downloaded, you need to instruct Chrome to render the page in the tab. This can be done by modifying the headers.
Content-Type
to text/plain
(because it is a light format).X-Content-Type-Options: nosniff
(to prevent MIME-sniffing).Content-Disposition
header (to prevent some kinds of downloads).With these headers, Chrome will try to render the response in the tab. Here's where the method from the other answer comes in: By calling chrome.tabs.update
that points to a resource that replies with HTTP status code 204, the navigation is cancelled without leaving the current page.
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"]);
Note: This is a hacky method. Feel free to use it for personal use, but please do not upload such kinds of extensions to the Chrome Web Store.
Upvotes: 3