mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
Add pdfjs to PM (from basilisk)
This commit is contained in:
parent
e75a07ae32
commit
32e898e91e
276 changed files with 69821 additions and 0 deletions
|
|
@ -1098,6 +1098,18 @@ pref("permissions.manager.defaultsUrl", "resource://app/defaults/permissions");
|
|||
// (this pref has no effect if more than 6 hours have passed since the last crash)
|
||||
pref("toolkit.startup.max_resumed_crashes", 3);
|
||||
|
||||
// Completely disable pdf.js as an option to preview pdfs within firefox.
|
||||
// Note: if this is not disabled it does not necessarily mean pdf.js is the pdf
|
||||
// handler just that it is an option.
|
||||
pref("pdfjs.disabled", false);
|
||||
// Used by pdf.js to know the first time firefox is run with it installed so it
|
||||
// can become the default pdf viewer.
|
||||
pref("pdfjs.firstRun", true);
|
||||
// The values of preferredAction and alwaysAskBeforeHandling before pdf.js
|
||||
// became the default.
|
||||
pref("pdfjs.previousHandler.preferredAction", 0);
|
||||
pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
|
||||
|
||||
// The maximum amount of decoded image data we'll willingly keep around (we
|
||||
// might keep around more than this, but we'll try to get down to this value).
|
||||
// (This is intentionally on the high side; see bug 746055.)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "winShellService",
|
|||
["BookmarkHTMLUtils", "resource://gre/modules/BookmarkHTMLUtils.jsm"],
|
||||
["BookmarkJSONUtils", "resource://gre/modules/BookmarkJSONUtils.jsm"],
|
||||
["PageThumbs", "resource://gre/modules/PageThumbs.jsm"],
|
||||
["PdfJs", "resource://pdf.js/PdfJs.jsm"],
|
||||
["NewTabUtils", "resource://gre/modules/NewTabUtils.jsm"],
|
||||
["BrowserNewTabPreloader", "resource:///modules/BrowserNewTabPreloader.jsm"],
|
||||
#ifdef MOZ_WEBRTC
|
||||
|
|
@ -630,6 +631,20 @@ BrowserGlue.prototype = {
|
|||
|
||||
// the first browser window has finished initializing
|
||||
_onFirstWindowLoaded: function() {
|
||||
// Initialize PdfJs when running in-process and remote. This only
|
||||
// happens once since PdfJs registers global hooks. If the PdfJs
|
||||
// extension is installed the init method below will be overridden
|
||||
// leaving initialization to the extension.
|
||||
// parent only: configure default prefs, set up pref observers, register
|
||||
// pdf content handler, and initializes parent side message manager
|
||||
// shim for privileged api access.
|
||||
PdfJs.init(true);
|
||||
// child only: similar to the call above for parent - register content
|
||||
// handler and init message manager child shim for privileged api access.
|
||||
// With older versions of the extension installed, this load will fail
|
||||
// passively.
|
||||
Services.ppmm.loadProcessScript("resource://pdf.js/pdfjschildbootstrap.js", true);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// For Windows, initialize the jump list module.
|
||||
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
|
||||
|
|
|
|||
9
application/palemoon/extensions/moz.build
Normal file
9
application/palemoon/extensions/moz.build
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'pdfjs',
|
||||
]
|
||||
|
||||
177
application/palemoon/extensions/pdfjs/LICENSE
Normal file
177
application/palemoon/extensions/pdfjs/LICENSE
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
3
application/palemoon/extensions/pdfjs/README.mozilla
Normal file
3
application/palemoon/extensions/pdfjs/README.mozilla
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.7.348
|
||||
1
application/palemoon/extensions/pdfjs/chrome.manifest
Normal file
1
application/palemoon/extensions/pdfjs/chrome.manifest
Normal file
|
|
@ -0,0 +1 @@
|
|||
resource pdf.js content/
|
||||
349
application/palemoon/extensions/pdfjs/content/PdfJs.jsm
Normal file
349
application/palemoon/extensions/pdfjs/content/PdfJs.jsm
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
/* Copyright 2012 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 Components, Services, XPCOMUtils, PdfjsChromeUtils,
|
||||
PdfjsContentUtils, PdfStreamConverter */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PdfJs"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cm = Components.manager;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const PREF_PREFIX = "pdfjs";
|
||||
const PREF_DISABLED = PREF_PREFIX + ".disabled";
|
||||
const PREF_MIGRATION_VERSION = PREF_PREFIX + ".migrationVersion";
|
||||
const PREF_PREVIOUS_ACTION = PREF_PREFIX + ".previousHandler.preferredAction";
|
||||
const PREF_PREVIOUS_ASK = PREF_PREFIX +
|
||||
".previousHandler.alwaysAskBeforeHandling";
|
||||
const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
|
||||
const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
|
||||
const TOPIC_PLUGINS_LIST_UPDATED = "plugins-list-updated";
|
||||
const TOPIC_PLUGIN_INFO_UPDATED = "plugin-info-updated";
|
||||
const PDF_CONTENT_TYPE = "application/pdf";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
|
||||
"@mozilla.org/mime;1",
|
||||
"nsIMIMEService");
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, "pluginHost",
|
||||
"@mozilla.org/plugin/host;1",
|
||||
"nsIPluginHost");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PdfjsChromeUtils",
|
||||
"resource://pdf.js/PdfjsChromeUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PdfjsContentUtils",
|
||||
"resource://pdf.js/PdfjsContentUtils.jsm");
|
||||
|
||||
function getBoolPref(aPref, aDefaultValue) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(aPref);
|
||||
} catch (ex) {
|
||||
return aDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
function getIntPref(aPref, aDefaultValue) {
|
||||
try {
|
||||
return Services.prefs.getIntPref(aPref);
|
||||
} catch (ex) {
|
||||
return aDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
function isDefaultHandler() {
|
||||
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
return PdfjsContentUtils.isDefaultHandlerApp();
|
||||
}
|
||||
return PdfjsChromeUtils.isDefaultHandlerApp();
|
||||
}
|
||||
|
||||
function initializeDefaultPreferences() {
|
||||
var DEFAULT_PREFERENCES =
|
||||
{
|
||||
"showPreviousViewOnLoad": true,
|
||||
"defaultZoomValue": "",
|
||||
"sidebarViewOnLoad": 0,
|
||||
"enableHandToolOnLoad": false,
|
||||
"enableWebGL": false,
|
||||
"pdfBugEnabled": false,
|
||||
"disableRange": false,
|
||||
"disableStream": false,
|
||||
"disableAutoFetch": false,
|
||||
"disableFontFace": false,
|
||||
"disableTextLayer": false,
|
||||
"useOnlyCssZoom": false,
|
||||
"externalLinkTarget": 0,
|
||||
"enhanceTextSelection": false,
|
||||
"renderer": "canvas",
|
||||
"renderInteractiveForms": false,
|
||||
"enablePrintAutoRotate": false,
|
||||
"disablePageLabels": false
|
||||
}
|
||||
|
||||
|
||||
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
|
||||
var defaultValue;
|
||||
for (var key in DEFAULT_PREFERENCES) {
|
||||
defaultValue = DEFAULT_PREFERENCES[key];
|
||||
switch (typeof defaultValue) {
|
||||
case "boolean":
|
||||
defaultBranch.setBoolPref(key, defaultValue);
|
||||
break;
|
||||
case "number":
|
||||
defaultBranch.setIntPref(key, defaultValue);
|
||||
break;
|
||||
case "string":
|
||||
defaultBranch.setCharPref(key, defaultValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a factory.
|
||||
function Factory() {}
|
||||
Factory.prototype = {
|
||||
register: function register(targetConstructor) {
|
||||
var proto = targetConstructor.prototype;
|
||||
this._classID = proto.classID;
|
||||
|
||||
var factory = XPCOMUtils._getFactory(targetConstructor);
|
||||
this._factory = factory;
|
||||
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(proto.classID, proto.classDescription,
|
||||
proto.contractID, factory);
|
||||
|
||||
if (proto.classID2) {
|
||||
this._classID2 = proto.classID2;
|
||||
registrar.registerFactory(proto.classID2, proto.classDescription,
|
||||
proto.contractID2, factory);
|
||||
}
|
||||
},
|
||||
|
||||
unregister: function unregister() {
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(this._classID, this._factory);
|
||||
if (this._classID2) {
|
||||
registrar.unregisterFactory(this._classID2, this._factory);
|
||||
}
|
||||
this._factory = null;
|
||||
}
|
||||
};
|
||||
|
||||
var PdfJs = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
_registered: false,
|
||||
_initialized: false,
|
||||
|
||||
init: function init(remote) {
|
||||
if (Services.appinfo.processType !==
|
||||
Services.appinfo.PROCESS_TYPE_DEFAULT) {
|
||||
throw new Error("PdfJs.init should only get called " +
|
||||
"in the parent process.");
|
||||
}
|
||||
PdfjsChromeUtils.init();
|
||||
if (!remote) {
|
||||
PdfjsContentUtils.init();
|
||||
}
|
||||
this.initPrefs();
|
||||
this.updateRegistration();
|
||||
},
|
||||
|
||||
initPrefs: function initPrefs() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
this._initialized = true;
|
||||
|
||||
if (!getBoolPref(PREF_DISABLED, true)) {
|
||||
this._migrate();
|
||||
}
|
||||
|
||||
// Listen for when pdf.js is completely disabled or a different pdf handler
|
||||
// is chosen.
|
||||
Services.prefs.addObserver(PREF_DISABLED, this, false);
|
||||
Services.prefs.addObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
|
||||
Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
|
||||
Services.obs.addObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
|
||||
Services.obs.addObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
|
||||
|
||||
initializeDefaultPreferences();
|
||||
},
|
||||
|
||||
updateRegistration: function updateRegistration() {
|
||||
if (this.enabled) {
|
||||
this._ensureRegistered();
|
||||
} else {
|
||||
this._ensureUnregistered();
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function uninit() {
|
||||
if (this._initialized) {
|
||||
Services.prefs.removeObserver(PREF_DISABLED, this);
|
||||
Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this);
|
||||
Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED);
|
||||
this._initialized = false;
|
||||
}
|
||||
this._ensureUnregistered();
|
||||
},
|
||||
|
||||
_migrate: function migrate() {
|
||||
const VERSION = 2;
|
||||
var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
|
||||
if (currentVersion >= VERSION) {
|
||||
return;
|
||||
}
|
||||
// Make pdf.js the default pdf viewer on the first migration.
|
||||
if (currentVersion < 1) {
|
||||
this._becomeHandler();
|
||||
}
|
||||
if (currentVersion < 2) {
|
||||
// cleaning up of unused database preference (see #3994)
|
||||
Services.prefs.clearUserPref(PREF_PREFIX + ".database");
|
||||
}
|
||||
Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
|
||||
},
|
||||
|
||||
_becomeHandler: function _becomeHandler() {
|
||||
let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
|
||||
let prefs = Services.prefs;
|
||||
if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
|
||||
handlerInfo.preferredAction !== false) {
|
||||
// Store the previous settings of preferredAction and
|
||||
// alwaysAskBeforeHandling in case we need to revert them in a hotfix that
|
||||
// would turn pdf.js off.
|
||||
prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
|
||||
prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
|
||||
}
|
||||
|
||||
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].
|
||||
getService(Ci.nsIHandlerService);
|
||||
|
||||
// Change and save mime handler settings.
|
||||
handlerInfo.alwaysAskBeforeHandling = false;
|
||||
handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
|
||||
handlerService.store(handlerInfo);
|
||||
|
||||
// Also disable any plugins for pdfs.
|
||||
var stringTypes = "";
|
||||
var types = [];
|
||||
if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
|
||||
stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
|
||||
}
|
||||
if (stringTypes !== "") {
|
||||
types = stringTypes.split(",");
|
||||
}
|
||||
|
||||
if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
|
||||
types.push(PDF_CONTENT_TYPE);
|
||||
}
|
||||
prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(","));
|
||||
|
||||
// Update the category manager in case the plugins are already loaded.
|
||||
let categoryManager = Cc["@mozilla.org/categorymanager;1"];
|
||||
categoryManager.getService(Ci.nsICategoryManager).
|
||||
deleteCategoryEntry("Gecko-Content-Viewers",
|
||||
PDF_CONTENT_TYPE,
|
||||
false);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
this.updateRegistration();
|
||||
if (Services.appinfo.processType ===
|
||||
Services.appinfo.PROCESS_TYPE_DEFAULT) {
|
||||
let jsm = "resource://pdf.js/PdfjsChromeUtils.jsm";
|
||||
let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils;
|
||||
PdfjsChromeUtils.notifyChildOfSettingsChange();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* pdf.js is only enabled if it is both selected as the pdf viewer and if the
|
||||
* global switch enabling it is true.
|
||||
* @return {boolean} Whether or not it's enabled.
|
||||
*/
|
||||
get enabled() {
|
||||
var disabled = getBoolPref(PREF_DISABLED, true);
|
||||
if (disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the 'application/pdf' preview handler is configured properly.
|
||||
if (!isDefaultHandler()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have disabled plugin handling of 'application/pdf' in prefs
|
||||
if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
|
||||
let disabledPluginTypes =
|
||||
Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(",");
|
||||
if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is an enabled pdf plugin.
|
||||
// Note: this check is performed last because getPluginTags() triggers
|
||||
// costly plugin list initialization (bug 881575)
|
||||
let tags = Cc["@mozilla.org/plugin/host;1"].
|
||||
getService(Ci.nsIPluginHost).
|
||||
getPluginTags();
|
||||
let enabledPluginFound = tags.some(function(tag) {
|
||||
if (tag.disabled) {
|
||||
return false;
|
||||
}
|
||||
let mimeTypes = tag.getMimeTypes();
|
||||
return mimeTypes.some(function(mimeType) {
|
||||
return mimeType === PDF_CONTENT_TYPE;
|
||||
});
|
||||
});
|
||||
|
||||
// Use pdf.js if pdf plugin is not present or disabled
|
||||
return !enabledPluginFound;
|
||||
},
|
||||
|
||||
_ensureRegistered: function _ensureRegistered() {
|
||||
if (this._registered) {
|
||||
return;
|
||||
}
|
||||
this._pdfStreamConverterFactory = new Factory();
|
||||
Cu.import("resource://pdf.js/PdfStreamConverter.jsm");
|
||||
this._pdfStreamConverterFactory.register(PdfStreamConverter);
|
||||
|
||||
this._registered = true;
|
||||
},
|
||||
|
||||
_ensureUnregistered: function _ensureUnregistered() {
|
||||
if (!this._registered) {
|
||||
return;
|
||||
}
|
||||
this._pdfStreamConverterFactory.unregister();
|
||||
Cu.unload("resource://pdf.js/PdfStreamConverter.jsm");
|
||||
delete this._pdfStreamConverterFactory;
|
||||
|
||||
this._registered = false;
|
||||
}
|
||||
};
|
||||
|
||||
257
application/palemoon/extensions/pdfjs/content/PdfJsNetwork.jsm
Normal file
257
application/palemoon/extensions/pdfjs/content/PdfJsNetwork.jsm
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/* Copyright 2012 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 Components, Services */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["NetworkManager"];
|
||||
|
||||
function log(aMsg) {
|
||||
var msg = "PdfJsNetwork.jsm: " + (aMsg.join ? aMsg.join("") : aMsg);
|
||||
Services.console.logStringMessage(msg);
|
||||
}
|
||||
|
||||
var NetworkManager = (function NetworkManagerClosure() {
|
||||
|
||||
const OK_RESPONSE = 200;
|
||||
const PARTIAL_CONTENT_RESPONSE = 206;
|
||||
|
||||
function getArrayBuffer(xhr) {
|
||||
var data = xhr.response;
|
||||
if (typeof data !== "string") {
|
||||
return data;
|
||||
}
|
||||
var length = data.length;
|
||||
var array = new Uint8Array(length);
|
||||
for (var i = 0; i < length; i++) {
|
||||
array[i] = data.charCodeAt(i) & 0xFF;
|
||||
}
|
||||
return array.buffer;
|
||||
}
|
||||
|
||||
class NetworkManagerClass {
|
||||
constructor(url, args) {
|
||||
this.url = url;
|
||||
args = args || {};
|
||||
this.isHttp = /^https?:/i.test(url);
|
||||
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
|
||||
this.withCredentials = args.withCredentials || false;
|
||||
this.getXhr = args.getXhr ||
|
||||
function NetworkManager_getXhr() {
|
||||
return new XMLHttpRequest();
|
||||
};
|
||||
|
||||
this.currXhrId = 0;
|
||||
this.pendingRequests = Object.create(null);
|
||||
this.loadedRequests = Object.create(null);
|
||||
}
|
||||
|
||||
requestRange(begin, end, listeners) {
|
||||
var args = {
|
||||
begin,
|
||||
end,
|
||||
};
|
||||
for (var prop in listeners) {
|
||||
args[prop] = listeners[prop];
|
||||
}
|
||||
return this.request(args);
|
||||
}
|
||||
|
||||
requestFull(listeners) {
|
||||
return this.request(listeners);
|
||||
}
|
||||
|
||||
request(args) {
|
||||
var xhr = this.getXhr();
|
||||
var xhrId = this.currXhrId++;
|
||||
var pendingRequest = this.pendingRequests[xhrId] = {
|
||||
xhr,
|
||||
};
|
||||
|
||||
xhr.open("GET", this.url);
|
||||
xhr.withCredentials = this.withCredentials;
|
||||
for (var property in this.httpHeaders) {
|
||||
var value = this.httpHeaders[property];
|
||||
if (typeof value === "undefined") {
|
||||
continue;
|
||||
}
|
||||
xhr.setRequestHeader(property, value);
|
||||
}
|
||||
if (this.isHttp && "begin" in args && "end" in args) {
|
||||
var rangeStr = args.begin + "-" + (args.end - 1);
|
||||
xhr.setRequestHeader("Range", "bytes=" + rangeStr);
|
||||
pendingRequest.expectedStatus = 206;
|
||||
} else {
|
||||
pendingRequest.expectedStatus = 200;
|
||||
}
|
||||
|
||||
var useMozChunkedLoading = !!args.onProgressiveData;
|
||||
if (useMozChunkedLoading) {
|
||||
xhr.responseType = "moz-chunked-arraybuffer";
|
||||
pendingRequest.onProgressiveData = args.onProgressiveData;
|
||||
pendingRequest.mozChunked = true;
|
||||
} else {
|
||||
xhr.responseType = "arraybuffer";
|
||||
}
|
||||
|
||||
if (args.onError) {
|
||||
xhr.onerror = function(evt) {
|
||||
args.onError(xhr.status);
|
||||
};
|
||||
}
|
||||
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
|
||||
xhr.onprogress = this.onProgress.bind(this, xhrId);
|
||||
|
||||
pendingRequest.onHeadersReceived = args.onHeadersReceived;
|
||||
pendingRequest.onDone = args.onDone;
|
||||
pendingRequest.onError = args.onError;
|
||||
pendingRequest.onProgress = args.onProgress;
|
||||
|
||||
xhr.send(null);
|
||||
|
||||
return xhrId;
|
||||
}
|
||||
|
||||
onProgress(xhrId, evt) {
|
||||
var pendingRequest = this.pendingRequests[xhrId];
|
||||
if (!pendingRequest) {
|
||||
// Maybe abortRequest was called...
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingRequest.mozChunked) {
|
||||
var chunk = getArrayBuffer(pendingRequest.xhr);
|
||||
pendingRequest.onProgressiveData(chunk);
|
||||
}
|
||||
|
||||
var onProgress = pendingRequest.onProgress;
|
||||
if (onProgress) {
|
||||
onProgress(evt);
|
||||
}
|
||||
}
|
||||
|
||||
onStateChange(xhrId, evt) {
|
||||
var pendingRequest = this.pendingRequests[xhrId];
|
||||
if (!pendingRequest) {
|
||||
// Maybe abortRequest was called...
|
||||
return;
|
||||
}
|
||||
|
||||
var xhr = pendingRequest.xhr;
|
||||
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
|
||||
pendingRequest.onHeadersReceived();
|
||||
delete pendingRequest.onHeadersReceived;
|
||||
}
|
||||
|
||||
if (xhr.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(xhrId in this.pendingRequests)) {
|
||||
// The XHR request might have been aborted in onHeadersReceived()
|
||||
// callback, in which case we should abort request
|
||||
return;
|
||||
}
|
||||
|
||||
delete this.pendingRequests[xhrId];
|
||||
|
||||
// success status == 0 can be on ftp, file and other protocols
|
||||
if (xhr.status === 0 && this.isHttp) {
|
||||
if (pendingRequest.onError) {
|
||||
pendingRequest.onError(xhr.status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var xhrStatus = xhr.status || OK_RESPONSE;
|
||||
|
||||
// From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
|
||||
// "A server MAY ignore the Range header". This means it's possible to
|
||||
// get a 200 rather than a 206 response from a range request.
|
||||
var ok_response_on_range_request =
|
||||
xhrStatus === OK_RESPONSE &&
|
||||
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
|
||||
|
||||
if (!ok_response_on_range_request &&
|
||||
xhrStatus !== pendingRequest.expectedStatus) {
|
||||
if (pendingRequest.onError) {
|
||||
pendingRequest.onError(xhr.status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadedRequests[xhrId] = true;
|
||||
|
||||
var chunk = getArrayBuffer(xhr);
|
||||
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
|
||||
var rangeHeader = xhr.getResponseHeader("Content-Range");
|
||||
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
|
||||
var begin = parseInt(matches[1], 10);
|
||||
pendingRequest.onDone({
|
||||
begin,
|
||||
chunk,
|
||||
});
|
||||
} else if (pendingRequest.onProgressiveData) {
|
||||
pendingRequest.onDone(null);
|
||||
} else if (chunk) {
|
||||
pendingRequest.onDone({
|
||||
begin: 0,
|
||||
chunk,
|
||||
});
|
||||
} else if (pendingRequest.onError) {
|
||||
pendingRequest.onError(xhr.status);
|
||||
}
|
||||
}
|
||||
|
||||
hasPendingRequests() {
|
||||
for (var xhrId in this.pendingRequests) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getRequestXhr(xhrId) {
|
||||
return this.pendingRequests[xhrId].xhr;
|
||||
}
|
||||
|
||||
isStreamingRequest(xhrId) {
|
||||
return !!(this.pendingRequests[xhrId].onProgressiveData);
|
||||
}
|
||||
|
||||
isPendingRequest(xhrId) {
|
||||
return xhrId in this.pendingRequests;
|
||||
}
|
||||
|
||||
isLoadedRequest(xhrId) {
|
||||
return xhrId in this.loadedRequests;
|
||||
}
|
||||
|
||||
abortAllRequests() {
|
||||
for (var xhrId in this.pendingRequests) {
|
||||
this.abortRequest(xhrId | 0);
|
||||
}
|
||||
}
|
||||
|
||||
abortRequest(xhrId) {
|
||||
var xhr = this.pendingRequests[xhrId].xhr;
|
||||
delete this.pendingRequests[xhrId];
|
||||
xhr.abort();
|
||||
}
|
||||
}
|
||||
|
||||
return NetworkManagerClass;
|
||||
})();
|
||||
|
||||
|
|
@ -0,0 +1,964 @@
|
|||
/* Copyright 2012 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 Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
||||
dump, NetworkManager, PdfjsContentUtils */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PdfStreamConverter"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const PDFJS_EVENT_ID = "pdf.js.message";
|
||||
const PDF_CONTENT_TYPE = "application/pdf";
|
||||
const PREF_PREFIX = "pdfjs";
|
||||
const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html";
|
||||
const MAX_NUMBER_OF_PREFS = 50;
|
||||
const MAX_STRING_PREF_LENGTH = 128;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetworkManager",
|
||||
"resource://pdf.js/PdfJsNetwork.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PdfjsContentUtils",
|
||||
"resource://pdf.js/PdfjsContentUtils.jsm");
|
||||
|
||||
var Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
|
||||
"@mozilla.org/mime;1",
|
||||
"nsIMIMEService");
|
||||
|
||||
function getContainingBrowser(domWindow) {
|
||||
return domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
}
|
||||
|
||||
function getFindBar(domWindow) {
|
||||
if (PdfjsContentUtils.isRemote) {
|
||||
throw new Error("FindBar is not accessible from the content process.");
|
||||
}
|
||||
try {
|
||||
var browser = getContainingBrowser(domWindow);
|
||||
var tabbrowser = browser.getTabBrowser();
|
||||
var tab = tabbrowser.getTabForBrowser(browser);
|
||||
return tabbrowser.getFindBar(tab);
|
||||
} catch (e) {
|
||||
// Suppress errors for PDF files opened in the bookmark sidebar, see
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1248959.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getBoolPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(pref);
|
||||
} catch (ex) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
function getIntPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getIntPref(pref);
|
||||
} catch (ex) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
function getStringPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
|
||||
} catch (ex) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
function log(aMsg) {
|
||||
if (!getBoolPref(PREF_PREFIX + ".pdfBugEnabled", false)) {
|
||||
return;
|
||||
}
|
||||
var msg = "PdfStreamConverter.js: " + (aMsg.join ? aMsg.join("") : aMsg);
|
||||
Services.console.logStringMessage(msg);
|
||||
dump(msg + "\n");
|
||||
}
|
||||
|
||||
function getDOMWindow(aChannel) {
|
||||
var requestor = aChannel.notificationCallbacks ?
|
||||
aChannel.notificationCallbacks :
|
||||
aChannel.loadGroup.notificationCallbacks;
|
||||
var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
return win;
|
||||
}
|
||||
|
||||
function getLocalizedStrings(path) {
|
||||
var stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://pdf.js/locale/" + path);
|
||||
|
||||
var map = {};
|
||||
var enumerator = stringBundle.getSimpleEnumeration();
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
|
||||
var key = string.key, property = "textContent";
|
||||
var i = key.lastIndexOf(".");
|
||||
if (i >= 0) {
|
||||
property = key.substring(i + 1);
|
||||
key = key.substring(0, i);
|
||||
}
|
||||
if (!(key in map)) {
|
||||
map[key] = {};
|
||||
}
|
||||
map[key][property] = string.value;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
function getLocalizedString(strings, id, property) {
|
||||
property = property || "textContent";
|
||||
if (id in strings) {
|
||||
return strings[id][property];
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// PDF data storage
|
||||
function PdfDataListener(length) {
|
||||
this.length = length; // less than 0, if length is unknown
|
||||
this.buffer = null;
|
||||
this.loaded = 0;
|
||||
}
|
||||
|
||||
PdfDataListener.prototype = {
|
||||
append: function PdfDataListener_append(chunk) {
|
||||
// In most of the cases we will pass data as we receive it, but at the
|
||||
// beginning of the loading we may accumulate some data.
|
||||
if (!this.buffer) {
|
||||
this.buffer = new Uint8Array(chunk);
|
||||
} else {
|
||||
var buffer = this.buffer;
|
||||
var newBuffer = new Uint8Array(buffer.length + chunk.length);
|
||||
newBuffer.set(buffer);
|
||||
newBuffer.set(chunk, buffer.length);
|
||||
this.buffer = newBuffer;
|
||||
}
|
||||
this.loaded += chunk.length;
|
||||
if (this.length >= 0 && this.length < this.loaded) {
|
||||
this.length = -1; // reset the length, server is giving incorrect one
|
||||
}
|
||||
this.onprogress(this.loaded, this.length >= 0 ? this.length : void 0);
|
||||
},
|
||||
readData: function PdfDataListener_readData() {
|
||||
var result = this.buffer;
|
||||
this.buffer = null;
|
||||
return result;
|
||||
},
|
||||
finish: function PdfDataListener_finish() {
|
||||
this.isDataReady = true;
|
||||
if (this.oncompleteCallback) {
|
||||
this.oncompleteCallback(this.readData());
|
||||
}
|
||||
},
|
||||
error: function PdfDataListener_error(errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
if (this.oncompleteCallback) {
|
||||
this.oncompleteCallback(null, errorCode);
|
||||
}
|
||||
},
|
||||
onprogress() {},
|
||||
get oncomplete() {
|
||||
return this.oncompleteCallback;
|
||||
},
|
||||
set oncomplete(value) {
|
||||
this.oncompleteCallback = value;
|
||||
if (this.isDataReady) {
|
||||
value(this.readData());
|
||||
}
|
||||
if (this.errorCode) {
|
||||
value(null, this.errorCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All the privileged actions.
|
||||
*/
|
||||
class ChromeActions {
|
||||
constructor(domWindow, contentDispositionFilename) {
|
||||
this.domWindow = domWindow;
|
||||
this.contentDispositionFilename = contentDispositionFilename;
|
||||
}
|
||||
|
||||
isInPrivateBrowsing() {
|
||||
return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
|
||||
}
|
||||
|
||||
download(data, sendResponse) {
|
||||
var self = this;
|
||||
var originalUrl = data.originalUrl;
|
||||
var blobUrl = data.blobUrl || originalUrl;
|
||||
// The data may not be downloaded so we need just retry getting the pdf with
|
||||
// the original url.
|
||||
var originalUri = NetUtil.newURI(originalUrl);
|
||||
var filename = data.filename;
|
||||
if (typeof filename !== "string" ||
|
||||
(!/\.pdf$/i.test(filename) && !data.isAttachment)) {
|
||||
filename = "document.pdf";
|
||||
}
|
||||
var blobUri = NetUtil.newURI(blobUrl);
|
||||
var extHelperAppSvc =
|
||||
Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
|
||||
getService(Ci.nsIExternalHelperAppService);
|
||||
|
||||
var docIsPrivate = this.isInPrivateBrowsing();
|
||||
var netChannel = NetUtil.newChannel({
|
||||
uri: blobUri,
|
||||
loadUsingSystemPrincipal: true,
|
||||
});
|
||||
if ("nsIPrivateBrowsingChannel" in Ci &&
|
||||
netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
netChannel.setPrivate(docIsPrivate);
|
||||
}
|
||||
NetUtil.asyncFetch(netChannel, function(aInputStream, aResult) {
|
||||
if (!Components.isSuccessCode(aResult)) {
|
||||
if (sendResponse) {
|
||||
sendResponse(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Create a nsIInputStreamChannel so we can set the url on the channel
|
||||
// so the filename will be correct.
|
||||
var channel = Cc["@mozilla.org/network/input-stream-channel;1"].
|
||||
createInstance(Ci.nsIInputStreamChannel);
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
try {
|
||||
// contentDisposition/contentDispositionFilename is readonly before FF18
|
||||
channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
|
||||
if (self.contentDispositionFilename && !data.isAttachment) {
|
||||
channel.contentDispositionFilename = self.contentDispositionFilename;
|
||||
} else {
|
||||
channel.contentDispositionFilename = filename;
|
||||
}
|
||||
} catch (e) {}
|
||||
channel.setURI(originalUri);
|
||||
channel.loadInfo = netChannel.loadInfo;
|
||||
channel.contentStream = aInputStream;
|
||||
if ("nsIPrivateBrowsingChannel" in Ci &&
|
||||
channel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
channel.setPrivate(docIsPrivate);
|
||||
}
|
||||
|
||||
var listener = {
|
||||
extListener: null,
|
||||
onStartRequest(aRequest, aContext) {
|
||||
var loadContext = self.domWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
this.extListener = extHelperAppSvc.doContent(
|
||||
(data.isAttachment ? "application/octet-stream" :
|
||||
"application/pdf"),
|
||||
aRequest, loadContext, false);
|
||||
this.extListener.onStartRequest(aRequest, aContext);
|
||||
},
|
||||
onStopRequest(aRequest, aContext, aStatusCode) {
|
||||
if (this.extListener) {
|
||||
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
|
||||
}
|
||||
// Notify the content code we're done downloading.
|
||||
if (sendResponse) {
|
||||
sendResponse(false);
|
||||
}
|
||||
},
|
||||
onDataAvailable(aRequest, aContext, aDataInputStream, aOffset, aCount) {
|
||||
this.extListener.onDataAvailable(aRequest, aContext, aDataInputStream,
|
||||
aOffset, aCount);
|
||||
}
|
||||
};
|
||||
|
||||
channel.asyncOpen2(listener);
|
||||
});
|
||||
}
|
||||
|
||||
getLocale() {
|
||||
return getStringPref("general.useragent.locale", "en-US");
|
||||
}
|
||||
|
||||
getStrings(data) {
|
||||
try {
|
||||
// Lazy initialization of localizedStrings
|
||||
if (!("localizedStrings" in this)) {
|
||||
this.localizedStrings = getLocalizedStrings("viewer.properties");
|
||||
}
|
||||
var result = this.localizedStrings[data];
|
||||
return JSON.stringify(result || null);
|
||||
} catch (e) {
|
||||
log("Unable to retrieve localized strings: " + e);
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
|
||||
supportsIntegratedFind() {
|
||||
// Integrated find is only supported when we're not in a frame
|
||||
if (this.domWindow.frameElement !== null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... and we are in a child process
|
||||
if (PdfjsContentUtils.isRemote) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ... or when the new find events code exists.
|
||||
var findBar = getFindBar(this.domWindow);
|
||||
return !!findBar && ("updateControlState" in findBar);
|
||||
}
|
||||
|
||||
supportsDocumentFonts() {
|
||||
var prefBrowser = getIntPref("browser.display.use_document_fonts", 1);
|
||||
var prefGfx = getBoolPref("gfx.downloadable_fonts.enabled", true);
|
||||
return (!!prefBrowser && prefGfx);
|
||||
}
|
||||
|
||||
supportsDocumentColors() {
|
||||
return getIntPref("browser.display.document_color_use", 0) !== 2;
|
||||
}
|
||||
|
||||
supportedMouseWheelZoomModifierKeys() {
|
||||
return {
|
||||
ctrlKey: getIntPref("mousewheel.with_control.action", 3) === 3,
|
||||
metaKey: getIntPref("mousewheel.with_meta.action", 1) === 3,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args - Object with `featureId` and `url` properties.
|
||||
* @param {function} sendResponse - Callback function.
|
||||
*/
|
||||
fallback(args, sendResponse) {
|
||||
var featureId = args.featureId;
|
||||
|
||||
var domWindow = this.domWindow;
|
||||
var strings = getLocalizedStrings("chrome.properties");
|
||||
var message;
|
||||
if (featureId === "forms") {
|
||||
message = getLocalizedString(strings, "unsupported_feature_forms");
|
||||
} else {
|
||||
message = getLocalizedString(strings, "unsupported_feature");
|
||||
}
|
||||
PdfjsContentUtils.displayWarning(domWindow, message,
|
||||
getLocalizedString(strings, "open_with_different_viewer"),
|
||||
getLocalizedString(strings, "open_with_different_viewer", "accessKey"));
|
||||
|
||||
let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
|
||||
winmm.addMessageListener("PDFJS:Child:fallbackDownload",
|
||||
function fallbackDownload(msg) {
|
||||
let data = msg.data;
|
||||
sendResponse(data.download);
|
||||
|
||||
winmm.removeMessageListener("PDFJS:Child:fallbackDownload",
|
||||
fallbackDownload);
|
||||
});
|
||||
}
|
||||
|
||||
updateFindControlState(data) {
|
||||
if (!this.supportsIntegratedFind()) {
|
||||
return;
|
||||
}
|
||||
// Verify what we're sending to the findbar.
|
||||
var result = data.result;
|
||||
var findPrevious = data.findPrevious;
|
||||
var findPreviousType = typeof findPrevious;
|
||||
if ((typeof result !== "number" || result < 0 || result > 3) ||
|
||||
(findPreviousType !== "undefined" && findPreviousType !== "boolean")) {
|
||||
return;
|
||||
}
|
||||
|
||||
var winmm = this.domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
|
||||
winmm.sendAsyncMessage("PDFJS:Parent:updateControlState", data);
|
||||
}
|
||||
|
||||
setPreferences(prefs, sendResponse) {
|
||||
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
|
||||
var numberOfPrefs = 0;
|
||||
var prefValue, prefName;
|
||||
for (var key in prefs) {
|
||||
if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
|
||||
log("setPreferences - Exceeded the maximum number of preferences " +
|
||||
"that is allowed to be set at once.");
|
||||
break;
|
||||
} else if (!defaultBranch.getPrefType(key)) {
|
||||
continue;
|
||||
}
|
||||
prefValue = prefs[key];
|
||||
prefName = (PREF_PREFIX + "." + key);
|
||||
switch (typeof prefValue) {
|
||||
case "boolean":
|
||||
PdfjsContentUtils.setBoolPref(prefName, prefValue);
|
||||
break;
|
||||
case "number":
|
||||
PdfjsContentUtils.setIntPref(prefName, prefValue);
|
||||
break;
|
||||
case "string":
|
||||
if (prefValue.length > MAX_STRING_PREF_LENGTH) {
|
||||
log("setPreferences - Exceeded the maximum allowed length " +
|
||||
"for a string preference.");
|
||||
} else {
|
||||
PdfjsContentUtils.setStringPref(prefName, prefValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sendResponse) {
|
||||
sendResponse(true);
|
||||
}
|
||||
}
|
||||
|
||||
getPreferences(prefs, sendResponse) {
|
||||
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
|
||||
var currentPrefs = {}, numberOfPrefs = 0;
|
||||
var prefValue, prefName;
|
||||
for (var key in prefs) {
|
||||
if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
|
||||
log("getPreferences - Exceeded the maximum number of preferences " +
|
||||
"that is allowed to be fetched at once.");
|
||||
break;
|
||||
} else if (!defaultBranch.getPrefType(key)) {
|
||||
continue;
|
||||
}
|
||||
prefValue = prefs[key];
|
||||
prefName = (PREF_PREFIX + "." + key);
|
||||
switch (typeof prefValue) {
|
||||
case "boolean":
|
||||
currentPrefs[key] = getBoolPref(prefName, prefValue);
|
||||
break;
|
||||
case "number":
|
||||
currentPrefs[key] = getIntPref(prefName, prefValue);
|
||||
break;
|
||||
case "string":
|
||||
currentPrefs[key] = getStringPref(prefName, prefValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let result = JSON.stringify(currentPrefs);
|
||||
if (sendResponse) {
|
||||
sendResponse(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for range requests.
|
||||
*/
|
||||
class RangedChromeActions extends ChromeActions {
|
||||
constructor(domWindow, contentDispositionFilename, originalRequest,
|
||||
rangeEnabled, streamingEnabled, dataListener) {
|
||||
|
||||
super(domWindow, contentDispositionFilename);
|
||||
this.dataListener = dataListener;
|
||||
this.originalRequest = originalRequest;
|
||||
this.rangeEnabled = rangeEnabled;
|
||||
this.streamingEnabled = streamingEnabled;
|
||||
|
||||
this.pdfUrl = originalRequest.URI.spec;
|
||||
this.contentLength = originalRequest.contentLength;
|
||||
|
||||
// Pass all the headers from the original request through
|
||||
var httpHeaderVisitor = {
|
||||
headers: {},
|
||||
visitHeader(aHeader, aValue) {
|
||||
if (aHeader === "Range") {
|
||||
// When loading the PDF from cache, firefox seems to set the Range
|
||||
// request header to fetch only the unfetched portions of the file
|
||||
// (e.g. 'Range: bytes=1024-'). However, we want to set this header
|
||||
// manually to fetch the PDF in chunks.
|
||||
return;
|
||||
}
|
||||
this.headers[aHeader] = aValue;
|
||||
}
|
||||
};
|
||||
if (originalRequest.visitRequestHeaders) {
|
||||
originalRequest.visitRequestHeaders(httpHeaderVisitor);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var xhr_onreadystatechange = function xhr_onreadystatechange() {
|
||||
if (this.readyState === 1) { // LOADING
|
||||
var netChannel = this.channel;
|
||||
if ("nsIPrivateBrowsingChannel" in Ci &&
|
||||
netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
var docIsPrivate = self.isInPrivateBrowsing();
|
||||
netChannel.setPrivate(docIsPrivate);
|
||||
}
|
||||
}
|
||||
};
|
||||
var getXhr = function getXhr() {
|
||||
const XMLHttpRequest = Components.Constructor(
|
||||
"@mozilla.org/xmlextras/xmlhttprequest;1");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("readystatechange", xhr_onreadystatechange);
|
||||
return xhr;
|
||||
};
|
||||
|
||||
this.networkManager = new NetworkManager(this.pdfUrl, {
|
||||
httpHeaders: httpHeaderVisitor.headers,
|
||||
getXhr,
|
||||
});
|
||||
|
||||
// If we are in range request mode, this means we manually issued xhr
|
||||
// requests, which we need to abort when we leave the page
|
||||
domWindow.addEventListener("unload", function unload(e) {
|
||||
domWindow.removeEventListener(e.type, unload);
|
||||
self.abortLoading();
|
||||
});
|
||||
}
|
||||
|
||||
initPassiveLoading() {
|
||||
var data;
|
||||
if (!this.streamingEnabled) {
|
||||
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
this.originalRequest = null;
|
||||
data = this.dataListener.readData();
|
||||
this.dataListener = null;
|
||||
} else {
|
||||
data = this.dataListener.readData();
|
||||
|
||||
this.dataListener.onprogress = (loaded, total) => {
|
||||
this.domWindow.postMessage({
|
||||
pdfjsLoadAction: "progressiveRead",
|
||||
loaded,
|
||||
total,
|
||||
chunk: this.dataListener.readData(),
|
||||
}, "*");
|
||||
};
|
||||
this.dataListener.oncomplete = () => {
|
||||
this.dataListener = null;
|
||||
};
|
||||
}
|
||||
|
||||
this.domWindow.postMessage({
|
||||
pdfjsLoadAction: "supportsRangedLoading",
|
||||
rangeEnabled: this.rangeEnabled,
|
||||
streamingEnabled: this.streamingEnabled,
|
||||
pdfUrl: this.pdfUrl,
|
||||
length: this.contentLength,
|
||||
data,
|
||||
}, "*");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
requestDataRange(args) {
|
||||
if (!this.rangeEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var begin = args.begin;
|
||||
var end = args.end;
|
||||
var domWindow = this.domWindow;
|
||||
// TODO(mack): Support error handler. We're not currently not handling
|
||||
// errors from chrome code for non-range requests, so this doesn't
|
||||
// seem high-pri
|
||||
this.networkManager.requestRange(begin, end, {
|
||||
onDone: function RangedChromeActions_onDone(aArgs) {
|
||||
domWindow.postMessage({
|
||||
pdfjsLoadAction: "range",
|
||||
begin: aArgs.begin,
|
||||
chunk: aArgs.chunk,
|
||||
}, "*");
|
||||
},
|
||||
onProgress: function RangedChromeActions_onProgress(evt) {
|
||||
domWindow.postMessage({
|
||||
pdfjsLoadAction: "rangeProgress",
|
||||
loaded: evt.loaded,
|
||||
}, "*");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
abortLoading() {
|
||||
this.networkManager.abortAllRequests();
|
||||
if (this.originalRequest) {
|
||||
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
this.originalRequest = null;
|
||||
}
|
||||
this.dataListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for a single network stream.
|
||||
*/
|
||||
class StandardChromeActions extends ChromeActions {
|
||||
constructor(domWindow, contentDispositionFilename, originalRequest,
|
||||
dataListener) {
|
||||
super(domWindow, contentDispositionFilename);
|
||||
this.originalRequest = originalRequest;
|
||||
this.dataListener = dataListener;
|
||||
}
|
||||
|
||||
initPassiveLoading() {
|
||||
if (!this.dataListener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.dataListener.onprogress = (loaded, total) => {
|
||||
this.domWindow.postMessage({
|
||||
pdfjsLoadAction: "progress",
|
||||
loaded,
|
||||
total,
|
||||
}, "*");
|
||||
};
|
||||
|
||||
this.dataListener.oncomplete = (data, errorCode) => {
|
||||
this.domWindow.postMessage({
|
||||
pdfjsLoadAction: "complete",
|
||||
data,
|
||||
errorCode,
|
||||
}, "*");
|
||||
|
||||
this.dataListener = null;
|
||||
this.originalRequest = null;
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
abortLoading() {
|
||||
if (this.originalRequest) {
|
||||
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
this.originalRequest = null;
|
||||
}
|
||||
this.dataListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener to trigger chrome privileged code.
|
||||
*/
|
||||
class RequestListener {
|
||||
constructor(actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
// Receive an event and synchronously or asynchronously responds.
|
||||
receive(event) {
|
||||
var message = event.target;
|
||||
var doc = message.ownerDocument;
|
||||
var action = event.detail.action;
|
||||
var data = event.detail.data;
|
||||
var sync = event.detail.sync;
|
||||
var actions = this.actions;
|
||||
if (!(action in actions)) {
|
||||
log("Unknown action: " + action);
|
||||
return;
|
||||
}
|
||||
var response;
|
||||
if (sync) {
|
||||
response = actions[action].call(this.actions, data);
|
||||
event.detail.response = Cu.cloneInto(response, doc.defaultView);
|
||||
} else {
|
||||
if (!event.detail.responseExpected) {
|
||||
doc.documentElement.removeChild(message);
|
||||
response = null;
|
||||
} else {
|
||||
response = function sendResponse(aResponse) {
|
||||
try {
|
||||
var listener = doc.createEvent("CustomEvent");
|
||||
let detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
|
||||
listener.initCustomEvent("pdf.js.response", true, false, detail);
|
||||
return message.dispatchEvent(listener);
|
||||
} catch (e) {
|
||||
// doc is no longer accessible because the requestor is already
|
||||
// gone. unloaded content cannot receive the response anyway.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
actions[action].call(this.actions, data, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards events from the eventElement to the contentWindow only if the
|
||||
* content window matches the currently selected browser window.
|
||||
*/
|
||||
class FindEventManager {
|
||||
constructor(contentWindow) {
|
||||
this.contentWindow = contentWindow;
|
||||
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
}
|
||||
|
||||
bind() {
|
||||
var unload = function(e) {
|
||||
this.unbind();
|
||||
this.contentWindow.removeEventListener(e.type, unload);
|
||||
}.bind(this);
|
||||
this.contentWindow.addEventListener("unload", unload);
|
||||
|
||||
// We cannot directly attach listeners to for the find events
|
||||
// since the FindBar is in the parent process. Instead we're
|
||||
// asking the PdfjsChromeUtils to do it for us and forward
|
||||
// all the find events to us.
|
||||
this.winmm.sendAsyncMessage("PDFJS:Parent:addEventListener");
|
||||
this.winmm.addMessageListener("PDFJS:Child:handleEvent", this);
|
||||
}
|
||||
|
||||
receiveMessage(msg) {
|
||||
var detail = msg.data.detail;
|
||||
var type = msg.data.type;
|
||||
var contentWindow = this.contentWindow;
|
||||
|
||||
detail = Cu.cloneInto(detail, contentWindow);
|
||||
var forward = contentWindow.document.createEvent("CustomEvent");
|
||||
forward.initCustomEvent(type, true, true, detail);
|
||||
contentWindow.dispatchEvent(forward);
|
||||
}
|
||||
|
||||
unbind() {
|
||||
this.winmm.sendAsyncMessage("PDFJS:Parent:removeEventListener");
|
||||
}
|
||||
}
|
||||
|
||||
function PdfStreamConverter() {
|
||||
}
|
||||
|
||||
PdfStreamConverter.prototype = {
|
||||
|
||||
// properties required for XPCOM registration:
|
||||
classID: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2291}"),
|
||||
classDescription: "pdf.js Component",
|
||||
contractID: "@mozilla.org/streamconv;1?from=application/pdf&to=*/*",
|
||||
|
||||
classID2: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2292}"),
|
||||
contractID2: "@mozilla.org/streamconv;1?from=application/pdf&to=text/html",
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsISupports,
|
||||
Ci.nsIStreamConverter,
|
||||
Ci.nsIStreamListener,
|
||||
Ci.nsIRequestObserver
|
||||
]),
|
||||
|
||||
/*
|
||||
* This component works as such:
|
||||
* 1. asyncConvertData stores the listener
|
||||
* 2. onStartRequest creates a new channel, streams the viewer
|
||||
* 3. If range requests are supported:
|
||||
* 3.1. Leave the request open until the viewer is ready to switch to
|
||||
* range requests.
|
||||
*
|
||||
* If range rquests are not supported:
|
||||
* 3.1. Read the stream as it's loaded in onDataAvailable to send
|
||||
* to the viewer
|
||||
*
|
||||
* The convert function just returns the stream, it's just the synchronous
|
||||
* version of asyncConvertData.
|
||||
*/
|
||||
|
||||
// nsIStreamConverter::convert
|
||||
convert(aFromStream, aFromType, aToType, aCtxt) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
// nsIStreamConverter::asyncConvertData
|
||||
asyncConvertData(aFromType, aToType, aListener, aCtxt) {
|
||||
// Store the listener passed to us
|
||||
this.listener = aListener;
|
||||
},
|
||||
|
||||
// nsIStreamListener::onDataAvailable
|
||||
onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||
if (!this.dataListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
var binaryStream = this.binaryStream;
|
||||
binaryStream.setInputStream(aInputStream);
|
||||
var chunk = binaryStream.readByteArray(aCount);
|
||||
this.dataListener.append(chunk);
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStartRequest
|
||||
onStartRequest(aRequest, aContext) {
|
||||
// Setup the request so we can use it below.
|
||||
var isHttpRequest = false;
|
||||
try {
|
||||
aRequest.QueryInterface(Ci.nsIHttpChannel);
|
||||
isHttpRequest = true;
|
||||
} catch (e) {}
|
||||
|
||||
var rangeRequest = false;
|
||||
var streamRequest = false;
|
||||
if (isHttpRequest) {
|
||||
var contentEncoding = "identity";
|
||||
try {
|
||||
contentEncoding = aRequest.getResponseHeader("Content-Encoding");
|
||||
} catch (e) {}
|
||||
|
||||
var acceptRanges;
|
||||
try {
|
||||
acceptRanges = aRequest.getResponseHeader("Accept-Ranges");
|
||||
} catch (e) {}
|
||||
|
||||
var hash = aRequest.URI.ref;
|
||||
var isPDFBugEnabled = getBoolPref(PREF_PREFIX + ".pdfBugEnabled", false);
|
||||
rangeRequest = contentEncoding === "identity" &&
|
||||
acceptRanges === "bytes" &&
|
||||
aRequest.contentLength >= 0 &&
|
||||
!getBoolPref(PREF_PREFIX + ".disableRange", false) &&
|
||||
(!isPDFBugEnabled ||
|
||||
hash.toLowerCase().indexOf("disablerange=true") < 0);
|
||||
streamRequest = contentEncoding === "identity" &&
|
||||
aRequest.contentLength >= 0 &&
|
||||
!getBoolPref(PREF_PREFIX + ".disableStream", false) &&
|
||||
(!isPDFBugEnabled ||
|
||||
hash.toLowerCase().indexOf("disablestream=true") < 0);
|
||||
}
|
||||
|
||||
aRequest.QueryInterface(Ci.nsIChannel);
|
||||
|
||||
aRequest.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
|
||||
var contentDispositionFilename;
|
||||
try {
|
||||
contentDispositionFilename = aRequest.contentDispositionFilename;
|
||||
} catch (e) {}
|
||||
|
||||
// Change the content type so we don't get stuck in a loop.
|
||||
aRequest.setProperty("contentType", aRequest.contentType);
|
||||
aRequest.contentType = "text/html";
|
||||
if (isHttpRequest) {
|
||||
// We trust PDF viewer, using no CSP
|
||||
aRequest.setResponseHeader("Content-Security-Policy", "", false);
|
||||
aRequest.setResponseHeader("Content-Security-Policy-Report-Only", "",
|
||||
false);
|
||||
// The viewer does not need to handle HTTP Refresh header.
|
||||
aRequest.setResponseHeader("Refresh", "", false);
|
||||
}
|
||||
|
||||
// Creating storage for PDF data
|
||||
var contentLength = aRequest.contentLength;
|
||||
this.dataListener = new PdfDataListener(contentLength);
|
||||
this.binaryStream = Cc["@mozilla.org/binaryinputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
|
||||
// Create a new channel that is viewer loaded as a resource.
|
||||
var channel = NetUtil.newChannel({
|
||||
uri: PDF_VIEWER_WEB_PAGE,
|
||||
loadUsingSystemPrincipal: true,
|
||||
});
|
||||
|
||||
var listener = this.listener;
|
||||
var dataListener = this.dataListener;
|
||||
// Proxy all the request observer calls, when it gets to onStopRequest
|
||||
// we can get the dom window. We also intentionally pass on the original
|
||||
// request(aRequest) below so we don't overwrite the original channel and
|
||||
// trigger an assertion.
|
||||
var proxy = {
|
||||
onStartRequest(request, context) {
|
||||
listener.onStartRequest(aRequest, aContext);
|
||||
},
|
||||
onDataAvailable(request, context, inputStream, offset, count) {
|
||||
listener.onDataAvailable(aRequest, aContext, inputStream,
|
||||
offset, count);
|
||||
},
|
||||
onStopRequest(request, context, statusCode) {
|
||||
// We get the DOM window here instead of before the request since it
|
||||
// may have changed during a redirect.
|
||||
var domWindow = getDOMWindow(channel);
|
||||
var actions;
|
||||
if (rangeRequest || streamRequest) {
|
||||
actions = new RangedChromeActions(
|
||||
domWindow, contentDispositionFilename, aRequest,
|
||||
rangeRequest, streamRequest, dataListener);
|
||||
} else {
|
||||
actions = new StandardChromeActions(
|
||||
domWindow, contentDispositionFilename, aRequest, dataListener);
|
||||
}
|
||||
var requestListener = new RequestListener(actions);
|
||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||
requestListener.receive(event);
|
||||
}, false, true);
|
||||
if (actions.supportsIntegratedFind()) {
|
||||
var findEventManager = new FindEventManager(domWindow);
|
||||
findEventManager.bind();
|
||||
}
|
||||
listener.onStopRequest(aRequest, aContext, statusCode);
|
||||
|
||||
if (domWindow.frameElement) {
|
||||
var isObjectEmbed = domWindow.frameElement.tagName !== "IFRAME" ||
|
||||
domWindow.frameElement.className === "previewPluginContentFrame";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Keep the URL the same so the browser sees it as the same.
|
||||
channel.originalURI = aRequest.URI;
|
||||
channel.loadGroup = aRequest.loadGroup;
|
||||
channel.loadInfo.originAttributes = aRequest.loadInfo.originAttributes;
|
||||
|
||||
// We can use the resource principal when data is fetched by the chrome,
|
||||
// e.g. useful for NoScript. Make make sure we reuse the origin attributes
|
||||
// from the request channel to keep isolation consistent.
|
||||
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
var uri = NetUtil.newURI(PDF_VIEWER_WEB_PAGE);
|
||||
var resourcePrincipal =
|
||||
ssm.createCodebasePrincipal(uri, aRequest.loadInfo.originAttributes);
|
||||
aRequest.owner = resourcePrincipal;
|
||||
|
||||
channel.asyncOpen2(proxy);
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStopRequest
|
||||
onStopRequest(aRequest, aContext, aStatusCode) {
|
||||
if (!this.dataListener) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (Components.isSuccessCode(aStatusCode)) {
|
||||
this.dataListener.finish();
|
||||
} else {
|
||||
this.dataListener.error(aStatusCode);
|
||||
}
|
||||
delete this.dataListener;
|
||||
delete this.binaryStream;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
/* Copyright 2012 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 Components, Services, XPCOMUtils */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PdfjsChromeUtils"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const PREF_PREFIX = "pdfjs";
|
||||
const PDF_CONTENT_TYPE = "application/pdf";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
|
||||
"@mozilla.org/mime;1",
|
||||
"nsIMIMEService");
|
||||
|
||||
var DEFAULT_PREFERENCES =
|
||||
{
|
||||
"showPreviousViewOnLoad": true,
|
||||
"defaultZoomValue": "",
|
||||
"sidebarViewOnLoad": 0,
|
||||
"enableHandToolOnLoad": false,
|
||||
"enableWebGL": false,
|
||||
"pdfBugEnabled": false,
|
||||
"disableRange": false,
|
||||
"disableStream": false,
|
||||
"disableAutoFetch": false,
|
||||
"disableFontFace": false,
|
||||
"disableTextLayer": false,
|
||||
"useOnlyCssZoom": false,
|
||||
"externalLinkTarget": 0,
|
||||
"enhanceTextSelection": false,
|
||||
"renderer": "canvas",
|
||||
"renderInteractiveForms": false,
|
||||
"enablePrintAutoRotate": false,
|
||||
"disablePageLabels": false
|
||||
}
|
||||
|
||||
|
||||
var PdfjsChromeUtils = {
|
||||
// For security purposes when running remote, we restrict preferences
|
||||
// content can access.
|
||||
_allowedPrefNames: Object.keys(DEFAULT_PREFERENCES),
|
||||
_ppmm: null,
|
||||
_mmg: null,
|
||||
|
||||
/*
|
||||
* Public API
|
||||
*/
|
||||
|
||||
init() {
|
||||
this._browsers = new WeakSet();
|
||||
if (!this._ppmm) {
|
||||
// global parent process message manager (PPMM)
|
||||
this._ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].
|
||||
getService(Ci.nsIMessageBroadcaster);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:clearUserPref", this);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:setIntPref", this);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:setBoolPref", this);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:setCharPref", this);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:setStringPref", this);
|
||||
this._ppmm.addMessageListener("PDFJS:Parent:isDefaultHandlerApp", this);
|
||||
|
||||
// global dom message manager (MMg)
|
||||
this._mmg = Cc["@mozilla.org/globalmessagemanager;1"].
|
||||
getService(Ci.nsIMessageListenerManager);
|
||||
this._mmg.addMessageListener("PDFJS:Parent:displayWarning", this);
|
||||
|
||||
this._mmg.addMessageListener("PDFJS:Parent:addEventListener", this);
|
||||
this._mmg.addMessageListener("PDFJS:Parent:removeEventListener", this);
|
||||
this._mmg.addMessageListener("PDFJS:Parent:updateControlState", this);
|
||||
|
||||
// observer to handle shutdown
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
}
|
||||
},
|
||||
|
||||
uninit() {
|
||||
if (this._ppmm) {
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:clearUserPref", this);
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:setIntPref", this);
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:setBoolPref", this);
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:setCharPref", this);
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:setStringPref", this);
|
||||
this._ppmm.removeMessageListener("PDFJS:Parent:isDefaultHandlerApp",
|
||||
this);
|
||||
|
||||
this._mmg.removeMessageListener("PDFJS:Parent:displayWarning", this);
|
||||
|
||||
this._mmg.removeMessageListener("PDFJS:Parent:addEventListener", this);
|
||||
this._mmg.removeMessageListener("PDFJS:Parent:removeEventListener", this);
|
||||
this._mmg.removeMessageListener("PDFJS:Parent:updateControlState", this);
|
||||
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
|
||||
this._mmg = null;
|
||||
this._ppmm = null;
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Called by the main module when preference changes are picked up
|
||||
* in the parent process. Observers don't propagate so we need to
|
||||
* instruct the child to refresh its configuration and (possibly)
|
||||
* the module's registration.
|
||||
*/
|
||||
notifyChildOfSettingsChange() {
|
||||
if (Services.appinfo.processType ===
|
||||
Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
|
||||
// XXX kinda bad, we want to get the parent process mm associated
|
||||
// with the content process. _ppmm is currently the global process
|
||||
// manager, which means this is going to fire to every child process
|
||||
// we have open. Unfortunately I can't find a way to get at that
|
||||
// process specific mm from js.
|
||||
this._ppmm.broadcastAsyncMessage("PDFJS:Child:refreshSettings", {});
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "quit-application") {
|
||||
this.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
switch (aMsg.name) {
|
||||
case "PDFJS:Parent:clearUserPref":
|
||||
this._clearUserPref(aMsg.data.name);
|
||||
break;
|
||||
case "PDFJS:Parent:setIntPref":
|
||||
this._setIntPref(aMsg.data.name, aMsg.data.value);
|
||||
break;
|
||||
case "PDFJS:Parent:setBoolPref":
|
||||
this._setBoolPref(aMsg.data.name, aMsg.data.value);
|
||||
break;
|
||||
case "PDFJS:Parent:setCharPref":
|
||||
this._setCharPref(aMsg.data.name, aMsg.data.value);
|
||||
break;
|
||||
case "PDFJS:Parent:setStringPref":
|
||||
this._setStringPref(aMsg.data.name, aMsg.data.value);
|
||||
break;
|
||||
case "PDFJS:Parent:isDefaultHandlerApp":
|
||||
return this.isDefaultHandlerApp();
|
||||
case "PDFJS:Parent:displayWarning":
|
||||
this._displayWarning(aMsg);
|
||||
break;
|
||||
|
||||
case "PDFJS:Parent:updateControlState":
|
||||
return this._updateControlState(aMsg);
|
||||
case "PDFJS:Parent:addEventListener":
|
||||
return this._addEventListener(aMsg);
|
||||
case "PDFJS:Parent:removeEventListener":
|
||||
return this._removeEventListener(aMsg);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/*
|
||||
* Internal
|
||||
*/
|
||||
|
||||
_findbarFromMessage(aMsg) {
|
||||
let browser = aMsg.target;
|
||||
let tabbrowser = browser.getTabBrowser();
|
||||
let tab = tabbrowser.getTabForBrowser(browser);
|
||||
return tabbrowser.getFindBar(tab);
|
||||
},
|
||||
|
||||
_updateControlState(aMsg) {
|
||||
let data = aMsg.data;
|
||||
this._findbarFromMessage(aMsg)
|
||||
.updateControlState(data.result, data.findPrevious);
|
||||
},
|
||||
|
||||
handleEvent(aEvent) {
|
||||
// To avoid forwarding the message as a CPOW, create a structured cloneable
|
||||
// version of the event for both performance, and ease of usage, reasons.
|
||||
let type = aEvent.type;
|
||||
let detail = {
|
||||
query: aEvent.detail.query,
|
||||
caseSensitive: aEvent.detail.caseSensitive,
|
||||
highlightAll: aEvent.detail.highlightAll,
|
||||
findPrevious: aEvent.detail.findPrevious
|
||||
};
|
||||
|
||||
let browser = aEvent.currentTarget.browser;
|
||||
if (!this._browsers.has(browser)) {
|
||||
throw new Error("FindEventManager was not bound " +
|
||||
"for the current browser.");
|
||||
}
|
||||
// Only forward the events if the current browser is a registered browser.
|
||||
let mm = browser.messageManager;
|
||||
mm.sendAsyncMessage("PDFJS:Child:handleEvent", { type, detail, });
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
_types: ["find",
|
||||
"findagain",
|
||||
"findhighlightallchange",
|
||||
"findcasesensitivitychange"],
|
||||
|
||||
_addEventListener(aMsg) {
|
||||
let browser = aMsg.target;
|
||||
if (this._browsers.has(browser)) {
|
||||
throw new Error("FindEventManager was bound 2nd time " +
|
||||
"without unbinding it first.");
|
||||
}
|
||||
|
||||
// Since this jsm is global, we need to store all the browsers
|
||||
// we have to forward the messages for.
|
||||
this._browsers.add(browser);
|
||||
|
||||
// And we need to start listening to find events.
|
||||
for (var i = 0; i < this._types.length; i++) {
|
||||
var type = this._types[i];
|
||||
this._findbarFromMessage(aMsg)
|
||||
.addEventListener(type, this, true);
|
||||
}
|
||||
},
|
||||
|
||||
_removeEventListener(aMsg) {
|
||||
let browser = aMsg.target;
|
||||
if (!this._browsers.has(browser)) {
|
||||
throw new Error("FindEventManager was unbound without binding it first.");
|
||||
}
|
||||
|
||||
this._browsers.delete(browser);
|
||||
|
||||
// No reason to listen to find events any longer.
|
||||
for (var i = 0; i < this._types.length; i++) {
|
||||
var type = this._types[i];
|
||||
this._findbarFromMessage(aMsg)
|
||||
.removeEventListener(type, this, true);
|
||||
}
|
||||
},
|
||||
|
||||
_ensurePreferenceAllowed(aPrefName) {
|
||||
let unPrefixedName = aPrefName.split(PREF_PREFIX + ".");
|
||||
if (unPrefixedName[0] !== "" ||
|
||||
this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
|
||||
let msg = "\"" + aPrefName + "\" " +
|
||||
"can't be accessed from content. See PdfjsChromeUtils.";
|
||||
throw new Error(msg);
|
||||
}
|
||||
},
|
||||
|
||||
_clearUserPref(aPrefName) {
|
||||
this._ensurePreferenceAllowed(aPrefName);
|
||||
Services.prefs.clearUserPref(aPrefName);
|
||||
},
|
||||
|
||||
_setIntPref(aPrefName, aPrefValue) {
|
||||
this._ensurePreferenceAllowed(aPrefName);
|
||||
Services.prefs.setIntPref(aPrefName, aPrefValue);
|
||||
},
|
||||
|
||||
_setBoolPref(aPrefName, aPrefValue) {
|
||||
this._ensurePreferenceAllowed(aPrefName);
|
||||
Services.prefs.setBoolPref(aPrefName, aPrefValue);
|
||||
},
|
||||
|
||||
_setCharPref(aPrefName, aPrefValue) {
|
||||
this._ensurePreferenceAllowed(aPrefName);
|
||||
Services.prefs.setCharPref(aPrefName, aPrefValue);
|
||||
},
|
||||
|
||||
_setStringPref(aPrefName, aPrefValue) {
|
||||
this._ensurePreferenceAllowed(aPrefName);
|
||||
let str = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
str.data = aPrefValue;
|
||||
Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
|
||||
},
|
||||
|
||||
/*
|
||||
* Svc.mime doesn't have profile information in the child, so
|
||||
* we bounce this pdfjs enabled configuration check over to the
|
||||
* parent.
|
||||
*/
|
||||
isDefaultHandlerApp() {
|
||||
var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
|
||||
return (!handlerInfo.alwaysAskBeforeHandling &&
|
||||
handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
|
||||
},
|
||||
|
||||
/*
|
||||
* Display a notification warning when the renderer isn't sure
|
||||
* a pdf displayed correctly.
|
||||
*/
|
||||
_displayWarning(aMsg) {
|
||||
let data = aMsg.data;
|
||||
let browser = aMsg.target;
|
||||
|
||||
let tabbrowser = browser.getTabBrowser();
|
||||
let notificationBox = tabbrowser.getNotificationBox(browser);
|
||||
|
||||
// Flag so we don't send the message twice, since if the user clicks
|
||||
// "open with different viewer" both the button callback and
|
||||
// eventCallback will be called.
|
||||
let messageSent = false;
|
||||
function sendMessage(download) {
|
||||
let mm = browser.messageManager;
|
||||
mm.sendAsyncMessage("PDFJS:Child:fallbackDownload", { download, });
|
||||
}
|
||||
let buttons = [{
|
||||
label: data.label,
|
||||
accessKey: data.accessKey,
|
||||
callback() {
|
||||
messageSent = true;
|
||||
sendMessage(true);
|
||||
}
|
||||
}];
|
||||
notificationBox.appendNotification(data.message, "pdfjs-fallback", null,
|
||||
notificationBox.PRIORITY_INFO_LOW,
|
||||
buttons,
|
||||
function eventsCallback(eventType) {
|
||||
// Currently there is only one event "removed" but if there are any other
|
||||
// added in the future we still only care about removed at the moment.
|
||||
if (eventType !== "removed") {
|
||||
return;
|
||||
}
|
||||
// Don't send a response again if we already responded when the button was
|
||||
// clicked.
|
||||
if (messageSent) {
|
||||
return;
|
||||
}
|
||||
sendMessage(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/* Copyright 2012 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 Components, Services, XPCOMUtils */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PdfjsContentUtils"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var PdfjsContentUtils = {
|
||||
_mm: null,
|
||||
|
||||
/*
|
||||
* Public API
|
||||
*/
|
||||
|
||||
get isRemote() {
|
||||
return (Services.appinfo.processType ===
|
||||
Services.appinfo.PROCESS_TYPE_CONTENT);
|
||||
},
|
||||
|
||||
init() {
|
||||
// child *process* mm, or when loaded into the parent for in-content
|
||||
// support the psuedo child process mm 'child PPMM'.
|
||||
if (!this._mm) {
|
||||
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].
|
||||
getService(Ci.nsISyncMessageSender);
|
||||
this._mm.addMessageListener("PDFJS:Child:refreshSettings", this);
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
}
|
||||
},
|
||||
|
||||
uninit() {
|
||||
if (this._mm) {
|
||||
this._mm.removeMessageListener("PDFJS:Child:refreshSettings", this);
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
}
|
||||
this._mm = null;
|
||||
},
|
||||
|
||||
/*
|
||||
* prefs utilities - the child does not have write access to prefs.
|
||||
* note, the pref names here are cross-checked against a list of
|
||||
* approved pdfjs prefs in chrome utils.
|
||||
*/
|
||||
|
||||
clearUserPref(aPrefName) {
|
||||
this._mm.sendSyncMessage("PDFJS:Parent:clearUserPref", {
|
||||
name: aPrefName
|
||||
});
|
||||
},
|
||||
|
||||
setIntPref(aPrefName, aPrefValue) {
|
||||
this._mm.sendSyncMessage("PDFJS:Parent:setIntPref", {
|
||||
name: aPrefName,
|
||||
value: aPrefValue
|
||||
});
|
||||
},
|
||||
|
||||
setBoolPref(aPrefName, aPrefValue) {
|
||||
this._mm.sendSyncMessage("PDFJS:Parent:setBoolPref", {
|
||||
name: aPrefName,
|
||||
value: aPrefValue
|
||||
});
|
||||
},
|
||||
|
||||
setCharPref(aPrefName, aPrefValue) {
|
||||
this._mm.sendSyncMessage("PDFJS:Parent:setCharPref", {
|
||||
name: aPrefName,
|
||||
value: aPrefValue
|
||||
});
|
||||
},
|
||||
|
||||
setStringPref(aPrefName, aPrefValue) {
|
||||
this._mm.sendSyncMessage("PDFJS:Parent:setStringPref", {
|
||||
name: aPrefName,
|
||||
value: aPrefValue
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Forwards default app query to the parent where we check various
|
||||
* handler app settings only available in the parent process.
|
||||
*/
|
||||
isDefaultHandlerApp() {
|
||||
return this._mm.sendSyncMessage("PDFJS:Parent:isDefaultHandlerApp")[0];
|
||||
},
|
||||
|
||||
/*
|
||||
* Request the display of a notification warning in the associated window
|
||||
* when the renderer isn't sure a pdf displayed correctly.
|
||||
*/
|
||||
displayWarning(aWindow, aMessage, aLabel, aAccessKey) {
|
||||
// the child's dom frame mm associated with the window.
|
||||
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
winmm.sendAsyncMessage("PDFJS:Parent:displayWarning", {
|
||||
message: aMessage,
|
||||
label: aLabel,
|
||||
accessKey: aAccessKey,
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "quit-application") {
|
||||
this.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
switch (aMsg.name) {
|
||||
case "PDFJS:Child:refreshSettings":
|
||||
// Only react to this if we are remote.
|
||||
if (Services.appinfo.processType ===
|
||||
Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let jsm = "resource://pdf.js/PdfJs.jsm";
|
||||
let pdfjs = Components.utils.import(jsm, {}).PdfJs;
|
||||
pdfjs.updateRegistration();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
7226
application/palemoon/extensions/pdfjs/content/build/pdf.js
Normal file
7226
application/palemoon/extensions/pdfjs/content/build/pdf.js
Normal file
File diff suppressed because it is too large
Load diff
49140
application/palemoon/extensions/pdfjs/content/build/pdf.worker.js
vendored
Normal file
49140
application/palemoon/extensions/pdfjs/content/build/pdf.worker.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,34 @@
|
|||
/* 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 Components, PdfjsContentUtils, PdfJs, Services */
|
||||
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* pdfjschildbootstrap.js loads into the content process to take care of
|
||||
* initializing our built-in version of pdfjs when running remote.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://pdf.js/PdfJs.jsm");
|
||||
Components.utils.import("resource://pdf.js/PdfjsContentUtils.jsm");
|
||||
|
||||
// init content utils shim pdfjs will use to access privileged apis.
|
||||
PdfjsContentUtils.init();
|
||||
|
||||
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
// register various pdfjs factories that hook us into content loading.
|
||||
PdfJs.updateRegistration();
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
àRCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSEáCNS2-H
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
àRCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSEá ETen-B5-H` ^
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
|||
àRCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSE!!<21>º]aX!!]`<60>21<32>> <09>p<0B>z<EFBFBD>$]‚<06>"R‚d<E2809A>-Uƒ7<C692>*„
4„%<25>+ „Z „{<7B>/…%…<<3C>9K…b<E280A6>1]†.<2E>"‡‰`]‡,<2C>"]ˆ
|
||||
<EFBFBD>"]ˆh<CB86>"]‰F<E280B0>"]Š$<24>"]‹<02>"]‹`<60>"]Œ><3E>"]<5D><1C>"]<5D>z<EFBFBD>"]ŽX<C5BD>"]<5D>6<EFBFBD>"]<5D><14>"]<5D>r<EFBFBD>"]‘P<E28098>"]’.<2E>"]“<0C>"]“j<E2809C>"]”H<E2809D>"]•&<26>"]–<04>"]–b<E28093>"]—@<40>"]˜<1E>"]˜|<7C>"]™Z<E284A2>"]š8<C5A1>"]›<16>"]›t<E280BA>"]œR<C593>"]<5D>0<EFBFBD>"]ž<0E>"]žl<C5BE>"]ŸJ<C5B8>"] (<28>"]¡<06>"]¡d<C2A1>"]¢B<C2A2>"]£ <20>"X£~<7E>']¤W<C2A4>"]¥5<C2A5>"]¦<13>"]¦q<C2A6>"]§O<C2A7>"]¨-<2D>"]©<0B>"]©i<C2A9>"]ªG<C2AA>"]«%<25>"]¬<03>"]¬a<C2AC>"]?<3F>"]®<1D>"]®{<7B>"]¯Y<C2AF>"]°7<C2B0>"]±<15>"]±s<C2B1>"]²Q<C2B2>"]³/<2F>"]´
<0A>"]´k<C2B4>"]µI<C2B5>"]¶'<27>"]·<05>"]·c<C2B7>"]¸A<C2B8>"]¹<1F>"]¹}<7D>"]º[<5B>"]»9
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue