From ae32f31eb4c4d27b2e9230a6fa62f0a64d967b3a Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Sun, 30 Mar 2014 00:25:37 +0100 Subject: [PATCH] Use redirectUrl at onHeadersReceived if available. http://crbug.com/280464 has been resolved, so we can now use redirectUrl at onHeadersReceived. For backwards-compatibility, the code for the original method has not been removed, and a feature detection script was added that detects whether the desired feature is available. --- extensions/chromium/feature-detect.js | 67 ++++++++++++++++++++++++++- extensions/chromium/pdfHandler.js | 7 ++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/extensions/chromium/feature-detect.js b/extensions/chromium/feature-detect.js index 013193d83..121672c0a 100644 --- a/extensions/chromium/feature-detect.js +++ b/extensions/chromium/feature-detect.js @@ -23,6 +23,8 @@ var Features = { featureDetectLastUA: '', // Whether ftp: in XMLHttpRequest is allowed extensionSupportsFTP: false, + // Whether redirectUrl at onHeadersReceived is supported. + webRequestRedirectUrl: false, }; chrome.storage.local.get(Features, function(features) { @@ -31,13 +33,34 @@ chrome.storage.local.get(Features, function(features) { // Browser not upgraded, so the features did probably not change. return; } + var inconclusiveTestCount = 0; if (!features.extensionSupportsFTP) { features.extensionSupportsFTP = featureTestFTP(); } - Features.featureDetectLastUA = navigator.userAgent; - chrome.storage.local.set(Features); + if (!features.webRequestRedirectUrl) { + ++inconclusiveTestCount; + // Relatively expensive (and asynchronous) test: + featureTestRedirectOnHeadersReceived(function(result) { + // result = 'yes', 'no' or 'maybe'. + if (result !== 'maybe') { + --inconclusiveTestCount; + } + features.webRequestRedirectUrl = result === 'yes'; + checkTestCompletion(); + }); + } + + checkTestCompletion(); + + function checkTestCompletion() { + // Only stamp the feature detection results when all tests have finished. + if (inconclusiveTestCount === 0) { + Features.featureDetectLastUA = navigator.userAgent; + } + chrome.storage.local.set(Features); + } }); // Tests whether the extension can perform a FTP request. @@ -56,3 +79,43 @@ function featureTestFTP() { return false; } } + +// Tests whether redirectUrl at the onHeadersReceived stage is functional. +// Feature is supported since Chromium 35.0.1911.0 (r259546). +function featureTestRedirectOnHeadersReceived(callback) { + // The following URL is really going to be accessed via the network. + // It is the only way to feature-detect this feature, because the + // onHeadersReceived event is only triggered for http(s) requests. + var url = 'http://example.com/?feature-detect-' + chrome.runtime.id; + function onHeadersReceived(details) { + // If supported, the request is redirected. + // If not supported, the return value is ignored. + return { + redirectUrl: chrome.runtime.getURL('/manifest.json') + }; + } + chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, { + types: ['xmlhttprequest'], + urls: [url] + }, ['blocking']); + + var x = new XMLHttpRequest(); + x.open('get', url); + x.onloadend = function() { + chrome.webRequest.onHeadersReceived.removeListener(onHeadersReceived); + if (!x.responseText) { + // Network error? Anyway, can't tell with certainty whether the feature + // is supported. + callback('maybe'); + } else if (/^\s*\{/.test(x.responseText)) { + // If the response starts with "{", assume that the redirection to the + // manifest file succeeded, so the feature is supported. + callback('yes'); + } else { + // Did not get the content of manifest.json, so the redirect seems not to + // be followed. The feature is not supported. + callback('no'); + } + }; + x.send(); +} diff --git a/extensions/chromium/pdfHandler.js b/extensions/chromium/pdfHandler.js index b33b5786d..5f5465b57 100644 --- a/extensions/chromium/pdfHandler.js +++ b/extensions/chromium/pdfHandler.js @@ -114,8 +114,11 @@ chrome.webRequest.onHeadersReceived.addListener( var viewerUrl = getViewerURL(details.url); // Replace frame with viewer - // TODO: When http://crbug.com/280464 is fixed, use - // return { redirectUrl: viewerUrl }; + if (Features.webRequestRedirectUrl) { + return { redirectUrl: viewerUrl }; + } + // Aww.. redirectUrl is not yet supported, so we have to use a different + // method as fallback (Chromium <35). if (details.frameId === 0) { // Main frame. Just replace the tab and be done!