Backed out changeset 8ea9fae20fa5 (bug 995431) for mochitest-bc crashes.

This commit is contained in:
Ryan VanderMeulen 2014-04-12 23:25:11 -04:00
Родитель 96f06d9ae1
Коммит d90cfa210e
8 изменённых файлов: 2372 добавлений и 3521 удалений

Просмотреть файл

@ -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: 1.0.2 Current extension version is: 0.8.1334

Просмотреть файл

@ -64,9 +64,7 @@ function initializeDefaultPreferences() {
var DEFAULT_PREFERENCES = { var DEFAULT_PREFERENCES = {
showPreviousViewOnLoad: true, showPreviousViewOnLoad: true,
defaultZoomValue: '', defaultZoomValue: '',
ifAvailableShowOutlineOnLoad: false, ifAvailableShowOutlineOnLoad: false
enableHandToolOnLoad: false,
enableWebGL: false
}; };
@ -136,18 +134,14 @@ let PdfJs = {
}, },
_migrate: function migrate() { _migrate: function migrate() {
const VERSION = 2; const VERSION = 1;
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 < 1) {
this._becomeHandler();
}
if (currentVersion < 2) { if (currentVersion < 2) {
// cleaning up of unused database preference (see #3994) this._becomeHandler();
Services.prefs.clearUserPref(PREF_PREFIX + '.database');
} }
Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION); Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
}, },

Просмотреть файл

@ -32,6 +32,7 @@ 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;
@ -294,6 +295,19 @@ 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');
}, },
@ -438,7 +452,7 @@ ChromeActions.prototype = {
getChromeWindow(this.domWindow).gFindBar getChromeWindow(this.domWindow).gFindBar
.updateControlState(result, findPrevious); .updateControlState(result, findPrevious);
}, },
setPreferences: function(prefs, sendResponse) { setPreferences: function(prefs) {
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;
@ -469,11 +483,8 @@ ChromeActions.prototype = {
break; break;
} }
} }
if (sendResponse) {
sendResponse(true);
}
}, },
getPreferences: function(prefs, sendResponse) { getPreferences: function(prefs) {
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;
@ -499,11 +510,7 @@ ChromeActions.prototype = {
break; break;
} }
} }
if (sendResponse) { return JSON.stringify(currentPrefs);
sendResponse(JSON.stringify(currentPrefs));
} else {
return JSON.stringify(currentPrefs);
}
} }
}; };

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -211,11 +211,10 @@ 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 (i = 0; i < steppers.length; ++i) { for (var 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');
@ -224,7 +223,7 @@ var StepperManager = (function StepperManagerClosure() {
} }
} }
var options = stepperChooser.options; var options = stepperChooser.options;
for (i = 0; i < options.length; ++i) { for (var i = 0; i < options.length; ++i) {
var option = options[i]; var option = options[i];
option.selected = option.value == pageIndex; option.selected = option.value == pageIndex;
} }
@ -345,7 +344,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';
@ -370,7 +369,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];
decArgs = args.slice(); var decArgs = args.slice();
var newArg; var newArg;
if (fn === 'showSpacedText') { if (fn === 'showSpacedText') {
newArg = []; newArg = [];

Просмотреть файл

@ -67,12 +67,10 @@ 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) {
@ -1189,6 +1187,7 @@ 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;
} }
@ -1306,9 +1305,6 @@ 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;

Просмотреть файл

@ -309,99 +309,49 @@ 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() {
* Preferences - Utility for storing persistent settings. function Preferences() {
* Used for settings that should be applied to all opened documents, this.prefs = {};
* or every time the viewer is loaded. this.isInitializedPromiseResolved = false;
*/ this.initializedPromise = this.readFromStorage(DEFAULT_PREFERENCES).then(
var Preferences = { function(prefObj) {
prefs: Object.create(DEFAULT_PREFERENCES), this.isInitializedPromiseResolved = true;
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 = {
* Set the value of a preference. writeToStorage: function Preferences_writeToStorage(prefObj) {
* @param {string} name The name of the preference that should be changed. return;
* @param {boolean|number|string} value The new value of the preference. },
* @return {Promise} A promise that is resolved when the value has been set,
* provided that the preference exists and the types match. readFromStorage: function Preferences_readFromStorage(prefObj) {
*/ var readFromStoragePromise = Promise.resolve();
set: function preferencesSet(name, value) { return readFromStoragePromise;
return this.initializedPromise.then(function () { },
if (DEFAULT_PREFERENCES[name] === undefined) {
throw new Error('preferencesSet: \'' + name + '\' is undefined.'); reset: function Preferences_reset() {
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) {
throw new Error('preferencesSet: no value is specified.'); console.error('Preferences_set: 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];
@ -410,43 +360,40 @@ var Preferences = {
if (valueType === 'number' && defaultType === 'string') { if (valueType === 'number' && defaultType === 'string') {
value = value.toString(); value = value.toString();
} else { } else {
throw new Error('Preferences_set: \'' + value + '\' is a \"' + console.error('Preferences_set: \'' + value + '\' is a \"' +
valueType + '\", expected \"' + defaultType + '\".'); valueType + '\", expected a \"' + defaultType + '\".');
return;
} }
} else { } else {
if (valueType === 'number' && (value | 0) !== value) { if (valueType === 'number' && (value | 0) !== value) {
throw new Error('Preferences_set: \'' + value + console.error('Preferences_set: \'' + value +
'\' must be an \"integer\".'); '\' must be an \"integer\".');
return;
} }
} }
this.prefs[name] = value; this.prefs[name] = value;
return this._writeToStorage(this.prefs); this.writeToStorage(this.prefs);
}.bind(this)); },
},
/** get: function Preferences_get(name) {
* Get the value of a preference. var defaultPref = DEFAULT_PREFERENCES[name];
* @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 (defaultValue === undefined) { if (defaultPref === undefined) {
throw new Error('preferencesGet: \'' + name + '\' is undefined.'); console.error('Preferences_get: \'' + name + '\' is undefined.');
} else { return;
var prefValue = this.prefs[name]; } else if (this.isInitializedPromiseResolved) {
var pref = this.prefs[name];
if (prefValue !== undefined) { if (pref !== undefined) {
return prefValue; return pref;
} }
} }
return defaultValue; return defaultPref;
}.bind(this)); }
} };
};
return Preferences;
})();
@ -541,19 +488,17 @@ var DownloadManager = (function DownloadManagerClosure() {
return DownloadManager; return DownloadManager;
})(); })();
Preferences._writeToStorage = function (prefObj) { Preferences.prototype.writeToStorage = function(prefObj) {
return new Promise(function (resolve) { FirefoxCom.requestSync('setPreferences', prefObj);
FirefoxCom.request('setPreferences', prefObj, resolve);
});
}; };
Preferences._readFromStorage = function (prefObj) { Preferences.prototype.readFromStorage = function(prefObj) {
return new Promise(function (resolve) { var readFromStoragePromise = new Promise(function (resolve) {
FirefoxCom.request('getPreferences', prefObj, function (prefStr) { var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences',
var readPrefs = JSON.parse(prefStr); prefObj));
resolve(readPrefs); resolve(readPrefs);
});
}); });
return readFromStoragePromise;
}; };
@ -568,7 +513,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 sessionStorage. * - FIREFOX or MOZCENTRAL - uses about:config.
* - B2G - uses asyncStorage. * - B2G - uses asyncStorage.
* - GENERIC or CHROME - uses localStorage, if it is available. * - GENERIC or CHROME - uses localStorage, if it is available.
*/ */
@ -588,7 +533,7 @@ var ViewHistory = (function ViewHistoryClosure() {
}).bind(this); }).bind(this);
resolvePromise(sessionStorage.getItem('pdfjsHistory')); resolvePromise(FirefoxCom.requestSync('getDatabase', null));
} }
@ -625,7 +570,7 @@ var ViewHistory = (function ViewHistoryClosure() {
var database = JSON.stringify(this.database); var database = JSON.stringify(this.database);
sessionStorage.setItem('pdfjsHistory',database); FirefoxCom.requestSync('setDatabase', database);
}, },
@ -926,12 +871,11 @@ 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(textContent) { function textContentResolved(bidiTexts) {
var textItems = textContent.items;
var str = ''; var str = '';
for (var i = 0; i < textItems.length; i++) { for (var i = 0; i < bidiTexts.length; i++) {
str += textItems[i].str; str += bidiTexts[i].str;
} }
// Store the pageContent as a string. // Store the pageContent as a string.
@ -1834,9 +1778,11 @@ 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);
@ -2164,15 +2110,8 @@ 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() {
@ -2238,10 +2177,6 @@ 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) {
@ -2252,51 +2187,44 @@ var DocumentProperties = {
}, },
getProperties: function documentPropertiesGetProperties() { getProperties: function documentPropertiesGetProperties() {
if (!this.visible) { var self = this;
// 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) {
this.setFileSize(data.length); self.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: this.fileNameField, content: this.fileName }, { field: self.fileNameField, content: self.fileName },
// The fileSize field is updated once getDownloadInfo is resolved. { field: self.fileSizeField, content: self.fileSize },
{ field: this.titleField, content: data.info.Title }, { field: self.titleField, content: data.info.Title },
{ field: this.authorField, content: data.info.Author }, { field: self.authorField, content: data.info.Author },
{ field: this.subjectField, content: data.info.Subject }, { field: self.subjectField, content: data.info.Subject },
{ field: this.keywordsField, content: data.info.Keywords }, { field: self.keywordsField, content: data.info.Keywords },
{ field: this.creationDateField, { field: self.creationDateField,
content: this.parseDate(data.info.CreationDate) }, content: self.parseDate(data.info.CreationDate) },
{ field: this.modificationDateField, { field: self.modificationDateField,
content: this.parseDate(data.info.ModDate) }, content: self.parseDate(data.info.ModDate) },
{ field: this.creatorField, content: data.info.Creator }, { field: self.creatorField, content: data.info.Creator },
{ field: this.producerField, content: data.info.Producer }, { field: self.producerField, content: data.info.Producer },
{ field: this.versionField, content: data.info.PDFFormatVersion }, { field: self.versionField, content: data.info.PDFFormatVersion },
{ field: this.pageCountField, content: PDFView.pdfDocument.numPages } { field: self.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];
this.updateUI(element.field, element.content); if (element.field && element.content !== undefined &&
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) {
@ -2321,10 +2249,7 @@ 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() {
@ -2422,8 +2347,6 @@ 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'),
@ -2498,20 +2421,10 @@ 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) {
@ -2577,11 +2490,9 @@ var PDFView = {
if (!currentPage) { if (!currentPage) {
return; return;
} }
var hPadding = PresentationMode.active ? 0 : SCROLLBAR_PADDING; var pageWidthScale = (this.container.clientWidth - 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 - vPadding) / var pageHeightScale = (this.container.clientHeight - VERTICAL_PADDING) /
currentPage.height * currentPage.scale; currentPage.height * currentPage.scale;
switch (value) { switch (value) {
case 'page-actual': case 'page-actual':
@ -2863,9 +2774,6 @@ 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};
@ -2883,8 +2791,6 @@ 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;
@ -2907,13 +2813,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
loadingErrorMessage = mozL10n.get('invalid_file_error', null, var 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
loadingErrorMessage = mozL10n.get('missing_file_error', null, var loadingErrorMessage = mozL10n.get('missing_file_error', null,
'Missing PDF file.'); 'Missing PDF file.');
} }
@ -2928,7 +2834,7 @@ var PDFView = {
}, },
download: function pdfViewDownload() { download: function pdfViewDownload() {
function downloadByUrl() { function noData() {
downloadManager.downloadUrl(url, filename); downloadManager.downloadUrl(url, filename);
} }
@ -2942,12 +2848,7 @@ var PDFView = {
}; };
if (!this.pdfDocument) { // the PDF is not ready yet if (!this.pdfDocument) { // the PDF is not ready yet
downloadByUrl(); noData();
return;
}
if (!this.downloadComplete) { // the PDF is still downloading
downloadByUrl();
return; return;
} }
@ -2956,8 +2857,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);
}, },
downloadByUrl // Error occurred try downloading with just the url. noData // Error occurred try downloading with just the url.
).then(null, downloadByUrl); ).then(null, noData);
}, },
fallback: function pdfViewFallback(featureId) { fallback: function pdfViewFallback(featureId) {
@ -3125,10 +3026,7 @@ var PDFView = {
this.pdfDocument = pdfDocument; this.pdfDocument = pdfDocument;
DocumentProperties.resolveDataAvailable();
pdfDocument.getDownloadInfo().then(function() { 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');
@ -3141,6 +3039,7 @@ 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);
@ -3209,26 +3108,15 @@ var PDFView = {
PDFView.loadingBar.setWidth(container); PDFView.loadingBar.setWidth(container);
PDFFindController.resolveFirstPage(); PDFFindController.resolveFirstPage();
// Initialize the browsing history.
PDFHistory.initialize(self.documentFingerprint);
}); });
// Fetch the necessary preference values. var prefsPromise = prefs.initializedPromise;
var showPreviousViewOnLoad;
var showPreviousViewOnLoadPromise =
Preferences.get('showPreviousViewOnLoad').then(function (prefValue) {
showPreviousViewOnLoad = prefValue;
});
var defaultZoomValue;
var defaultZoomValuePromise =
Preferences.get('defaultZoomValue').then(function (prefValue) {
defaultZoomValue = prefValue;
});
var storePromise = store.initializedPromise; var storePromise = store.initializedPromise;
Promise.all([firstPagePromise, storePromise, showPreviousViewOnLoadPromise, Promise.all([firstPagePromise, prefsPromise, storePromise]).
defaultZoomValuePromise]).then(function resolved() { then(function() {
var showPreviousViewOnLoad = prefs.get('showPreviousViewOnLoad');
var defaultZoomValue = prefs.get('defaultZoomValue');
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');
@ -3241,6 +3129,9 @@ 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,
@ -3249,12 +3140,6 @@ 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() {
@ -3293,16 +3178,11 @@ var PDFView = {
self.outline = new DocumentOutlineView(outline); self.outline = new DocumentOutlineView(outline);
document.getElementById('viewOutline').disabled = !outline; document.getElementById('viewOutline').disabled = !outline;
if (outline) { if (outline && prefs.get('ifAvailableShowOutlineOnLoad')) {
Preferences.get('ifAvailableShowOutlineOnLoad').then( if (!self.sidebarOpen) {
function (prefValue) { document.getElementById('sidebarToggle').click();
if (prefValue) { }
if (!self.sidebarOpen) { self.switchSidebarView('outline');
document.getElementById('sidebarToggle').click();
}
self.switchSidebarView('outline');
}
});
} }
}); });
}); });
@ -3314,10 +3194,9 @@ 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 || '-').trim() + info.PDFFormatVersion + ' ' + (info.Producer || '-') +
' / ' + (info.Creator || '-').trim() + ']' + ' / ' + (info.Creator || '-') + ']' +
' (PDF.js: ' + (PDFJS.version || '-') + (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')) {
@ -3689,11 +3568,10 @@ 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 (i = 0, ii = this.pages.length; i < ii; ++i) { for (var 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;
@ -3709,7 +3587,7 @@ var PDFView = {
var body = document.querySelector('body'); var body = document.querySelector('body');
body.setAttribute('data-mozPrintCallback', true); body.setAttribute('data-mozPrintCallback', true);
for (i = 0, ii = this.pages.length; i < ii; ++i) { for (var i = 0, ii = this.pages.length; i < ii; ++i) {
this.pages[i].beforePrint(); this.pages[i].beforePrint();
} }
}, },
@ -3723,15 +3601,14 @@ 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 (i = 0, l = this.pages.length; i < l; i++) { for (var 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 (i = 0, l = this.thumbnails.length; i < l; i++) { for (var 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);
} }
@ -4142,7 +4019,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 === 0 ? false : true); var changeOrientation = !!(this.rotation % 180);
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) /
@ -4279,8 +4156,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.style.width; textLayerDiv.style.width = canvas.width + 'px';
textLayerDiv.style.height = canvas.style.height; textLayerDiv.style.height = canvas.height + 'px';
div.appendChild(textLayerDiv); div.appendChild(textLayerDiv);
} }
var textLayer = this.textLayer = var textLayer = this.textLayer =
@ -4297,6 +4174,14 @@ 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
@ -4382,19 +4267,20 @@ 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);
}; };
@ -4669,7 +4555,6 @@ 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;
@ -4679,6 +4564,16 @@ 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');
@ -4738,56 +4633,70 @@ var TextLayerBuilder = function textLayerBuilder(options) {
} }
}; };
this.appendText = function textLayerBuilderAppendText(geom, styles) { this.appendText = function textLayerBuilderAppendText(geom) {
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));
textDiv.style.position = 'absolute'; this.divContentDone = true;
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;
textDiv.textContent = geom.str; var textDivs = this.textDivs;
textDiv.dataset.fontName = geom.fontName; var bidiTexts = this.textContent;
textDiv.dataset.angle = angle * (180 / Math.PI);
if (style.vertical) { for (var i = 0; i < bidiTexts.length; i++) {
textDiv.dataset.canvasWidth = geom.height * this.viewport.scale; var bidiText = bidiTexts[i];
} else { var textDiv = textDivs[i];
textDiv.dataset.canvasWidth = geom.width * this.viewport.scale; if (!/\S/.test(bidiText.str)) {
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.items; var bidiTexts = this.textContent;
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);
@ -4846,7 +4755,7 @@ var TextLayerBuilder = function textLayerBuilder(options) {
return; return;
} }
var bidiTexts = this.textContent.items; var bidiTexts = this.textContent;
var textDivs = this.textDivs; var textDivs = this.textDivs;
var prevEnd = null; var prevEnd = null;
var isSelectedPage = (PDFFindController === null ? var isSelectedPage = (PDFFindController === null ?
@ -4962,7 +4871,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.items; var bidiTexts = this.textContent;
var clearedUntilDivIdx = -1; var clearedUntilDivIdx = -1;
// Clear out all current matches. // Clear out all current matches.
@ -5042,10 +4951,8 @@ var DocumentOutlineView = function documentOutlineView(outline) {
function webViewerLoad(evt) { function webViewerLoad(evt) {
PDFView.initialize().then(webViewerInitialized); PDFView.initialize();
}
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');
@ -5075,10 +4982,6 @@ function webViewerInitialized() {
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');
} }
@ -5232,6 +5135,7 @@ function webViewerInitialized() {
if (file) { if (file) {
PDFView.open(file, 0); PDFView.open(file, 0);
} }
} }
document.addEventListener('DOMContentLoaded', webViewerLoad, true); document.addEventListener('DOMContentLoaded', webViewerLoad, true);