Skip to content

Commit

Permalink
Merge pull request #4545 from Rob--W/crx-api-enhancements
Browse files Browse the repository at this point in the history
Use new Chromium APIs for FTP and redirects
  • Loading branch information
yurydelendik committed Apr 2, 2014
2 parents 75d09fd + ae32f31 commit bd11111
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 8 deletions.
121 changes: 121 additions & 0 deletions extensions/chromium/feature-detect.js
@@ -0,0 +1,121 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/*
Copyright 2014 Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* globals chrome */

'use strict';

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) {
Features = features;
if (features.featureDetectLastUA === navigator.userAgent) {
// Browser not upgraded, so the features did probably not change.
return;
}
var inconclusiveTestCount = 0;

if (!features.extensionSupportsFTP) {
features.extensionSupportsFTP = featureTestFTP();
}

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.
// Feature is supported since Chromium 35.0.1888.0 (r256810).
function featureTestFTP() {
var x = new XMLHttpRequest();
// The URL does not need to exist, as long as the scheme is ftp:.
x.open('GET', 'ftp://ftp.mozilla.org/');
try {
x.send();
// Previous call did not throw error, so the feature is supported!
// Immediately abort the request so that the network is not hit at all.
x.abort();
return true;
} catch (e) {
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();
}
5 changes: 3 additions & 2 deletions extensions/chromium/pdfHandler-v2.js
Expand Up @@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* globals chrome, URL, getViewerURL */
/* globals chrome, URL, getViewerURL, Features */

(function() {
'use strict';
Expand Down Expand Up @@ -158,7 +158,8 @@ limitations under the License.
var streamInfo = getStream(sender.tab.id, pdfUrl) || {};
sendResponse({
streamUrl: streamInfo.streamUrl,
contentLength: streamInfo.contentLength
contentLength: streamInfo.contentLength,
extensionSupportsFTP: Features.extensionSupportsFTP
});
}
});
Expand Down
1 change: 1 addition & 0 deletions extensions/chromium/pdfHandler.html
Expand Up @@ -15,6 +15,7 @@
limitations under the License.
-->
<script src="chrome.tabs.executeScriptInFrame.js"></script>
<script src="feature-detect.js"></script>
<script src="pdfHandler.js"></script>
<script src="extension-router.js"></script>
<script src="pdfHandler-v2.js"></script>
Expand Down
30 changes: 27 additions & 3 deletions extensions/chromium/pdfHandler.js
Expand Up @@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* globals chrome */
/* globals chrome, Features */

'use strict';

Expand Down Expand Up @@ -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!
Expand Down Expand Up @@ -172,6 +175,27 @@ chrome.webRequest.onHeadersReceived.addListener(
},
['blocking','responseHeaders']);

chrome.webRequest.onBeforeRequest.addListener(
function onBeforeRequestForFTP(details) {
if (!Features.extensionSupportsFTP) {
chrome.webRequest.onBeforeRequest.removeListener(onBeforeRequestForFTP);
return;
}
if (isPdfDownloadable(details)) {
return;
}
var viewerUrl = getViewerURL(details.url);
return { redirectUrl: viewerUrl };
},
{
urls: [
'ftp://*/*.pdf',
'ftp://*/*.PDF'
],
types: ['main_frame', 'sub_frame']
},
['blocking']);

chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (isPdfDownloadable(details)) {
Expand Down
7 changes: 4 additions & 3 deletions web/viewer.js
Expand Up @@ -1880,9 +1880,10 @@ function webViewerLoad(evt) {
// PDFView.setTitleUsingUrl(file);
// return;
// }
// if (isFTPFile) {
// // Stream not found, and it's loaded from FTP. Reload the page, because
// // it is not possible to get resources over ftp using XMLHttpRequest.
// if (isFTPFile && !response.extensionSupportsFTP) {
// // Stream not found, and it's loaded from FTP.
// // When the browser does not support loading ftp resources over
// // XMLHttpRequest, just reload the page.
// // NOTE: This will not lead to an infinite redirect loop, because
// // if the file exists, then the streamsPrivate API will capture the
// // stream and send back the response. If the stream does not exist, then
Expand Down

0 comments on commit bd11111

Please sign in to comment.