[CRX] Show nicely formatted URL in omnibox

Before commit:
chrome-extension://EXTENSIONID/content/web/viewer.html?file=http%3A%2F%2Fexample.com%2Ffile.pdf

After commit:
chrome-extension://EXTENSIONID/http://example/file.pdf

Technical details:
- The extension's background page uses the webRequest API to intercept
  requests for <extension host>/<real path to pdf>, and redirect it to
  the viewer's URL.
- viewer.js uses history.replaceState to rewrite the URL, so that it's
  easier for users to recognize and copy-paste URLs.
- The fake paths /http:, /https:, /file:, etc. have been added to the
  web_accessible_resources section of the manifest file, in order to
  avoid seeing chrome-extension://invalid/ instead of the actual URL
  when using history back/forward to navigate from/to the PDF viewer.
- Since the relative path resolving doesn't work because relative URLs
  are inaccurate, a <base> tag has been added. This method has already
  been proven to work in the Firefox add-on.

Notes:
- This commit has been cherry-picked from crx-using-streams-api.
- Need to merge https://github.com/mozilla/pdf.js/pull/3582 to deal with
  a bug in Chrome <=30
- In Chrome, getting the contents of a FTP file is not possible, so
  there's no support for FTP files, even though the extension router
  recognizes the ftp: scheme.
This commit is contained in:
Rob Wu 2013-08-15 22:47:30 +02:00
parent e9cb91de39
commit 83b780af81
6 changed files with 100 additions and 7 deletions

View File

@ -0,0 +1,54 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/*
Copyright 2013 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';
(function ExtensionRouterClosure() {
var VIEWER_URL = chrome.extension.getURL('content/web/viewer.html');
var CRX_BASE_URL = chrome.extension.getURL('/');
// TODO(rob): Use declarativeWebRequest once declared URL-encoding is
// supported, see http://crbug.com/273589
// (or rewrite the query string parser in viewer.js to get it to
// recognize the non-URL-encoded PDF URL.)
chrome.webRequest.onBeforeRequest.addListener(function(details) {
// This listener converts chrome-extension://.../http://...pdf to
// chrome-extension://.../content/web/viewer.html?file=http%3A%2F%2F...pdf
var url = details.url.substring(CRX_BASE_URL.length);
var matchingUrl = /^(?:https?|file|ftp|chrome-extension)(:|%3A)/.exec(url);
if (matchingUrl) {
// location.hash is restored when "#" is missing from URL.
url = url.split('#')[0];
if (matchingUrl[1] === ':') {
url = encodeURIComponent(url);
}
url = VIEWER_URL + '?file=' + url;
console.log('Redirecting ' + details.url + ' to ' + url);
return { redirectUrl: url };
}
}, {
types: ['main_frame', 'sub_frame'],
urls: [
CRX_BASE_URL + 'http*', // and https
CRX_BASE_URL + 'file*',
CRX_BASE_URL + 'ftp*',
CRX_BASE_URL + 'chrome-extension*'
]
}, ['blocking']);
console.log('Set up extension URL router.');
})();

View File

@ -24,6 +24,11 @@
"incognito": "split",
"web_accessible_resources": [
"getFrameId",
"content/web/viewer.html"
"content/web/viewer.html",
"http:/*",
"https:/*",
"ftp:/*",
"file:/*",
"chrome-extension:/*"
]
}

View File

@ -16,3 +16,4 @@ limitations under the License.
-->
<script src="chrome.tabs.executeScriptInFrame.js"></script>
<script src="pdfHandler.js"></script>
<script src="extension-router.js"></script>

View File

@ -0,0 +1,5 @@
<!-- This snippet is used in the Chrome extension, see Makefile -->
<base href="/content/web/">
<link rel="resource" type="application/l10n" href="locale/locale.properties">
<script type="text/javascript" src="l10n.js"></script>
<script type="text/javascript" src="../build/pdf.js"></script>

View File

@ -25,6 +25,9 @@ limitations under the License.
<!--#if FIREFOX || MOZCENTRAL-->
<!--#include viewer-snippet-firefox-extension.html-->
<!--#endif-->
<!--#if CHROME-->
<!--#include viewer-snippet-chrome-extension.html-->
<!--#endif-->
<link rel="stylesheet" href="viewer.css"/>
@ -53,7 +56,7 @@ limitations under the License.
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script>
<!--#endif-->
<!--#if GENERIC || CHROME-->
<!--#if GENERIC -->
<!--#include viewer-snippet.html-->
<!--#endif-->

View File

@ -670,15 +670,19 @@ var PDFView = {
},
/**
* For the firefox extension we prefix the full url on anchor links so they
* don't come up as resource:// urls and so open in new tab/window works.
* @param {String} anchor The anchor hash include the #.
* Prefix the full url on anchor links to make sure that links are resolved
* relative to the current URL instead of the one defined in <base href>.
* @param {String} anchor The anchor hash, including the #.
*/
getAnchorUrl: function getAnchorUrl(anchor) {
//#if !(FIREFOX || MOZCENTRAL)
//#if !(FIREFOX || MOZCENTRAL || CHROME)
return anchor;
//#else
//#if CHROME
// return location.href.split('#')[0] + anchor;
//#else
// return this.url.split('#')[0] + anchor;
//#endif
//#endif
},
@ -1459,15 +1463,36 @@ var DocumentOutlineView = function documentOutlineView(outline) {
}
};
//#if CHROME
//(function rewriteUrlClosure() {
// // Run this code outside DOMContentLoaded to make sure that the URL
// // is rewritten as soon as possible.
// if (location.origin + '/' !== chrome.extension.getURL('/')) {
// DEFAULT_URL = window.location.href.split('#')[0];
// } else {
// var params = PDFView.parseQueryString(document.location.search.slice(1));
// DEFAULT_URL = params.file || DEFAULT_URL;
//
// // Example: chrome-extension://.../http://example.com/file.pdf
// var humanReadableUrl = '/' + DEFAULT_URL + location.hash;
// history.replaceState(history.state, '', humanReadableUrl);
// }
//})();
//#endif
document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
PDFView.initialize();
//#if !(FIREFOX || MOZCENTRAL)
//#if !(FIREFOX || MOZCENTRAL || CHROME)
var params = PDFView.parseQueryString(document.location.search.substring(1));
var file = params.file || DEFAULT_URL;
//#else
//#if CHROME
//var file = DEFAULT_URL;
//#else
//var file = window.location.href.split('#')[0];
//#endif
//#endif
//#if CHROME
//if (location.protocol !== 'chrome-extension:') {