[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