[Pkg-javascript-commits] [pdf.js] 74/106: [CRX] Add Referer request header if needed
David Prévot
taffit at moszumanska.debian.org
Sat Jun 20 21:34:57 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit adb2f8ae21dd73ef1e37bd0cc354b3a8b12f4eb1
Author: Rob Wu <rob at robwu.nl>
Date: Tue Mar 10 15:22:32 2015 +0100
[CRX] Add Referer request header if needed
This patch adds the Referer request header to PDF requests if
the original PDF request included the Referer header.
---
extensions/chromium/pdfHandler.html | 1 +
extensions/chromium/pdfHandler.js | 5 +-
extensions/chromium/preserve-referer.js | 143 ++++++++++++++++++++++++++++++++
web/chromecom.js | 62 ++++++++++++++
web/pdf_history.js | 11 +++
web/viewer.js | 4 +-
6 files changed, 223 insertions(+), 3 deletions(-)
diff --git a/extensions/chromium/pdfHandler.html b/extensions/chromium/pdfHandler.html
index 79657a0..02a82fa 100644
--- a/extensions/chromium/pdfHandler.html
+++ b/extensions/chromium/pdfHandler.html
@@ -16,6 +16,7 @@ limitations under the License.
-->
<script src="chrome.tabs.executeScriptInFrame.js"></script>
<script src="feature-detect.js"></script>
+<script src="preserve-referer.js"></script>
<script src="pdfHandler.js"></script>
<script src="extension-router.js"></script>
<script src="pdfHandler-v2.js"></script>
diff --git a/extensions/chromium/pdfHandler.js b/extensions/chromium/pdfHandler.js
index b0c0cee..6cb82ef 100644
--- a/extensions/chromium/pdfHandler.js
+++ b/extensions/chromium/pdfHandler.js
@@ -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, Features */
+/* globals chrome, Features, saveReferer */
'use strict';
@@ -113,6 +113,9 @@ chrome.webRequest.onHeadersReceived.addListener(
var viewerUrl = getViewerURL(details.url);
+ // Implemented in preserve-referer.js
+ saveReferer(details);
+
// Replace frame with viewer
if (Features.webRequestRedirectUrl) {
return { redirectUrl: viewerUrl };
diff --git a/extensions/chromium/preserve-referer.js b/extensions/chromium/preserve-referer.js
new file mode 100644
index 0000000..f9702ea
--- /dev/null
+++ b/extensions/chromium/preserve-referer.js
@@ -0,0 +1,143 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/*
+Copyright 2015 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, getHeaderFromHeaders */
+/* exported saveReferer */
+
+'use strict';
+/**
+ * This file is one part of the Referer persistency implementation. The other
+ * part resides in chromecom.js.
+ *
+ * This file collects request headers for every http(s) request, and temporarily
+ * stores the request headers in a dictionary. Upon completion of the request
+ * (success or failure), the headers are discarded.
+ * pdfHandler.js will call saveReferer(details) when it is about to redirect to
+ * the viewer. Upon calling saveReferer, the Referer header is extracted from
+ * the request headers and saved.
+ *
+ * When the viewer is opened, it opens a port ("chromecom-referrer"). This port
+ * is used to set up the webRequest listeners that stick the Referer headers to
+ * the HTTP requests created by this extension. When the port is disconnected,
+ * the webRequest listeners and the referrer information is discarded.
+ *
+ * See setReferer in chromecom.js for more explanation of this logic.
+ */
+
+// Remembers the request headers for every http(s) page request for the duration
+// of the request.
+var g_requestHeaders = {};
+// g_referrers[tabId][frameId] = referrer of PDF frame.
+var g_referrers = {};
+
+(function() {
+ var requestFilter = {
+ urls: ['*://*/*'],
+ types: ['main_frame', 'sub_frame']
+ };
+ chrome.webRequest.onSendHeaders.addListener(function(details) {
+ g_requestHeaders[details.requestId] = details.requestHeaders;
+ }, requestFilter, ['requestHeaders']);
+ chrome.webRequest.onBeforeRedirect.addListener(forgetHeaders, requestFilter);
+ chrome.webRequest.onCompleted.addListener(forgetHeaders, requestFilter);
+ chrome.webRequest.onErrorOccurred.addListener(forgetHeaders, requestFilter);
+ function forgetHeaders(details) {
+ delete g_requestHeaders[details.requestId];
+ }
+})();
+
+/**
+ * @param {object} details - onHeadersReceived event data.
+ */
+function saveReferer(details) {
+ var referer = g_requestHeaders[details.requestId] &&
+ getHeaderFromHeaders(g_requestHeaders[details.requestId], 'referer');
+ referer = referer && referer.value || '';
+ if (!g_referrers[details.tabId]) {
+ g_referrers[details.tabId] = {};
+ }
+ g_referrers[details.tabId][details.frameId] = referer;
+}
+
+chrome.tabs.onRemoved.addListener(function(tabId) {
+ delete g_referrers[tabId];
+});
+
+// This method binds a webRequest event handler which adds the Referer header
+// to matching PDF resource requests (only if the Referer is non-empty). The
+// handler is removed as soon as the PDF viewer frame is unloaded.
+chrome.runtime.onConnect.addListener(function onReceivePort(port) {
+ if (port.name !== 'chromecom-referrer') {
+ return;
+ }
+ // Note: sender.frameId is only set in Chrome 41+.
+ if (!('frameId' in port.sender)) {
+ port.disconnect();
+ return;
+ }
+ var tabId = port.sender.tab.id;
+ var frameId = port.sender.frameId;
+
+ // If the PDF is viewed for the first time, then the referer will be set here.
+ var referer = g_referrers[tabId] && g_referrers[tabId][frameId] || '';
+ port.onMessage.addListener(function(data) {
+ // If the viewer was opened directly (without opening a PDF URL first), then
+ // the background script does not know about g_referrers, but the viewer may
+ // know about the referer if stored in the history state (see chromecom.js).
+ if (data.referer) {
+ referer = data.referer;
+ }
+ chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
+ if (referer) {
+ // Only add a blocking request handler if the referer has to be rewritten.
+ chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {
+ urls: [data.requestUrl],
+ types: ['xmlhttprequest'],
+ tabId: tabId
+ }, ['blocking', 'requestHeaders']);
+ }
+ // Acknowledge the message, and include the latest referer for this frame.
+ port.postMessage(referer);
+ });
+
+ // The port is only disconnected when the other end reloads.
+ port.onDisconnect.addListener(function() {
+ if (g_referrers[tabId]) {
+ delete g_referrers[tabId][frameId];
+ }
+ chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
+ });
+
+ function onBeforeSendHeaders(details) {
+ if (details.frameId !== frameId) {
+ return;
+ }
+ var headers = details.requestHeaders;
+ var refererHeader = getHeaderFromHeaders(headers, 'referer');
+ if (!refererHeader) {
+ refererHeader = {name: 'Referer'};
+ headers.push(refererHeader);
+ } else if (refererHeader.value &&
+ refererHeader.value.lastIndexOf('chrome-extension:', 0) !== 0) {
+ // Sanity check. If the referer is set, and the value is not the URL of
+ // this extension, then the request was not initiated by this extension.
+ return;
+ }
+ refererHeader.value = referer;
+ return {requestHeaders: headers};
+ }
+});
diff --git a/web/chromecom.js b/web/chromecom.js
index 5fe69fe..a4c9ee4 100644
--- a/web/chromecom.js
+++ b/web/chromecom.js
@@ -104,8 +104,70 @@ var ChromeCom = (function ChromeComClosure() {
});
return;
}
+ if (/^https?:/.test(file)) {
+ // Assumption: The file being opened is the file that was requested.
+ // There is no UI to input a different URL, so this assumption will hold
+ // for now.
+ setReferer(file, function() {
+ PDFViewerApplication.open(file, 0);
+ });
+ return;
+ }
PDFViewerApplication.open(file, 0);
});
};
+
+ // This port is used for several purposes:
+ // 1. When disconnected, the background page knows that the frame has unload.
+ // 2. When the referrer was saved in history.state.chromecomState, it is sent
+ // to the background page.
+ // 3. When the background page knows the referrer of the page, the referrer is
+ // saved in history.state.chromecomState.
+ var port;
+ // Set the referer for the given URL.
+ // 0. Background: If loaded via a http(s) URL: Save referer.
+ // 1. Page -> background: send URL and referer from history.state
+ // 2. Background: Bind referer to URL (via webRequest).
+ // 3. Background -> page: Send latest referer and save to history.
+ // 4. Page: Invoke callback.
+ function setReferer(url, callback) {
+ if (!port) {
+ // The background page will accept the port, and keep adding the Referer
+ // request header to requests to |url| until the port is disconnected.
+ port = chrome.runtime.connect({name: 'chromecom-referrer'});
+ }
+ port.onDisconnect.addListener(onDisconnect);
+ port.onMessage.addListener(onMessage);
+ // Initiate the information exchange.
+ port.postMessage({
+ referer: window.history.state && window.history.state.chromecomState,
+ requestUrl: url
+ });
+
+ function onMessage(referer) {
+ if (referer) {
+ // The background extracts the Referer from the initial HTTP request for
+ // the PDF file. When the viewer is reloaded or when the user navigates
+ // back and forward, the background page will not observe a HTTP request
+ // with Referer. To make sure that the Referer is preserved, store it in
+ // history.state, which is preserved accross reloads/navigations.
+ var state = window.history.state || {};
+ state.chromecomState = referer;
+ window.history.replaceState(state, '');
+ }
+ onCompleted();
+ }
+ function onDisconnect() {
+ // When the connection fails, ignore the error and call the callback.
+ port = null;
+ onCompleted();
+ }
+ function onCompleted() {
+ port.onDisconnect.removeListener(onDisconnect);
+ port.onMessage.removeListener(onMessage);
+ callback();
+ }
+ }
+
return ChromeCom;
})();
diff --git a/web/pdf_history.js b/web/pdf_history.js
index e426273..a2fe22e 100644
--- a/web/pdf_history.js
+++ b/web/pdf_history.js
@@ -135,6 +135,10 @@ var PDFHistory = (function () {
});
},
+ clearHistoryState: function pdfHistory_clearHistoryState() {
+ this._pushOrReplaceState(null, true);
+ },
+
_isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) {
return (state && state.uid >= 0 &&
state.fingerprint && this.fingerprint === state.fingerprint &&
@@ -143,6 +147,13 @@ var PDFHistory = (function () {
_pushOrReplaceState: function pdfHistory_pushOrReplaceState(stateObj,
replace) {
+//#if CHROME
+ // history.state.chromecomState is managed by chromecom.js.
+ if (window.history.state && 'chromecomState' in window.history.state) {
+ stateObj = stateObj || {};
+ stateObj.chromecomState = window.history.state.chromecomState;
+ }
+//#endif
if (replace) {
//#if (GENERIC || CHROME)
window.history.replaceState(stateObj, '', document.URL);
diff --git a/web/viewer.js b/web/viewer.js
index a3db3b4..0b473c0 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -795,8 +795,8 @@ var PDFViewerApplication = {
if (!PDFJS.disableHistory && !self.isViewerEmbedded) {
// The browsing history is only enabled when the viewer is standalone,
// i.e. not when it is embedded in a web page.
- if (!self.preferenceShowPreviousViewOnLoad && window.history.state) {
- window.history.replaceState(null, '');
+ if (!self.preferenceShowPreviousViewOnLoad) {
+ PDFHistory.clearHistoryState();
}
self.pdfHistory.initialize(self.documentFingerprint);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git
More information about the Pkg-javascript-commits
mailing list