diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js
index db84e8254..38d9af92b 100644
--- a/extensions/firefox/components/PdfStreamConverter.js
+++ b/extensions/firefox/components/PdfStreamConverter.js
@@ -16,7 +16,7 @@
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
- dump, NetworkManager, PdfJsTelemetry */
+ dump, NetworkManager, PdfJsTelemetry, DEFAULT_PREFERENCES */
'use strict';
@@ -33,12 +33,16 @@ const PDF_CONTENT_TYPE = 'application/pdf';
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
const MAX_DATABASE_LENGTH = 4096;
+const MAX_STRING_PREF_LENGTH = 4096;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
Cu.import('resource://pdf.js/network.js');
+// Load the default preferences.
+Cu.import('resource://pdf.js/default_preferences.js');
+
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
'resource://gre/modules/PrivateBrowsingUtils.jsm');
@@ -58,6 +62,10 @@ function getChromeWindow(domWindow) {
return containingBrowser.ownerDocument.defaultView;
}
+function setBoolPref(pref, value) {
+ Services.prefs.setBoolPref(pref, value);
+}
+
function getBoolPref(pref, def) {
try {
return Services.prefs.getBoolPref(pref);
@@ -66,6 +74,10 @@ function getBoolPref(pref, def) {
}
}
+function setIntPref(pref, value) {
+ Services.prefs.setIntPref(pref, value);
+}
+
function getIntPref(pref, def) {
try {
return Services.prefs.getIntPref(pref);
@@ -431,6 +443,62 @@ ChromeActions.prototype = {
}
getChromeWindow(this.domWindow).gFindBar
.updateControlState(result, findPrevious);
+ },
+ setPreferences: function(prefs) {
+ var prefValue, defaultValue, prefName, prefType, defaultType;
+
+ for (var key in DEFAULT_PREFERENCES) {
+ prefValue = prefs[key];
+ defaultValue = DEFAULT_PREFERENCES[key];
+ prefName = (PREF_PREFIX + '.' + key);
+
+ if (!prefValue || prefValue === defaultValue) {
+ Services.prefs.clearUserPref(prefName);
+ } else {
+ prefType = typeof prefValue;
+ defaultType = typeof defaultValue;
+
+ if (prefType !== defaultType) {
+ continue;
+ }
+ switch (defaultType) {
+ case 'boolean':
+ setBoolPref(prefName, prefValue);
+ break;
+ case 'number':
+ setIntPref(prefName, prefValue);
+ break;
+ case 'string':
+ // Protect against adding arbitrarily long strings in about:config.
+ if (prefValue.length <= MAX_STRING_PREF_LENGTH) {
+ setStringPref(prefName, prefValue);
+ }
+ break;
+ }
+ }
+ }
+ },
+ getPreferences: function() {
+ var currentPrefs = {};
+ var defaultValue, prefName;
+
+ for (var key in DEFAULT_PREFERENCES) {
+ defaultValue = DEFAULT_PREFERENCES[key];
+ prefName = (PREF_PREFIX + '.' + key);
+
+ switch (typeof defaultValue) {
+ case 'boolean':
+ currentPrefs[key] = getBoolPref(prefName, defaultValue);
+ break;
+ case 'number':
+ currentPrefs[key] = getIntPref(prefName, defaultValue);
+ break;
+ case 'string':
+ currentPrefs[key] = getStringPref(prefName, defaultValue);
+ break;
+ }
+ }
+ return JSON.stringify(currentPrefs);
}
};
diff --git a/make.js b/make.js
index ca6c77181..6b5b84985 100644
--- a/make.js
+++ b/make.js
@@ -436,7 +436,8 @@ target.firefox = function() {
copy: [
[COMMON_WEB_FILES, FIREFOX_BUILD_CONTENT_DIR + '/web'],
[FIREFOX_EXTENSION_DIR + 'tools/l10n.js',
- FIREFOX_BUILD_CONTENT_DIR + '/web']
+ FIREFOX_BUILD_CONTENT_DIR + '/web'],
+ ['web/default_preferences.js', FIREFOX_BUILD_CONTENT_DIR]
],
preprocess: [
[COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'],
@@ -551,7 +552,8 @@ target.mozcentral = function() {
defines: defines,
copy: [
[COMMON_WEB_FILES, MOZCENTRAL_CONTENT_DIR + '/web'],
- ['extensions/firefox/tools/l10n.js', MOZCENTRAL_CONTENT_DIR + '/web']
+ ['extensions/firefox/tools/l10n.js', MOZCENTRAL_CONTENT_DIR + '/web'],
+ ['web/default_preferences.js', MOZCENTRAL_CONTENT_DIR]
],
preprocess: [
[COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'],
diff --git a/web/default_preferences.js b/web/default_preferences.js
new file mode 100644
index 000000000..498907751
--- /dev/null
+++ b/web/default_preferences.js
@@ -0,0 +1,27 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2013 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* globals */
+
+'use strict';
+
+var EXPORTED_SYMBOLS = ['DEFAULT_PREFERENCES'];
+
+var DEFAULT_PREFERENCES = {
+ showPreviousViewOnLoad: true,
+ defaultZoomValue: '',
+ ifAvailableShowOutlineOnLoad: false
+};
diff --git a/web/firefoxcom.js b/web/firefoxcom.js
index 488fcd4dd..6826097f2 100644
--- a/web/firefoxcom.js
+++ b/web/firefoxcom.js
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/* globals Preferences, PDFJS */
'use strict';
@@ -102,3 +103,14 @@ var DownloadManager = (function DownloadManagerClosure() {
return DownloadManager;
})();
+
+Preferences.prototype.writeToStorage = function(prefObj) {
+ FirefoxCom.requestSync('setPreferences', prefObj);
+};
+
+Preferences.prototype.readFromStorage = function() {
+ var readFromStoragePromise = new PDFJS.Promise();
+ var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences'));
+ readFromStoragePromise.resolve(readPrefs);
+ return readFromStoragePromise;
+};
diff --git a/web/preferences.js b/web/preferences.js
new file mode 100644
index 000000000..2e3625e5e
--- /dev/null
+++ b/web/preferences.js
@@ -0,0 +1,126 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2013 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* globals DEFAULT_PREFERENCES, PDFJS, isLocalStorageEnabled */
+
+'use strict';
+
+//#include default_preferences.js
+
+var Preferences = (function PreferencesClosure() {
+ function Preferences() {
+ this.prefs = {};
+ this.initializedPromise = this.readFromStorage().then(function(prefObj) {
+ if (prefObj) {
+ this.prefs = prefObj;
+ }
+ }.bind(this));
+ }
+
+ Preferences.prototype = {
+ writeToStorage: function Preferences_writeToStorage(prefObj) {
+ return;
+ },
+
+ readFromStorage: function Preferences_readFromStorage() {
+ var readFromStoragePromise = new PDFJS.Promise();
+ return readFromStoragePromise;
+ },
+
+ reset: function Preferences_reset() {
+ if (this.initializedPromise.isResolved) {
+ this.prefs = {};
+ this.writeToStorage(this.prefs);
+ }
+ },
+
+ set: function Preferences_set(name, value) {
+ if (!this.initializedPromise.isResolved) {
+ return;
+ } else if (DEFAULT_PREFERENCES[name] === undefined) {
+ console.error('Preferences_set: \'' + name + '\' is undefined.');
+ return;
+ } else if (value === undefined) {
+ console.error('Preferences_set: no value is specified.');
+ return;
+ }
+ var valueType = typeof value;
+ var defaultType = typeof DEFAULT_PREFERENCES[name];
+
+ if (valueType !== defaultType) {
+ if (valueType === 'number' && defaultType === 'string') {
+ value = value.toString();
+ } else {
+ console.error('Preferences_set: \'' + value + '\' is a \"' +
+ valueType + '\", expected a \"' + defaultType + '\".');
+ return;
+ }
+ }
+ this.prefs[name] = value;
+ this.writeToStorage(this.prefs);
+ },
+
+ get: function Preferences_get(name) {
+ var defaultPref = DEFAULT_PREFERENCES[name];
+
+ if (defaultPref === undefined) {
+ console.error('Preferences_get: \'' + name + '\' is undefined.');
+ return;
+ } else if (this.initializedPromise.isResolved) {
+ var pref = this.prefs[name];
+
+ if (pref !== undefined) {
+ return pref;
+ }
+ }
+ return defaultPref;
+ }
+ };
+
+ return Preferences;
+})();
+
+//#if B2G
+//Preferences.prototype.writeToStorage = function(prefObj) {
+// asyncStorage.setItem('preferences', JSON.stringify(prefObj));
+//};
+//
+//Preferences.prototype.readFromStorage = function() {
+// var readFromStoragePromise = new PDFJS.Promise();
+// asyncStorage.getItem('preferences', function(prefString) {
+// var readPrefs = JSON.parse(prefString);
+// readFromStoragePromise.resolve(readPrefs);
+// });
+// return readFromStoragePromise;
+//};
+//#endif
+
+//#if !(FIREFOX || MOZCENTRAL || B2G)
+Preferences.prototype.writeToStorage = function(prefObj) {
+ if (isLocalStorageEnabled) {
+ localStorage.setItem('preferences', JSON.stringify(prefObj));
+ }
+};
+
+Preferences.prototype.readFromStorage = function() {
+ var readFromStoragePromise = new PDFJS.Promise();
+ if (isLocalStorageEnabled) {
+ var readPrefs = JSON.parse(localStorage.getItem('preferences'));
+ readFromStoragePromise.resolve(readPrefs);
+ }
+ return readFromStoragePromise;
+};
+//#endif
diff --git a/web/ui_utils.js b/web/ui_utils.js
index 0a85321a5..8b2c1f121 100644
--- a/web/ui_utils.js
+++ b/web/ui_utils.js
@@ -240,3 +240,16 @@ var Cache = function cacheCache(size) {
};
};
+//#if !(FIREFOX || MOZCENTRAL || B2G)
+var isLocalStorageEnabled = (function isLocalStorageEnabledClosure() {
+ // Feature test as per http://diveintohtml5.info/storage.html
+ // The additional localStorage call is to get around a FF quirk, see
+ // bug #495747 in bugzilla
+ try {
+ return ('localStorage' in window && window['localStorage'] !== null &&
+ localStorage);
+ } catch (e) {
+ return false;
+ }
+})();
+//#endif
diff --git a/web/viewer.html b/web/viewer.html
index 4dc8e69c5..148489cab 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -62,6 +62,8 @@ limitations under the License.
+
+
diff --git a/web/viewer.js b/web/viewer.js
index a5b2a4675..ff98f28da 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -16,8 +16,8 @@
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
- getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
- PDFHistory, Settings, PageView, ThumbnailView, noContextMenuHandler,
+ getFileName, scrollIntoView, getPDFFileNameFromURL, PDFHistory,
+ Preferences, Settings, PageView, ThumbnailView, noContextMenuHandler,
SecondaryToolbar, PasswordPrompt, PresentationMode */
'use strict';
@@ -63,6 +63,7 @@ PDFJS.imageResourcesPath = './images/';
var mozL10n = document.mozL10n || document.webL10n;
//#include ui_utils.js
+//#include preferences.js
//#if !(FIREFOX || MOZCENTRAL || B2G)
//#include mozPrintCallback_polyfill.js
@@ -235,6 +236,10 @@ var PDFView = {
case 'auto':
scale = Math.min(MAX_AUTO_SCALE, pageWidthScale);
break;
+ default:
+ console.error('pdfViewSetScale: \'' + value +
+ '\' is an unknown zoom value.');
+ return;
}
}
this.currentScaleValue = value;
@@ -814,6 +819,7 @@ var PDFView = {
mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
document.getElementById('pageNumber').max = pagesCount;
+ var prefs = PDFView.prefs = new Preferences();
PDFView.documentFingerprint = id;
var store = PDFView.store = new Settings(id);
@@ -858,17 +864,24 @@ var PDFView = {
});
});
+ var prefsPromise = prefs.initializedPromise;
var storePromise = store.initializedPromise;
- PDFJS.Promise.all([firstPagePromise, storePromise]).then(function() {
+ PDFJS.Promise.all([firstPagePromise, prefsPromise, storePromise]).
+ then(function() {
+ var showPreviousViewOnLoad = prefs.get('showPreviousViewOnLoad');
+ var defaultZoomValue = prefs.get('defaultZoomValue');
+
var storedHash = null;
- if (store.get('exists', false)) {
+ if (showPreviousViewOnLoad && store.get('exists', false)) {
var pageNum = store.get('page', '1');
- var zoom = store.get('zoom', PDFView.currentScale);
+ var zoom = defaultZoomValue || store.get('zoom', PDFView.currentScale);
var left = store.get('scrollLeft', '0');
var top = store.get('scrollTop', '0');
storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' +
left + ',' + top;
+ } else if (defaultZoomValue) {
+ storedHash = 'page=1&zoom=' + defaultZoomValue;
}
// Initialize the browsing history.
PDFHistory.initialize(self.documentFingerprint);
@@ -920,6 +933,13 @@ var PDFView = {
pdfDocument.getOutline().then(function(outline) {
self.outline = new DocumentOutlineView(outline);
document.getElementById('viewOutline').disabled = !outline;
+
+ if (outline && prefs.get('ifAvailableShowOutlineOnLoad')) {
+ if (!self.sidebarOpen) {
+ document.getElementById('sidebarToggle').click();
+ }
+ self.switchSidebarView('outline');
+ }
});
});