Bug 995431 - Update pdf.js to version 1.0.21. r=yury, r=Mossop, f=RyanVM

This commit is contained in:
Brendan Dahl
2014-04-14 16:09:04 -05:00
parent 66b14f4f7d
commit ddbc1a38f0
11 changed files with 3600 additions and 2461 deletions

View File

@@ -1,4 +1,4 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 0.8.1334 Current extension version is: 1.0.21

View File

@@ -64,7 +64,9 @@ function initializeDefaultPreferences() {
var DEFAULT_PREFERENCES = { var DEFAULT_PREFERENCES = {
showPreviousViewOnLoad: true, showPreviousViewOnLoad: true,
defaultZoomValue: '', defaultZoomValue: '',
ifAvailableShowOutlineOnLoad: false ifAvailableShowOutlineOnLoad: false,
enableHandToolOnLoad: false,
enableWebGL: false
}; };
@@ -134,15 +136,19 @@ let PdfJs = {
}, },
_migrate: function migrate() { _migrate: function migrate() {
const VERSION = 1; const VERSION = 2;
var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0); var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
if (currentVersion >= VERSION) { if (currentVersion >= VERSION) {
return; return;
} }
// Make pdf.js the default pdf viewer on the first migration. // Make pdf.js the default pdf viewer on the first migration.
if (currentVersion < 2) { if (currentVersion < 1) {
this._becomeHandler(); 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); Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
}, },

View File

@@ -32,7 +32,6 @@ const PDFJS_EVENT_ID = 'pdf.js.message';
const PDF_CONTENT_TYPE = 'application/pdf'; const PDF_CONTENT_TYPE = 'application/pdf';
const PREF_PREFIX = 'pdfjs'; const PREF_PREFIX = 'pdfjs';
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html'; const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
const MAX_DATABASE_LENGTH = 4096;
const MAX_NUMBER_OF_PREFS = 50; const MAX_NUMBER_OF_PREFS = 50;
const MAX_STRING_PREF_LENGTH = 128; const MAX_STRING_PREF_LENGTH = 128;
@@ -295,19 +294,6 @@ ChromeActions.prototype = {
channel.asyncOpen(listener, null); channel.asyncOpen(listener, null);
}); });
}, },
setDatabase: function(data) {
if (this.isInPrivateBrowsing())
return;
// Protect against something sending tons of data to setDatabase.
if (data.length > MAX_DATABASE_LENGTH)
return;
setStringPref(PREF_PREFIX + '.database', data);
},
getDatabase: function() {
if (this.isInPrivateBrowsing())
return '{}';
return getStringPref(PREF_PREFIX + '.database', '{}');
},
getLocale: function() { getLocale: function() {
return getStringPref('general.useragent.locale', 'en-US'); return getStringPref('general.useragent.locale', 'en-US');
}, },
@@ -452,7 +438,7 @@ ChromeActions.prototype = {
getChromeWindow(this.domWindow).gFindBar getChromeWindow(this.domWindow).gFindBar
.updateControlState(result, findPrevious); .updateControlState(result, findPrevious);
}, },
setPreferences: function(prefs) { setPreferences: function(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.'); var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var numberOfPrefs = 0; var numberOfPrefs = 0;
var prefValue, prefName; var prefValue, prefName;
@@ -483,8 +469,11 @@ ChromeActions.prototype = {
break; break;
} }
} }
if (sendResponse) {
sendResponse(true);
}
}, },
getPreferences: function(prefs) { getPreferences: function(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.'); var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var currentPrefs = {}, numberOfPrefs = 0; var currentPrefs = {}, numberOfPrefs = 0;
var prefValue, prefName; var prefValue, prefName;
@@ -510,7 +499,11 @@ ChromeActions.prototype = {
break; break;
} }
} }
return JSON.stringify(currentPrefs); if (sendResponse) {
sendResponse(JSON.stringify(currentPrefs));
} else {
return JSON.stringify(currentPrefs);
}
} }
}; };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -211,10 +211,11 @@ var StepperManager = (function StepperManagerClosure() {
return stepper; return stepper;
}, },
selectStepper: function selectStepper(pageIndex, selectPanel) { selectStepper: function selectStepper(pageIndex, selectPanel) {
var i;
if (selectPanel) { if (selectPanel) {
this.manager.selectPanel(this); this.manager.selectPanel(this);
} }
for (var i = 0; i < steppers.length; ++i) { for (i = 0; i < steppers.length; ++i) {
var stepper = steppers[i]; var stepper = steppers[i];
if (stepper.pageIndex == pageIndex) { if (stepper.pageIndex == pageIndex) {
stepper.panel.removeAttribute('hidden'); stepper.panel.removeAttribute('hidden');
@@ -223,7 +224,7 @@ var StepperManager = (function StepperManagerClosure() {
} }
} }
var options = stepperChooser.options; var options = stepperChooser.options;
for (var i = 0; i < options.length; ++i) { for (i = 0; i < options.length; ++i) {
var option = options[i]; var option = options[i];
option.selected = option.value == pageIndex; option.selected = option.value == pageIndex;
} }
@@ -344,7 +345,7 @@ var Stepper = (function StepperClosure() {
var self = this; var self = this;
var chunk = document.createDocumentFragment(); var chunk = document.createDocumentFragment();
var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT, var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT,
operatorList.fnArray.length); operatorList.fnArray.length);
for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) { for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) {
var line = c('tr'); var line = c('tr');
line.className = 'line'; line.className = 'line';
@@ -369,7 +370,7 @@ var Stepper = (function StepperClosure() {
if (fn in glyphCommands) { if (fn in glyphCommands) {
var glyphIndex = glyphCommands[fn]; var glyphIndex = glyphCommands[fn];
var glyphs = args[glyphIndex]; var glyphs = args[glyphIndex];
var decArgs = args.slice(); decArgs = args.slice();
var newArg; var newArg;
if (fn === 'showSpacedText') { if (fn === 'showSpacedText') {
newArg = []; newArg = [];

View File

@@ -67,10 +67,12 @@ select {
:-moz-full-screen .page { :-moz-full-screen .page {
margin-bottom: 100%; margin-bottom: 100%;
border: 0;
} }
:fullscreen .page { :fullscreen .page {
margin-bottom: 100%; margin-bottom: 100%;
border: 0;
} }
:-moz-full-screen a:not(.internalLink) { :-moz-full-screen a:not(.internalLink) {
@@ -1187,7 +1189,6 @@ canvas {
.textLayer > div { .textLayer > div {
color: transparent; color: transparent;
position: absolute; position: absolute;
line-height: 1;
white-space: pre; white-space: pre;
cursor: text; cursor: text;
} }
@@ -1305,6 +1306,9 @@ canvas {
background-color: hsla(0,0%,0%,.2); background-color: hsla(0,0%,0%,.2);
z-index: 10000; z-index: 10000;
} }
#overlayContainer > * {
overflow: auto;
}
#promptContainer { #promptContainer {
display: table-cell; display: table-cell;

View File

@@ -309,49 +309,99 @@ var Cache = function cacheCache(size) {
var DEFAULT_PREFERENCES = { var DEFAULT_PREFERENCES = {
showPreviousViewOnLoad: true, showPreviousViewOnLoad: true,
defaultZoomValue: '', defaultZoomValue: '',
ifAvailableShowOutlineOnLoad: false ifAvailableShowOutlineOnLoad: false,
enableHandToolOnLoad: false,
enableWebGL: false
}; };
var Preferences = (function PreferencesClosure() { /**
function Preferences() { * Preferences - Utility for storing persistent settings.
this.prefs = {}; * Used for settings that should be applied to all opened documents,
this.isInitializedPromiseResolved = false; * or every time the viewer is loaded.
this.initializedPromise = this.readFromStorage(DEFAULT_PREFERENCES).then( */
function(prefObj) { var Preferences = {
this.isInitializedPromiseResolved = true; prefs: Object.create(DEFAULT_PREFERENCES),
isInitializedPromiseResolved: false,
initializedPromise: null,
/**
* Initialize and fetch the current preference values from storage.
* @return {Promise} A promise that is resolved when the preferences
* have been initialized.
*/
initialize: function preferencesInitialize() {
return this.initializedPromise =
this._readFromStorage(DEFAULT_PREFERENCES).then(function(prefObj) {
this.isInitializedPromiseResolved = true;
if (prefObj) {
this.prefs = prefObj;
}
}.bind(this));
},
/**
* Stub function for writing preferences to storage.
* NOTE: This should be overridden by a build-specific function defined below.
* @param {Object} prefObj The preferences that should be written to storage.
* @return {Promise} A promise that is resolved when the preference values
* have been written.
*/
_writeToStorage: function preferences_writeToStorage(prefObj) {
return Promise.resolve();
},
/**
* Stub function for reading preferences from storage.
* NOTE: This should be overridden by a build-specific function defined below.
* @param {Object} prefObj The preferences that should be read from storage.
* @return {Promise} A promise that is resolved with an {Object} containing
* the preferences that have been read.
*/
_readFromStorage: function preferences_readFromStorage(prefObj) {
return Promise.resolve();
},
/**
* Reset the preferences to their default values and update storage.
* @return {Promise} A promise that is resolved when the preference values
* have been reset.
*/
reset: function preferencesReset() {
return this.initializedPromise.then(function() {
this.prefs = Object.create(DEFAULT_PREFERENCES);
return this._writeToStorage(DEFAULT_PREFERENCES);
}.bind(this));
},
/**
* Replace the current preference values with the ones from storage.
* @return {Promise} A promise that is resolved when the preference values
* have been updated.
*/
reload: function preferencesReload() {
return this.initializedPromise.then(function () {
this._readFromStorage(DEFAULT_PREFERENCES).then(function(prefObj) {
if (prefObj) { if (prefObj) {
this.prefs = prefObj; this.prefs = prefObj;
} }
}.bind(this)); }.bind(this));
} }.bind(this));
},
Preferences.prototype = { /**
writeToStorage: function Preferences_writeToStorage(prefObj) { * Set the value of a preference.
return; * @param {string} name The name of the preference that should be changed.
}, * @param {boolean|number|string} value The new value of the preference.
* @return {Promise} A promise that is resolved when the value has been set,
readFromStorage: function Preferences_readFromStorage(prefObj) { * provided that the preference exists and the types match.
var readFromStoragePromise = Promise.resolve(); */
return readFromStoragePromise; set: function preferencesSet(name, value) {
}, return this.initializedPromise.then(function () {
if (DEFAULT_PREFERENCES[name] === undefined) {
reset: function Preferences_reset() { throw new Error('preferencesSet: \'' + name + '\' is undefined.');
if (this.isInitializedPromiseResolved) {
this.prefs = {};
this.writeToStorage(DEFAULT_PREFERENCES);
}
},
set: function Preferences_set(name, value) {
if (!this.isInitializedPromiseResolved) {
return;
} else if (DEFAULT_PREFERENCES[name] === undefined) {
console.error('Preferences_set: \'' + name + '\' is undefined.');
return;
} else if (value === undefined) { } else if (value === undefined) {
console.error('Preferences_set: no value is specified.'); throw new Error('preferencesSet: no value is specified.');
return;
} }
var valueType = typeof value; var valueType = typeof value;
var defaultType = typeof DEFAULT_PREFERENCES[name]; var defaultType = typeof DEFAULT_PREFERENCES[name];
@@ -360,40 +410,43 @@ var Preferences = (function PreferencesClosure() {
if (valueType === 'number' && defaultType === 'string') { if (valueType === 'number' && defaultType === 'string') {
value = value.toString(); value = value.toString();
} else { } else {
console.error('Preferences_set: \'' + value + '\' is a \"' + throw new Error('Preferences_set: \'' + value + '\' is a \"' +
valueType + '\", expected a \"' + defaultType + '\".'); valueType + '\", expected \"' + defaultType + '\".');
return;
} }
} else { } else {
if (valueType === 'number' && (value | 0) !== value) { if (valueType === 'number' && (value | 0) !== value) {
console.error('Preferences_set: \'' + value + throw new Error('Preferences_set: \'' + value +
'\' must be an \"integer\".'); '\' must be an \"integer\".');
return;
} }
} }
this.prefs[name] = value; this.prefs[name] = value;
this.writeToStorage(this.prefs); return this._writeToStorage(this.prefs);
}, }.bind(this));
},
get: function Preferences_get(name) { /**
var defaultPref = DEFAULT_PREFERENCES[name]; * Get the value of a preference.
* @param {string} name The name of the preference whose value is requested.
* @return {Promise} A promise that is resolved with a {boolean|number|string}
* containing the value of the preference.
*/
get: function preferencesGet(name) {
return this.initializedPromise.then(function () {
var defaultValue = DEFAULT_PREFERENCES[name];
if (defaultPref === undefined) { if (defaultValue === undefined) {
console.error('Preferences_get: \'' + name + '\' is undefined.'); throw new Error('preferencesGet: \'' + name + '\' is undefined.');
return; } else {
} else if (this.isInitializedPromiseResolved) { var prefValue = this.prefs[name];
var pref = this.prefs[name];
if (pref !== undefined) { if (prefValue !== undefined) {
return pref; return prefValue;
} }
} }
return defaultPref; return defaultValue;
} }.bind(this));
}; }
};
return Preferences;
})();
@@ -488,17 +541,19 @@ var DownloadManager = (function DownloadManagerClosure() {
return DownloadManager; return DownloadManager;
})(); })();
Preferences.prototype.writeToStorage = function(prefObj) { Preferences._writeToStorage = function (prefObj) {
FirefoxCom.requestSync('setPreferences', prefObj); return new Promise(function (resolve) {
FirefoxCom.request('setPreferences', prefObj, resolve);
});
}; };
Preferences.prototype.readFromStorage = function(prefObj) { Preferences._readFromStorage = function (prefObj) {
var readFromStoragePromise = new Promise(function (resolve) { return new Promise(function (resolve) {
var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences', FirefoxCom.request('getPreferences', prefObj, function (prefStr) {
prefObj)); var readPrefs = JSON.parse(prefStr);
resolve(readPrefs); resolve(readPrefs);
});
}); });
return readFromStoragePromise;
}; };
@@ -513,7 +568,7 @@ var currentPageNumber = 1;
* *
* The way that the view parameters are stored depends on how PDF.js is built, * The way that the view parameters are stored depends on how PDF.js is built,
* for 'node make <flag>' the following cases exist: * for 'node make <flag>' the following cases exist:
* - FIREFOX or MOZCENTRAL - uses about:config. * - FIREFOX or MOZCENTRAL - uses sessionStorage.
* - B2G - uses asyncStorage. * - B2G - uses asyncStorage.
* - GENERIC or CHROME - uses localStorage, if it is available. * - GENERIC or CHROME - uses localStorage, if it is available.
*/ */
@@ -533,7 +588,7 @@ var ViewHistory = (function ViewHistoryClosure() {
}).bind(this); }).bind(this);
resolvePromise(FirefoxCom.requestSync('getDatabase', null)); resolvePromise(sessionStorage.getItem('pdfjsHistory'));
} }
@@ -570,7 +625,7 @@ var ViewHistory = (function ViewHistoryClosure() {
var database = JSON.stringify(this.database); var database = JSON.stringify(this.database);
FirefoxCom.requestSync('setDatabase', database); sessionStorage.setItem('pdfjsHistory',database);
}, },
@@ -871,11 +926,12 @@ var PDFFindController = {
var self = this; var self = this;
function extractPageText(pageIndex) { function extractPageText(pageIndex) {
self.pdfPageSource.pages[pageIndex].getTextContent().then( self.pdfPageSource.pages[pageIndex].getTextContent().then(
function textContentResolved(bidiTexts) { function textContentResolved(textContent) {
var textItems = textContent.items;
var str = ''; var str = '';
for (var i = 0; i < bidiTexts.length; i++) { for (var i = 0; i < textItems.length; i++) {
str += bidiTexts[i].str; str += textItems[i].str;
} }
// Store the pageContent as a string. // Store the pageContent as a string.
@@ -1778,11 +1834,9 @@ var PresentationMode = {
// Presentation Mode, by waiting until fullscreen mode is disabled. // Presentation Mode, by waiting until fullscreen mode is disabled.
// Note: This is only necessary in non-Mozilla browsers. // Note: This is only necessary in non-Mozilla browsers.
setTimeout(function exitPresentationModeTimeout() { setTimeout(function exitPresentationModeTimeout() {
this.active = false;
PDFView.setScale(this.args.previousScale); PDFView.setScale(this.args.previousScale);
PDFView.page = page; PDFView.page = page;
// Keep Presentation Mode active until the page is scrolled into view,
// to prevent issues in non-Mozilla browsers.
this.active = false;
this.args = null; this.args = null;
}.bind(this), 0); }.bind(this), 0);
@@ -2110,8 +2164,15 @@ var HandTool = {
}); });
if (toggleHandTool) { if (toggleHandTool) {
toggleHandTool.addEventListener('click', this.toggle.bind(this), false); toggleHandTool.addEventListener('click', this.toggle.bind(this), false);
window.addEventListener('localized', function (evt) {
Preferences.get('enableHandToolOnLoad').then(function (prefValue) {
if (prefValue) {
this.handTool.activate();
}
}.bind(this));
}.bind(this));
} }
// TODO: Read global prefs and call this.handTool.activate() if needed.
}, },
toggle: function handToolToggle() { toggle: function handToolToggle() {
@@ -2177,6 +2238,10 @@ var DocumentProperties = {
options.closeButton.addEventListener('click', this.hide.bind(this)); options.closeButton.addEventListener('click', this.hide.bind(this));
} }
this.dataAvailablePromise = new Promise(function (resolve) {
this.resolveDataAvailable = resolve;
}.bind(this));
// Bind the event listener for the Esc key (to close the dialog). // Bind the event listener for the Esc key (to close the dialog).
window.addEventListener('keydown', window.addEventListener('keydown',
function (e) { function (e) {
@@ -2187,44 +2252,51 @@ var DocumentProperties = {
}, },
getProperties: function documentPropertiesGetProperties() { getProperties: function documentPropertiesGetProperties() {
var self = this; if (!this.visible) {
// If the dialog was closed before dataAvailablePromise was resolved,
// don't bother updating the properties.
return;
}
// Get the file name. // Get the file name.
this.fileName = getPDFFileNameFromURL(PDFView.url); this.fileName = getPDFFileNameFromURL(PDFView.url);
// Get the file size. // Get the file size.
PDFView.pdfDocument.getDownloadInfo().then(function(data) { PDFView.pdfDocument.getDownloadInfo().then(function(data) {
self.setFileSize(data.length); this.setFileSize(data.length);
}); this.updateUI(this.fileSizeField, this.fileSize);
}.bind(this));
// Get the other document properties. // Get the other document properties.
PDFView.pdfDocument.getMetadata().then(function(data) { PDFView.pdfDocument.getMetadata().then(function(data) {
var fields = [ var fields = [
{ field: self.fileNameField, content: self.fileName }, { field: this.fileNameField, content: this.fileName },
{ field: self.fileSizeField, content: self.fileSize }, // The fileSize field is updated once getDownloadInfo is resolved.
{ field: self.titleField, content: data.info.Title }, { field: this.titleField, content: data.info.Title },
{ field: self.authorField, content: data.info.Author }, { field: this.authorField, content: data.info.Author },
{ field: self.subjectField, content: data.info.Subject }, { field: this.subjectField, content: data.info.Subject },
{ field: self.keywordsField, content: data.info.Keywords }, { field: this.keywordsField, content: data.info.Keywords },
{ field: self.creationDateField, { field: this.creationDateField,
content: self.parseDate(data.info.CreationDate) }, content: this.parseDate(data.info.CreationDate) },
{ field: self.modificationDateField, { field: this.modificationDateField,
content: self.parseDate(data.info.ModDate) }, content: this.parseDate(data.info.ModDate) },
{ field: self.creatorField, content: data.info.Creator }, { field: this.creatorField, content: data.info.Creator },
{ field: self.producerField, content: data.info.Producer }, { field: this.producerField, content: data.info.Producer },
{ field: self.versionField, content: data.info.PDFFormatVersion }, { field: this.versionField, content: data.info.PDFFormatVersion },
{ field: self.pageCountField, content: PDFView.pdfDocument.numPages } { field: this.pageCountField, content: PDFView.pdfDocument.numPages }
]; ];
// Show the properties in the dialog. // Show the properties in the dialog.
for (var item in fields) { for (var item in fields) {
var element = fields[item]; var element = fields[item];
if (element.field && element.content !== undefined && this.updateUI(element.field, element.content);
element.content !== '') {
element.field.textContent = element.content;
}
} }
}); }.bind(this));
},
updateUI: function documentPropertiesUpdateUI(field, content) {
if (field && content !== undefined && content !== '') {
field.textContent = content;
}
}, },
setFileSize: function documentPropertiesSetFileSize(fileSize) { setFileSize: function documentPropertiesSetFileSize(fileSize) {
@@ -2249,7 +2321,10 @@ var DocumentProperties = {
this.visible = true; this.visible = true;
this.overlayContainer.classList.remove('hidden'); this.overlayContainer.classList.remove('hidden');
this.overlayContainer.lastElementChild.classList.remove('hidden'); this.overlayContainer.lastElementChild.classList.remove('hidden');
this.getProperties();
this.dataAvailablePromise.then(function () {
this.getProperties();
}.bind(this));
}, },
hide: function documentPropertiesClose() { hide: function documentPropertiesClose() {
@@ -2347,6 +2422,8 @@ var PDFView = {
this.watchScroll(thumbnailContainer, this.thumbnailViewScroll, this.watchScroll(thumbnailContainer, this.thumbnailViewScroll,
this.renderHighestPriority.bind(this)); this.renderHighestPriority.bind(this));
Preferences.initialize();
PDFFindBar.initialize({ PDFFindBar.initialize({
bar: document.getElementById('findbar'), bar: document.getElementById('findbar'),
toggleButton: document.getElementById('viewFind'), toggleButton: document.getElementById('viewFind'),
@@ -2421,10 +2498,20 @@ var PDFView = {
pageCountField: document.getElementById('pageCountField') pageCountField: document.getElementById('pageCountField')
}); });
this.initialized = true;
container.addEventListener('scroll', function() { container.addEventListener('scroll', function() {
self.lastScroll = Date.now(); self.lastScroll = Date.now();
}, false); }, false);
var initializedPromise = Promise.all([
Preferences.get('enableWebGL').then(function (value) {
PDFJS.disableWebGL = !value;
})
// TODO move more preferences and other async stuff here
]);
return initializedPromise.then(function () {
PDFView.initialized = true;
});
}, },
getPage: function pdfViewGetPage(n) { getPage: function pdfViewGetPage(n) {
@@ -2490,9 +2577,11 @@ var PDFView = {
if (!currentPage) { if (!currentPage) {
return; return;
} }
var pageWidthScale = (this.container.clientWidth - SCROLLBAR_PADDING) / var hPadding = PresentationMode.active ? 0 : SCROLLBAR_PADDING;
var vPadding = PresentationMode.active ? 0 : VERTICAL_PADDING;
var pageWidthScale = (this.container.clientWidth - hPadding) /
currentPage.width * currentPage.scale; currentPage.width * currentPage.scale;
var pageHeightScale = (this.container.clientHeight - VERTICAL_PADDING) / var pageHeightScale = (this.container.clientHeight - vPadding) /
currentPage.height * currentPage.scale; currentPage.height * currentPage.scale;
switch (value) { switch (value) {
case 'page-actual': case 'page-actual':
@@ -2774,6 +2863,9 @@ var PDFView = {
pdfDataRangeTransport, args) { pdfDataRangeTransport, args) {
if (this.pdfDocument) { if (this.pdfDocument) {
this.close(); this.close();
// Reload the preferences if a document was previously opened.
Preferences.reload();
} }
var parameters = {password: password}; var parameters = {password: password};
@@ -2791,6 +2883,8 @@ var PDFView = {
var self = this; var self = this;
self.loading = true; self.loading = true;
self.downloadComplete = false;
var passwordNeeded = function passwordNeeded(updatePassword, reason) { var passwordNeeded = function passwordNeeded(updatePassword, reason) {
PasswordPrompt.updatePassword = updatePassword; PasswordPrompt.updatePassword = updatePassword;
PasswordPrompt.reason = reason; PasswordPrompt.reason = reason;
@@ -2813,13 +2907,13 @@ var PDFView = {
if (exception && exception.name === 'InvalidPDFException') { if (exception && exception.name === 'InvalidPDFException') {
// change error message also for other builds // change error message also for other builds
var loadingErrorMessage = mozL10n.get('invalid_file_error', null, loadingErrorMessage = mozL10n.get('invalid_file_error', null,
'Invalid or corrupted PDF file.'); 'Invalid or corrupted PDF file.');
} }
if (exception && exception.name === 'MissingPDFException') { if (exception && exception.name === 'MissingPDFException') {
// special message for missing PDF's // special message for missing PDF's
var loadingErrorMessage = mozL10n.get('missing_file_error', null, loadingErrorMessage = mozL10n.get('missing_file_error', null,
'Missing PDF file.'); 'Missing PDF file.');
} }
@@ -2834,7 +2928,7 @@ var PDFView = {
}, },
download: function pdfViewDownload() { download: function pdfViewDownload() {
function noData() { function downloadByUrl() {
downloadManager.downloadUrl(url, filename); downloadManager.downloadUrl(url, filename);
} }
@@ -2848,7 +2942,12 @@ var PDFView = {
}; };
if (!this.pdfDocument) { // the PDF is not ready yet if (!this.pdfDocument) { // the PDF is not ready yet
noData(); downloadByUrl();
return;
}
if (!this.downloadComplete) { // the PDF is still downloading
downloadByUrl();
return; return;
} }
@@ -2857,8 +2956,8 @@ var PDFView = {
var blob = PDFJS.createBlob(data, 'application/pdf'); var blob = PDFJS.createBlob(data, 'application/pdf');
downloadManager.download(blob, url, filename); downloadManager.download(blob, url, filename);
}, },
noData // Error occurred try downloading with just the url. downloadByUrl // Error occurred try downloading with just the url.
).then(null, noData); ).then(null, downloadByUrl);
}, },
fallback: function pdfViewFallback(featureId) { fallback: function pdfViewFallback(featureId) {
@@ -3026,7 +3125,10 @@ var PDFView = {
this.pdfDocument = pdfDocument; this.pdfDocument = pdfDocument;
pdfDocument.getDownloadInfo().then(function() { DocumentProperties.resolveDataAvailable();
var downloadedPromise = pdfDocument.getDownloadInfo().then(function() {
self.downloadComplete = true;
PDFView.loadingBar.hide(); PDFView.loadingBar.hide();
var outerContainer = document.getElementById('outerContainer'); var outerContainer = document.getElementById('outerContainer');
outerContainer.classList.remove('loadingInProgress'); outerContainer.classList.remove('loadingInProgress');
@@ -3039,7 +3141,6 @@ var PDFView = {
mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}'); mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
document.getElementById('pageNumber').max = pagesCount; document.getElementById('pageNumber').max = pagesCount;
var prefs = PDFView.prefs = new Preferences();
PDFView.documentFingerprint = id; PDFView.documentFingerprint = id;
var store = PDFView.store = new ViewHistory(id); var store = PDFView.store = new ViewHistory(id);
@@ -3101,22 +3202,35 @@ var PDFView = {
} }
}); });
var event = document.createEvent('CustomEvent'); downloadedPromise.then(function () {
event.initCustomEvent('documentload', true, true, {}); var event = document.createEvent('CustomEvent');
window.dispatchEvent(event); event.initCustomEvent('documentload', true, true, {});
window.dispatchEvent(event);
});
PDFView.loadingBar.setWidth(container); PDFView.loadingBar.setWidth(container);
PDFFindController.resolveFirstPage(); PDFFindController.resolveFirstPage();
// Initialize the browsing history.
PDFHistory.initialize(self.documentFingerprint);
}); });
var prefsPromise = prefs.initializedPromise; // Fetch the necessary preference values.
var storePromise = store.initializedPromise; var showPreviousViewOnLoad;
Promise.all([firstPagePromise, prefsPromise, storePromise]). var showPreviousViewOnLoadPromise =
then(function() { Preferences.get('showPreviousViewOnLoad').then(function (prefValue) {
var showPreviousViewOnLoad = prefs.get('showPreviousViewOnLoad'); showPreviousViewOnLoad = prefValue;
var defaultZoomValue = prefs.get('defaultZoomValue'); });
var defaultZoomValue;
var defaultZoomValuePromise =
Preferences.get('defaultZoomValue').then(function (prefValue) {
defaultZoomValue = prefValue;
});
var storePromise = store.initializedPromise;
Promise.all([firstPagePromise, storePromise, showPreviousViewOnLoadPromise,
defaultZoomValuePromise]).then(function resolved() {
var storedHash = null; var storedHash = null;
if (showPreviousViewOnLoad && store.get('exists', false)) { if (showPreviousViewOnLoad && store.get('exists', false)) {
var pageNum = store.get('page', '1'); var pageNum = store.get('page', '1');
@@ -3129,9 +3243,6 @@ var PDFView = {
} else if (defaultZoomValue) { } else if (defaultZoomValue) {
storedHash = 'page=1&zoom=' + defaultZoomValue; storedHash = 'page=1&zoom=' + defaultZoomValue;
} }
// Initialize the browsing history.
PDFHistory.initialize(self.documentFingerprint);
self.setInitialView(storedHash, scale); self.setInitialView(storedHash, scale);
// Make all navigation keys work on document load, // Make all navigation keys work on document load,
@@ -3140,6 +3251,12 @@ var PDFView = {
self.container.focus(); self.container.focus();
self.container.blur(); self.container.blur();
} }
}, function rejected(errorMsg) {
console.error(errorMsg);
firstPagePromise.then(function () {
self.setInitialView(null, scale);
});
}); });
pagesPromise.then(function() { pagesPromise.then(function() {
@@ -3178,11 +3295,16 @@ var PDFView = {
self.outline = new DocumentOutlineView(outline); self.outline = new DocumentOutlineView(outline);
document.getElementById('viewOutline').disabled = !outline; document.getElementById('viewOutline').disabled = !outline;
if (outline && prefs.get('ifAvailableShowOutlineOnLoad')) { if (outline) {
if (!self.sidebarOpen) { Preferences.get('ifAvailableShowOutlineOnLoad').then(
document.getElementById('sidebarToggle').click(); function (prefValue) {
} if (prefValue) {
self.switchSidebarView('outline'); if (!self.sidebarOpen) {
document.getElementById('sidebarToggle').click();
}
self.switchSidebarView('outline');
}
});
} }
}); });
}); });
@@ -3194,9 +3316,10 @@ var PDFView = {
// Provides some basic debug information // Provides some basic debug information
console.log('PDF ' + pdfDocument.fingerprint + ' [' + console.log('PDF ' + pdfDocument.fingerprint + ' [' +
info.PDFFormatVersion + ' ' + (info.Producer || '-') + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
' / ' + (info.Creator || '-') + ']' + ' / ' + (info.Creator || '-').trim() + ']' +
(PDFJS.version ? ' (PDF.js: ' + PDFJS.version + ')' : '')); ' (PDF.js: ' + (PDFJS.version || '-') +
(!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')');
var pdfTitle; var pdfTitle;
if (metadata && metadata.has('dc:title')) { if (metadata && metadata.has('dc:title')) {
@@ -3568,10 +3691,11 @@ var PDFView = {
} }
var alertNotReady = false; var alertNotReady = false;
var i, ii;
if (!this.pages.length) { if (!this.pages.length) {
alertNotReady = true; alertNotReady = true;
} else { } else {
for (var i = 0, ii = this.pages.length; i < ii; ++i) { for (i = 0, ii = this.pages.length; i < ii; ++i) {
if (!this.pages[i].pdfPage) { if (!this.pages[i].pdfPage) {
alertNotReady = true; alertNotReady = true;
break; break;
@@ -3587,7 +3711,7 @@ var PDFView = {
var body = document.querySelector('body'); var body = document.querySelector('body');
body.setAttribute('data-mozPrintCallback', true); body.setAttribute('data-mozPrintCallback', true);
for (var i = 0, ii = this.pages.length; i < ii; ++i) { for (i = 0, ii = this.pages.length; i < ii; ++i) {
this.pages[i].beforePrint(); this.pages[i].beforePrint();
} }
}, },
@@ -3601,14 +3725,15 @@ var PDFView = {
rotatePages: function pdfViewRotatePages(delta) { rotatePages: function pdfViewRotatePages(delta) {
var currentPage = this.pages[this.page - 1]; var currentPage = this.pages[this.page - 1];
var i, l;
this.pageRotation = (this.pageRotation + 360 + delta) % 360; this.pageRotation = (this.pageRotation + 360 + delta) % 360;
for (var i = 0, l = this.pages.length; i < l; i++) { for (i = 0, l = this.pages.length; i < l; i++) {
var page = this.pages[i]; var page = this.pages[i];
page.update(page.scale, this.pageRotation); page.update(page.scale, this.pageRotation);
} }
for (var i = 0, l = this.thumbnails.length; i < l; i++) { for (i = 0, l = this.thumbnails.length; i < l; i++) {
var thumb = this.thumbnails[i]; var thumb = this.thumbnails[i];
thumb.update(this.pageRotation); thumb.update(this.pageRotation);
} }
@@ -4019,7 +4144,7 @@ var PageView = function pageView(container, id, scale,
var x = 0, y = 0; var x = 0, y = 0;
var width = 0, height = 0, widthScale, heightScale; var width = 0, height = 0, widthScale, heightScale;
var changeOrientation = !!(this.rotation % 180); var changeOrientation = (this.rotation % 180 === 0 ? false : true);
var pageWidth = (changeOrientation ? this.height : this.width) / var pageWidth = (changeOrientation ? this.height : this.width) /
this.scale / CSS_UNITS; this.scale / CSS_UNITS;
var pageHeight = (changeOrientation ? this.width : this.height) / var pageHeight = (changeOrientation ? this.width : this.height) /
@@ -4156,8 +4281,8 @@ var PageView = function pageView(container, id, scale,
if (!PDFJS.disableTextLayer) { if (!PDFJS.disableTextLayer) {
textLayerDiv = document.createElement('div'); textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer'; textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvas.width + 'px'; textLayerDiv.style.width = canvas.style.width;
textLayerDiv.style.height = canvas.height + 'px'; textLayerDiv.style.height = canvas.style.height;
div.appendChild(textLayerDiv); div.appendChild(textLayerDiv);
} }
var textLayer = this.textLayer = var textLayer = this.textLayer =
@@ -4174,14 +4299,6 @@ var PageView = function pageView(container, id, scale,
if (outputScale.scaled) { if (outputScale.scaled) {
ctx.scale(outputScale.sx, outputScale.sy); ctx.scale(outputScale.sx, outputScale.sy);
} }
if (outputScale.scaled && textLayerDiv) {
var cssScale = 'scale(' + (1 / outputScale.sx) + ', ' +
(1 / outputScale.sy) + ')';
CustomStyle.setProp('transform' , textLayerDiv, cssScale);
CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%');
textLayerDiv.dataset._scaleX = outputScale.sx;
textLayerDiv.dataset._scaleY = outputScale.sy;
}
// Rendering area // Rendering area
@@ -4267,20 +4384,19 @@ var PageView = function pageView(container, id, scale,
this.renderTask.promise.then( this.renderTask.promise.then(
function pdfPageRenderCallback() { function pdfPageRenderCallback() {
pageViewDrawCallback(null); pageViewDrawCallback(null);
if (textLayer) {
self.getTextContent().then(
function textContentResolved(textContent) {
textLayer.setTextContent(textContent);
}
);
}
}, },
function pdfPageRenderError(error) { function pdfPageRenderError(error) {
pageViewDrawCallback(error); pageViewDrawCallback(error);
} }
); );
if (textLayer) {
this.getTextContent().then(
function textContentResolved(textContent) {
textLayer.setTextContent(textContent);
}
);
}
setupAnnotations(div, pdfPage, this.viewport); setupAnnotations(div, pdfPage, this.viewport);
div.setAttribute('data-loaded', true); div.setAttribute('data-loaded', true);
}; };
@@ -4555,6 +4671,7 @@ var TextLayerBuilder = function textLayerBuilder(options) {
this.lastScrollSource = options.lastScrollSource; this.lastScrollSource = options.lastScrollSource;
this.viewport = options.viewport; this.viewport = options.viewport;
this.isViewerInPresentationMode = options.isViewerInPresentationMode; this.isViewerInPresentationMode = options.isViewerInPresentationMode;
this.textDivs = [];
if (typeof PDFFindController === 'undefined') { if (typeof PDFFindController === 'undefined') {
window.PDFFindController = null; window.PDFFindController = null;
@@ -4564,16 +4681,6 @@ var TextLayerBuilder = function textLayerBuilder(options) {
this.lastScrollSource = null; this.lastScrollSource = null;
} }
this.beginLayout = function textLayerBuilderBeginLayout() {
this.textDivs = [];
this.renderingDone = false;
};
this.endLayout = function textLayerBuilderEndLayout() {
this.layoutDone = true;
this.insertDivContent();
};
this.renderLayer = function textLayerBuilderRenderLayer() { this.renderLayer = function textLayerBuilderRenderLayer() {
var textDivs = this.textDivs; var textDivs = this.textDivs;
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
@@ -4633,70 +4740,56 @@ var TextLayerBuilder = function textLayerBuilder(options) {
} }
}; };
this.appendText = function textLayerBuilderAppendText(geom) { this.appendText = function textLayerBuilderAppendText(geom, styles) {
var style = styles[geom.fontName];
var textDiv = document.createElement('div'); var textDiv = document.createElement('div');
// vScale and hScale already contain the scaling to pixel units
var fontHeight = geom.fontSize * Math.abs(geom.vScale);
textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
textDiv.dataset.fontName = geom.fontName;
textDiv.dataset.angle = geom.angle * (180 / Math.PI);
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = geom.fontFamily;
var fontAscent = (geom.ascent ? geom.ascent * fontHeight :
(geom.descent ? (1 + geom.descent) * fontHeight : fontHeight));
textDiv.style.left = (geom.x + (fontAscent * Math.sin(geom.angle))) + 'px';
textDiv.style.top = (geom.y - (fontAscent * Math.cos(geom.angle))) + 'px';
// The content of the div is set in the `setTextContent` function.
this.textDivs.push(textDiv); this.textDivs.push(textDiv);
}; if (!/\S/.test(geom.str)) {
textDiv.dataset.isWhitespace = true;
this.insertDivContent = function textLayerUpdateTextContent() {
// Only set the content of the divs once layout has finished, the content
// for the divs is available and content is not yet set on the divs.
if (!this.layoutDone || this.divContentDone || !this.textContent) {
return; return;
} }
var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform);
var angle = Math.atan2(tx[1], tx[0]);
if (style.vertical) {
angle += Math.PI / 2;
}
var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
var fontAscent = (style.ascent ? style.ascent * fontHeight :
(style.descent ? (1 + style.descent) * fontHeight : fontHeight));
this.divContentDone = true; textDiv.style.position = 'absolute';
textDiv.style.left = (tx[4] + (fontAscent * Math.sin(angle))) + 'px';
textDiv.style.top = (tx[5] - (fontAscent * Math.cos(angle))) + 'px';
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = style.fontFamily;
var textDivs = this.textDivs; textDiv.textContent = geom.str;
var bidiTexts = this.textContent; textDiv.dataset.fontName = geom.fontName;
textDiv.dataset.angle = angle * (180 / Math.PI);
for (var i = 0; i < bidiTexts.length; i++) { if (style.vertical) {
var bidiText = bidiTexts[i]; textDiv.dataset.canvasWidth = geom.height * this.viewport.scale;
var textDiv = textDivs[i]; } else {
if (!/\S/.test(bidiText.str)) { textDiv.dataset.canvasWidth = geom.width * this.viewport.scale;
textDiv.dataset.isWhitespace = true;
continue;
}
textDiv.textContent = bidiText.str;
// TODO refactor text layer to use text content position
/**
* var arr = this.viewport.convertToViewportPoint(bidiText.x, bidiText.y);
* textDiv.style.left = arr[0] + 'px';
* textDiv.style.top = arr[1] + 'px';
*/
// bidiText.dir may be 'ttb' for vertical texts.
textDiv.dir = bidiText.dir;
} }
this.setupRenderLayoutTimer();
}; };
this.setTextContent = function textLayerBuilderSetTextContent(textContent) { this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
this.textContent = textContent; this.textContent = textContent;
this.insertDivContent();
var textItems = textContent.items;
for (var i = 0; i < textItems.length; i++) {
this.appendText(textItems[i], textContent.styles);
}
this.divContentDone = true;
this.setupRenderLayoutTimer();
}; };
this.convertMatches = function textLayerBuilderConvertMatches(matches) { this.convertMatches = function textLayerBuilderConvertMatches(matches) {
var i = 0; var i = 0;
var iIndex = 0; var iIndex = 0;
var bidiTexts = this.textContent; var bidiTexts = this.textContent.items;
var end = bidiTexts.length - 1; var end = bidiTexts.length - 1;
var queryLen = (PDFFindController === null ? var queryLen = (PDFFindController === null ?
0 : PDFFindController.state.query.length); 0 : PDFFindController.state.query.length);
@@ -4755,7 +4848,7 @@ var TextLayerBuilder = function textLayerBuilder(options) {
return; return;
} }
var bidiTexts = this.textContent; var bidiTexts = this.textContent.items;
var textDivs = this.textDivs; var textDivs = this.textDivs;
var prevEnd = null; var prevEnd = null;
var isSelectedPage = (PDFFindController === null ? var isSelectedPage = (PDFFindController === null ?
@@ -4776,26 +4869,17 @@ var TextLayerBuilder = function textLayerBuilder(options) {
var divIdx = begin.divIdx; var divIdx = begin.divIdx;
var div = textDivs[divIdx]; var div = textDivs[divIdx];
div.textContent = ''; div.textContent = '';
appendTextToDiv(divIdx, 0, begin.offset, className);
var content = bidiTexts[divIdx].str.substring(0, begin.offset);
var node = document.createTextNode(content);
if (className) {
var isSelected = isSelectedPage &&
divIdx === selectedMatchIdx;
var span = document.createElement('span');
span.className = className + (isSelected ? ' selected' : '');
span.appendChild(node);
div.appendChild(span);
return;
}
div.appendChild(node);
} }
function appendText(from, to, className) { function appendText(from, to, className) {
var divIdx = from.divIdx; appendTextToDiv(from.divIdx, from.offset, to.offset, className);
}
function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
var div = textDivs[divIdx]; var div = textDivs[divIdx];
var content = bidiTexts[divIdx].str.substring(from.offset, to.offset); var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
var node = document.createTextNode(content); var node = document.createTextNode(content);
if (className) { if (className) {
var span = document.createElement('span'); var span = document.createElement('span');
@@ -4871,7 +4955,7 @@ var TextLayerBuilder = function textLayerBuilder(options) {
// Clear out all matches. // Clear out all matches.
var matches = this.matches; var matches = this.matches;
var textDivs = this.textDivs; var textDivs = this.textDivs;
var bidiTexts = this.textContent; var bidiTexts = this.textContent.items;
var clearedUntilDivIdx = -1; var clearedUntilDivIdx = -1;
// Clear out all current matches. // Clear out all current matches.
@@ -4951,8 +5035,10 @@ var DocumentOutlineView = function documentOutlineView(outline) {
function webViewerLoad(evt) { function webViewerLoad(evt) {
PDFView.initialize(); PDFView.initialize().then(webViewerInitialized);
}
function webViewerInitialized() {
var file = window.location.href.split('#')[0]; var file = window.location.href.split('#')[0];
document.getElementById('openFile').setAttribute('hidden', 'true'); document.getElementById('openFile').setAttribute('hidden', 'true');
@@ -4982,6 +5068,10 @@ function webViewerLoad(evt) {
PDFJS.disableHistory = (hashParams['disableHistory'] === 'true'); PDFJS.disableHistory = (hashParams['disableHistory'] === 'true');
} }
if ('webgl' in hashParams) {
PDFJS.disableWebGL = (hashParams['webgl'] !== 'true');
}
if ('useOnlyCssZoom' in hashParams) { if ('useOnlyCssZoom' in hashParams) {
USE_ONLY_CSS_ZOOM = (hashParams['useOnlyCssZoom'] === 'true'); USE_ONLY_CSS_ZOOM = (hashParams['useOnlyCssZoom'] === 'true');
} }
@@ -5135,7 +5225,6 @@ function webViewerLoad(evt) {
if (file) { if (file) {
PDFView.open(file, 0); PDFView.open(file, 0);
} }
} }
document.addEventListener('DOMContentLoaded', webViewerLoad, true); document.addEventListener('DOMContentLoaded', webViewerLoad, true);

View File

@@ -3,7 +3,5 @@ skip-if = e10s # Bug 942707 - PDF viewer doesn't work with e10s.
support-files = file_pdfjs_test.pdf support-files = file_pdfjs_test.pdf
[browser_pdfjs_main.js] [browser_pdfjs_main.js]
skip-if = (os == "mac" && debug) || os == "win" # Bug 963075 - leaks when run in chunked mochitest-bc mode
[browser_pdfjs_savedialog.js] [browser_pdfjs_savedialog.js]
[browser_pdfjs_views.js] [browser_pdfjs_views.js]
skip-if = (os == "mac" && debug) || os == "win" # Bug 963075 - leaks when run in chunked mochitest-bc mode

View File

@@ -31,9 +31,9 @@ function test() {
window = newTabBrowser.contentWindow; window = newTabBrowser.contentWindow;
// Runs tests after all 'load' event handlers have fired off // Runs tests after all 'load' event handlers have fired off
setTimeout(function() { window.addEventListener("documentload", function() {
runTests(document, window, finish); runTests(document, window, finish);
}, 0); }, false, true);
}, true); }, true);
} }

View File

@@ -31,7 +31,9 @@ function test() {
window = newTabBrowser.contentWindow; window = newTabBrowser.contentWindow;
// Runs tests after all 'load' event handlers have fired off // Runs tests after all 'load' event handlers have fired off
window.addEventListener("documentload", function() {runTests(document, window, finish);}, false, true); window.addEventListener("documentload", function() {
runTests(document, window, finish);
}, false, true);
}, true); }, true);
} }