Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* Copyright 2012 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
16 var EXPORTED_SYMBOLS = ["PdfJs"];
18 const Cc = Components.classes;
19 const Ci = Components.interfaces;
20 const Cr = Components.results;
21 const Cm = Components.manager;
22 const Cu = Components.utils;
24 const PREF_PREFIX = 'pdfjs';
25 const PREF_DISABLED = PREF_PREFIX + '.disabled';
26 const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion';
27 const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
28 const PREF_PREVIOUS_ASK = PREF_PREFIX + '.previousHandler.alwaysAskBeforeHandling';
29 const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types';
30 const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
31 const TOPIC_PLUGINS_LIST_UPDATED = "plugins-list-updated";
32 const TOPIC_PLUGIN_INFO_UPDATED = "plugin-info-updated";
33 const PDF_CONTENT_TYPE = 'application/pdf';
35 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
36 Cu.import('resource://gre/modules/Services.jsm');
38 let Svc = {};
39 XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
40 '@mozilla.org/mime;1',
41 'nsIMIMEService');
42 XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
43 '@mozilla.org/plugin/host;1',
44 'nsIPluginHost');
46 function getBoolPref(aPref, aDefaultValue) {
47 try {
48 return Services.prefs.getBoolPref(aPref);
49 } catch (ex) {
50 return aDefaultValue;
51 }
52 }
54 function getIntPref(aPref, aDefaultValue) {
55 try {
56 return Services.prefs.getIntPref(aPref);
57 } catch (ex) {
58 return aDefaultValue;
59 }
60 }
62 function initializeDefaultPreferences() {
64 var DEFAULT_PREFERENCES = {
65 showPreviousViewOnLoad: true,
66 defaultZoomValue: '',
67 ifAvailableShowOutlineOnLoad: false,
68 enableHandToolOnLoad: false,
69 enableWebGL: false
70 };
73 var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
74 var defaultValue;
75 for (var key in DEFAULT_PREFERENCES) {
76 defaultValue = DEFAULT_PREFERENCES[key];
77 switch (typeof defaultValue) {
78 case 'boolean':
79 defaultBranch.setBoolPref(key, defaultValue);
80 break;
81 case 'number':
82 defaultBranch.setIntPref(key, defaultValue);
83 break;
84 case 'string':
85 defaultBranch.setCharPref(key, defaultValue);
86 break;
87 }
88 }
89 }
91 // Register/unregister a constructor as a factory.
92 function Factory() {}
93 Factory.prototype = {
94 register: function register(targetConstructor) {
95 var proto = targetConstructor.prototype;
96 this._classID = proto.classID;
98 var factory = XPCOMUtils._getFactory(targetConstructor);
99 this._factory = factory;
101 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
102 registrar.registerFactory(proto.classID, proto.classDescription,
103 proto.contractID, factory);
104 },
106 unregister: function unregister() {
107 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
108 registrar.unregisterFactory(this._classID, this._factory);
109 this._factory = null;
110 }
111 };
113 let PdfJs = {
114 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
115 _registered: false,
117 init: function init() {
118 if (!getBoolPref(PREF_DISABLED, true)) {
119 this._migrate();
120 }
122 if (this.enabled)
123 this._ensureRegistered();
124 else
125 this._ensureUnregistered();
127 // Listen for when pdf.js is completely disabled or a different pdf handler
128 // is chosen.
129 Services.prefs.addObserver(PREF_DISABLED, this, false);
130 Services.prefs.addObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
131 Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
132 Services.obs.addObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
133 Services.obs.addObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
135 initializeDefaultPreferences();
136 },
138 _migrate: function migrate() {
139 const VERSION = 2;
140 var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
141 if (currentVersion >= VERSION) {
142 return;
143 }
144 // Make pdf.js the default pdf viewer on the first migration.
145 if (currentVersion < 1) {
146 this._becomeHandler();
147 }
148 if (currentVersion < 2) {
149 // cleaning up of unused database preference (see #3994)
150 Services.prefs.clearUserPref(PREF_PREFIX + '.database');
151 }
152 Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
153 },
155 _becomeHandler: function _becomeHandler() {
156 let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
157 let prefs = Services.prefs;
158 if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
159 handlerInfo.preferredAction !== false) {
160 // Store the previous settings of preferredAction and
161 // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
162 // would turn pdf.js off.
163 prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
164 prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
165 }
167 let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
168 getService(Ci.nsIHandlerService);
170 // Change and save mime handler settings.
171 handlerInfo.alwaysAskBeforeHandling = false;
172 handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
173 handlerService.store(handlerInfo);
175 // Also disable any plugins for pdfs.
176 var stringTypes = '';
177 var types = [];
178 if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
179 stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
180 }
181 if (stringTypes !== '') {
182 types = stringTypes.split(',');
183 }
185 if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
186 types.push(PDF_CONTENT_TYPE);
187 }
188 prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(','));
190 // Update the category manager in case the plugins are already loaded.
191 let categoryManager = Cc["@mozilla.org/categorymanager;1"];
192 categoryManager.getService(Ci.nsICategoryManager).
193 deleteCategoryEntry("Gecko-Content-Viewers",
194 PDF_CONTENT_TYPE,
195 false);
196 },
198 // nsIObserver
199 observe: function observe(aSubject, aTopic, aData) {
200 if (this.enabled)
201 this._ensureRegistered();
202 else
203 this._ensureUnregistered();
204 },
206 /**
207 * pdf.js is only enabled if it is both selected as the pdf viewer and if the
208 * global switch enabling it is true.
209 * @return {boolean} Wether or not it's enabled.
210 */
211 get enabled() {
212 var disabled = getBoolPref(PREF_DISABLED, true);
213 if (disabled) {
214 return false;
215 }
217 // the 'application/pdf' handler is selected as internal?
218 var handlerInfo = Svc.mime
219 .getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
220 if (handlerInfo.alwaysAskBeforeHandling ||
221 handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally) {
222 return false;
223 }
225 // Check if we have disabled plugin handling of 'application/pdf' in prefs
226 if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
227 let disabledPluginTypes =
228 Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(',');
229 if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
230 return true;
231 }
232 }
234 // Check if there is an enabled pdf plugin.
235 // Note: this check is performed last because getPluginTags() triggers costly
236 // plugin list initialization (bug 881575)
237 let tags = Cc["@mozilla.org/plugin/host;1"].
238 getService(Ci.nsIPluginHost).
239 getPluginTags();
240 let enabledPluginFound = tags.some(function(tag) {
241 if (tag.disabled) {
242 return false;
243 }
244 let mimeTypes = tag.getMimeTypes();
245 return mimeTypes.some(function(mimeType) {
246 return mimeType === PDF_CONTENT_TYPE;
247 });
248 });
250 // Use pdf.js if pdf plugin is not present or disabled
251 return !enabledPluginFound;
252 },
254 _ensureRegistered: function _ensureRegistered() {
255 if (this._registered)
256 return;
258 this._pdfStreamConverterFactory = new Factory();
259 Cu.import('resource://pdf.js/PdfStreamConverter.jsm');
260 this._pdfStreamConverterFactory.register(PdfStreamConverter);
262 this._pdfRedirectorFactory = new Factory();
263 Cu.import('resource://pdf.js/PdfRedirector.jsm');
264 this._pdfRedirectorFactory.register(PdfRedirector);
266 Svc.pluginHost.registerPlayPreviewMimeType(PDF_CONTENT_TYPE, true,
267 'data:application/x-moz-playpreview-pdfjs;,');
269 this._registered = true;
270 },
272 _ensureUnregistered: function _ensureUnregistered() {
273 if (!this._registered)
274 return;
276 this._pdfStreamConverterFactory.unregister();
277 Cu.unload('resource://pdf.js/PdfStreamConverter.jsm');
278 delete this._pdfStreamConverterFactory;
280 this._pdfRedirectorFactory.unregister();
281 Cu.unload('resource://pdf.js/PdfRedirector.jsm');
282 delete this._pdfRedirectorFactory;
284 Svc.pluginHost.unregisterPlayPreviewMimeType(PDF_CONTENT_TYPE);
286 this._registered = false;
287 }
288 };