Merge pull request #9995 from Snuffleupagus/async-web

Refactor code in the `web/` folder to use `async`/`await`
This commit is contained in:
Tim van der Meij 2018-09-08 21:40:20 +02:00 committed by GitHub
commit 510f1c84d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 414 additions and 473 deletions

View File

@ -133,44 +133,42 @@ let PDFViewerApplication = {
contentDispositionFilename: null, contentDispositionFilename: null,
// Called once when the document is loaded. // Called once when the document is loaded.
initialize(appConfig) { async initialize(appConfig) {
this.preferences = this.externalServices.createPreferences(); this.preferences = this.externalServices.createPreferences();
this.appConfig = appConfig; this.appConfig = appConfig;
return this._readPreferences().then(() => { await this._readPreferences();
return this._parseHashParameters(); await this._parseHashParameters();
}).then(() => { await this._initializeL10n();
return this._initializeL10n();
}).then(() => {
if (this.isViewerEmbedded &&
AppOptions.get('externalLinkTarget') === LinkTarget.NONE) {
// Prevent external links from "replacing" the viewer,
// when it's embedded in e.g. an <iframe> or an <object>.
AppOptions.set('externalLinkTarget', LinkTarget.TOP);
}
return this._initializeViewerComponents();
}).then(() => {
// Bind the various event handlers *after* the viewer has been
// initialized, to prevent errors if an event arrives too soon.
this.bindEvents();
this.bindWindowEvents();
// We can start UI localization now. if (this.isViewerEmbedded &&
let appContainer = appConfig.appContainer || document.documentElement; AppOptions.get('externalLinkTarget') === LinkTarget.NONE) {
this.l10n.translate(appContainer).then(() => { // Prevent external links from "replacing" the viewer,
// Dispatch the 'localized' event on the `eventBus` once the viewer // when it's embedded in e.g. an <iframe> or an <object>.
// has been fully initialized and translated. AppOptions.set('externalLinkTarget', LinkTarget.TOP);
this.eventBus.dispatch('localized', { source: this, }); }
}); await this._initializeViewerComponents();
this.initialized = true; // Bind the various event handlers *after* the viewer has been
// initialized, to prevent errors if an event arrives too soon.
this.bindEvents();
this.bindWindowEvents();
// We can start UI localization now.
let appContainer = appConfig.appContainer || document.documentElement;
this.l10n.translate(appContainer).then(() => {
// Dispatch the 'localized' event on the `eventBus` once the viewer
// has been fully initialized and translated.
this.eventBus.dispatch('localized', { source: this, });
}); });
this.initialized = true;
}, },
/** /**
* @private * @private
*/ */
_readPreferences() { async _readPreferences() {
// A subset of the Preferences that `AppOptions`, for compatibility reasons, // A subset of the Preferences that `AppOptions`, for compatibility reasons,
// is allowed to override if the `AppOptions` values matches the ones below. // is allowed to override if the `AppOptions` values matches the ones below.
const OVERRIDES = { const OVERRIDES = {
@ -180,89 +178,89 @@ let PDFViewerApplication = {
textLayerMode: TextLayerMode.DISABLE, textLayerMode: TextLayerMode.DISABLE,
}; };
return this.preferences.getAll().then(function(prefs) { try {
const prefs = await this.preferences.getAll();
for (let name in prefs) { for (let name in prefs) {
if ((name in OVERRIDES) && AppOptions.get(name) === OVERRIDES[name]) { if ((name in OVERRIDES) && AppOptions.get(name) === OVERRIDES[name]) {
continue; continue;
} }
AppOptions.set(name, prefs[name]); AppOptions.set(name, prefs[name]);
} }
}, function(reason) { }); } catch (reason) { }
}, },
/** /**
* @private * @private
*/ */
_parseHashParameters() { async _parseHashParameters() {
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('PRODUCTION') &&
!AppOptions.get('pdfBugEnabled')) {
return;
}
const waitOn = []; const waitOn = [];
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION') || // Special debugging flags in the hash section of the URL.
AppOptions.get('pdfBugEnabled')) { let hash = document.location.hash.substring(1);
// Special debugging flags in the hash section of the URL. let hashParams = parseQueryString(hash);
let hash = document.location.hash.substring(1);
let hashParams = parseQueryString(hash);
if ('disableworker' in hashParams && if ('disableworker' in hashParams &&
hashParams['disableworker'] === 'true') { hashParams['disableworker'] === 'true') {
waitOn.push(loadFakeWorker()); waitOn.push(loadFakeWorker());
} }
if ('disablerange' in hashParams) { if ('disablerange' in hashParams) {
AppOptions.set('disableRange', hashParams['disablerange'] === 'true'); AppOptions.set('disableRange', hashParams['disablerange'] === 'true');
} }
if ('disablestream' in hashParams) { if ('disablestream' in hashParams) {
AppOptions.set('disableStream', hashParams['disablestream'] === 'true'); AppOptions.set('disableStream', hashParams['disablestream'] === 'true');
} }
if ('disableautofetch' in hashParams) { if ('disableautofetch' in hashParams) {
AppOptions.set('disableAutoFetch', AppOptions.set('disableAutoFetch',
hashParams['disableautofetch'] === 'true'); hashParams['disableautofetch'] === 'true');
} }
if ('disablefontface' in hashParams) { if ('disablefontface' in hashParams) {
AppOptions.set('disableFontFace', AppOptions.set('disableFontFace',
hashParams['disablefontface'] === 'true'); hashParams['disablefontface'] === 'true');
} }
if ('disablehistory' in hashParams) { if ('disablehistory' in hashParams) {
AppOptions.set('disableHistory', AppOptions.set('disableHistory', hashParams['disablehistory'] === 'true');
hashParams['disablehistory'] === 'true'); }
} if ('webgl' in hashParams) {
if ('webgl' in hashParams) { AppOptions.set('enableWebGL', hashParams['webgl'] === 'true');
AppOptions.set('enableWebGL', hashParams['webgl'] === 'true'); }
} if ('useonlycsszoom' in hashParams) {
if ('useonlycsszoom' in hashParams) { AppOptions.set('useOnlyCssZoom', hashParams['useonlycsszoom'] === 'true');
AppOptions.set('useOnlyCssZoom', }
hashParams['useonlycsszoom'] === 'true'); if ('verbosity' in hashParams) {
} AppOptions.set('verbosity', hashParams['verbosity'] | 0);
if ('verbosity' in hashParams) { }
AppOptions.set('verbosity', hashParams['verbosity'] | 0); if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) &&
} hashParams['disablebcmaps'] === 'true') {
if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) && AppOptions.set('cMapUrl', '../external/cmaps/');
hashParams['disablebcmaps'] === 'true') { AppOptions.set('cMapPacked', false);
AppOptions.set('cMapUrl', '../external/cmaps/'); }
AppOptions.set('cMapPacked', false); if ('textlayer' in hashParams) {
} switch (hashParams['textlayer']) {
if ('textlayer' in hashParams) { case 'off':
switch (hashParams['textlayer']) { AppOptions.set('textLayerMode', TextLayerMode.DISABLE);
case 'off': break;
AppOptions.set('textLayerMode', TextLayerMode.DISABLE); case 'visible':
break; case 'shadow':
case 'visible': case 'hover':
case 'shadow': let viewer = this.appConfig.viewerContainer;
case 'hover': viewer.classList.add('textLayer-' + hashParams['textlayer']);
let viewer = this.appConfig.viewerContainer; break;
viewer.classList.add('textLayer-' + hashParams['textlayer']);
break;
}
}
if ('pdfbug' in hashParams) {
AppOptions.set('pdfBug', true);
let enabled = hashParams['pdfbug'].split(',');
waitOn.push(loadAndEnablePDFBug(enabled));
}
// It is not possible to change locale for the (various) extension builds.
if ((typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('!PRODUCTION || GENERIC')) && 'locale' in hashParams) {
AppOptions.set('locale', hashParams['locale']);
} }
} }
if ('pdfbug' in hashParams) {
AppOptions.set('pdfBug', true);
let enabled = hashParams['pdfbug'].split(',');
waitOn.push(loadAndEnablePDFBug(enabled));
}
// It is not possible to change locale for the (various) extension builds.
if ((typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('!PRODUCTION || GENERIC')) && 'locale' in hashParams) {
AppOptions.set('locale', hashParams['locale']);
}
return Promise.all(waitOn); return Promise.all(waitOn);
}, },
@ -270,164 +268,160 @@ let PDFViewerApplication = {
/** /**
* @private * @private
*/ */
_initializeL10n() { async _initializeL10n() {
this.l10n = this.externalServices.createL10n({ this.l10n = this.externalServices.createL10n({
locale: AppOptions.get('locale'), locale: AppOptions.get('locale'),
}); });
return this.l10n.getDirection().then((dir) => { const dir = await this.l10n.getDirection();
document.getElementsByTagName('html')[0].dir = dir; document.getElementsByTagName('html')[0].dir = dir;
});
}, },
/** /**
* @private * @private
*/ */
_initializeViewerComponents() { async _initializeViewerComponents() {
let { appConfig, } = this; const appConfig = this.appConfig;
return new Promise((resolve, reject) => { this.overlayManager = new OverlayManager();
this.overlayManager = new OverlayManager();
const dispatchToDOM = AppOptions.get('eventBusDispatchToDOM'); const dispatchToDOM = AppOptions.get('eventBusDispatchToDOM');
let eventBus = appConfig.eventBus || getGlobalEventBus(dispatchToDOM); let eventBus = appConfig.eventBus || getGlobalEventBus(dispatchToDOM);
this.eventBus = eventBus; this.eventBus = eventBus;
let pdfRenderingQueue = new PDFRenderingQueue(); let pdfRenderingQueue = new PDFRenderingQueue();
pdfRenderingQueue.onIdle = this.cleanup.bind(this); pdfRenderingQueue.onIdle = this.cleanup.bind(this);
this.pdfRenderingQueue = pdfRenderingQueue; this.pdfRenderingQueue = pdfRenderingQueue;
let pdfLinkService = new PDFLinkService({ let pdfLinkService = new PDFLinkService({
eventBus, eventBus,
externalLinkTarget: AppOptions.get('externalLinkTarget'), externalLinkTarget: AppOptions.get('externalLinkTarget'),
externalLinkRel: AppOptions.get('externalLinkRel'), externalLinkRel: AppOptions.get('externalLinkRel'),
}); });
this.pdfLinkService = pdfLinkService; this.pdfLinkService = pdfLinkService;
let downloadManager = this.externalServices.createDownloadManager({ let downloadManager = this.externalServices.createDownloadManager({
disableCreateObjectURL: AppOptions.get('disableCreateObjectURL'), disableCreateObjectURL: AppOptions.get('disableCreateObjectURL'),
}); });
this.downloadManager = downloadManager; this.downloadManager = downloadManager;
let container = appConfig.mainContainer; let container = appConfig.mainContainer;
let viewer = appConfig.viewerContainer; let viewer = appConfig.viewerContainer;
this.pdfViewer = new PDFViewer({ this.pdfViewer = new PDFViewer({
container,
viewer,
eventBus,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService,
downloadManager,
renderer: AppOptions.get('renderer'),
enableWebGL: AppOptions.get('enableWebGL'),
l10n: this.l10n,
textLayerMode: AppOptions.get('textLayerMode'),
imageResourcesPath: AppOptions.get('imageResourcesPath'),
renderInteractiveForms: AppOptions.get('renderInteractiveForms'),
enablePrintAutoRotate: AppOptions.get('enablePrintAutoRotate'),
useOnlyCssZoom: AppOptions.get('useOnlyCssZoom'),
maxCanvasPixels: AppOptions.get('maxCanvasPixels'),
});
pdfRenderingQueue.setViewer(this.pdfViewer);
pdfLinkService.setViewer(this.pdfViewer);
let thumbnailContainer = appConfig.sidebar.thumbnailView;
this.pdfThumbnailViewer = new PDFThumbnailViewer({
container: thumbnailContainer,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService,
l10n: this.l10n,
});
pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
this.pdfHistory = new PDFHistory({
linkService: pdfLinkService,
eventBus,
});
pdfLinkService.setHistory(this.pdfHistory);
this.findController = new PDFFindController({
pdfViewer: this.pdfViewer,
eventBus,
});
this.findController.onUpdateResultsCount = (matchCount) => {
if (this.supportsIntegratedFind) {
return;
}
this.findBar.updateResultsCount(matchCount);
};
this.findController.onUpdateState = (state, previous, matchCount) => {
if (this.supportsIntegratedFind) {
this.externalServices.updateFindControlState({
result: state,
findPrevious: previous,
});
} else {
this.findBar.updateUIState(state, previous, matchCount);
}
};
this.pdfViewer.setFindController(this.findController);
// TODO: improve `PDFFindBar` constructor parameter passing
let findBarConfig = Object.create(appConfig.findBar);
findBarConfig.findController = this.findController;
findBarConfig.eventBus = eventBus;
this.findBar = new PDFFindBar(findBarConfig, this.l10n);
this.pdfDocumentProperties =
new PDFDocumentProperties(appConfig.documentProperties,
this.overlayManager, eventBus, this.l10n);
this.pdfCursorTools = new PDFCursorTools({
container,
eventBus,
cursorToolOnLoad: AppOptions.get('cursorToolOnLoad'),
});
this.toolbar = new Toolbar(appConfig.toolbar, container, eventBus,
this.l10n);
this.secondaryToolbar =
new SecondaryToolbar(appConfig.secondaryToolbar, container, eventBus);
if (this.supportsFullscreen) {
this.pdfPresentationMode = new PDFPresentationMode({
container, container,
viewer, viewer,
eventBus,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService,
downloadManager,
renderer: AppOptions.get('renderer'),
enableWebGL: AppOptions.get('enableWebGL'),
l10n: this.l10n,
textLayerMode: AppOptions.get('textLayerMode'),
imageResourcesPath: AppOptions.get('imageResourcesPath'),
renderInteractiveForms: AppOptions.get('renderInteractiveForms'),
enablePrintAutoRotate: AppOptions.get('enablePrintAutoRotate'),
useOnlyCssZoom: AppOptions.get('useOnlyCssZoom'),
maxCanvasPixels: AppOptions.get('maxCanvasPixels'),
});
pdfRenderingQueue.setViewer(this.pdfViewer);
pdfLinkService.setViewer(this.pdfViewer);
let thumbnailContainer = appConfig.sidebar.thumbnailView;
this.pdfThumbnailViewer = new PDFThumbnailViewer({
container: thumbnailContainer,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService,
l10n: this.l10n,
});
pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
this.pdfHistory = new PDFHistory({
linkService: pdfLinkService,
eventBus,
});
pdfLinkService.setHistory(this.pdfHistory);
this.findController = new PDFFindController({
pdfViewer: this.pdfViewer, pdfViewer: this.pdfViewer,
eventBus, eventBus,
contextMenuItems: appConfig.fullscreen,
}); });
this.findController.onUpdateResultsCount = (matchCount) => { }
if (this.supportsIntegratedFind) {
return;
}
this.findBar.updateResultsCount(matchCount);
};
this.findController.onUpdateState = (state, previous, matchCount) => {
if (this.supportsIntegratedFind) {
this.externalServices.updateFindControlState({
result: state,
findPrevious: previous,
});
} else {
this.findBar.updateUIState(state, previous, matchCount);
}
};
this.pdfViewer.setFindController(this.findController); this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay,
this.overlayManager, this.l10n);
// TODO: improve `PDFFindBar` constructor parameter passing this.pdfOutlineViewer = new PDFOutlineViewer({
let findBarConfig = Object.create(appConfig.findBar); container: appConfig.sidebar.outlineView,
findBarConfig.findController = this.findController; eventBus,
findBarConfig.eventBus = eventBus; linkService: pdfLinkService,
this.findBar = new PDFFindBar(findBarConfig, this.l10n);
this.pdfDocumentProperties =
new PDFDocumentProperties(appConfig.documentProperties,
this.overlayManager, eventBus, this.l10n);
this.pdfCursorTools = new PDFCursorTools({
container,
eventBus,
cursorToolOnLoad: AppOptions.get('cursorToolOnLoad'),
});
this.toolbar = new Toolbar(appConfig.toolbar, container, eventBus,
this.l10n);
this.secondaryToolbar =
new SecondaryToolbar(appConfig.secondaryToolbar, container, eventBus);
if (this.supportsFullscreen) {
this.pdfPresentationMode = new PDFPresentationMode({
container,
viewer,
pdfViewer: this.pdfViewer,
eventBus,
contextMenuItems: appConfig.fullscreen,
});
}
this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay,
this.overlayManager, this.l10n);
this.pdfOutlineViewer = new PDFOutlineViewer({
container: appConfig.sidebar.outlineView,
eventBus,
linkService: pdfLinkService,
});
this.pdfAttachmentViewer = new PDFAttachmentViewer({
container: appConfig.sidebar.attachmentsView,
eventBus,
downloadManager,
});
// TODO: improve `PDFSidebar` constructor parameter passing
let sidebarConfig = Object.create(appConfig.sidebar);
sidebarConfig.pdfViewer = this.pdfViewer;
sidebarConfig.pdfThumbnailViewer = this.pdfThumbnailViewer;
sidebarConfig.pdfOutlineViewer = this.pdfOutlineViewer;
sidebarConfig.eventBus = eventBus;
this.pdfSidebar = new PDFSidebar(sidebarConfig, this.l10n);
this.pdfSidebar.onToggled = this.forceRendering.bind(this);
this.pdfSidebarResizer = new PDFSidebarResizer(appConfig.sidebarResizer,
eventBus, this.l10n);
resolve(undefined);
}); });
this.pdfAttachmentViewer = new PDFAttachmentViewer({
container: appConfig.sidebar.attachmentsView,
eventBus,
downloadManager,
});
// TODO: improve `PDFSidebar` constructor parameter passing
let sidebarConfig = Object.create(appConfig.sidebar);
sidebarConfig.pdfViewer = this.pdfViewer;
sidebarConfig.pdfThumbnailViewer = this.pdfThumbnailViewer;
sidebarConfig.pdfOutlineViewer = this.pdfOutlineViewer;
sidebarConfig.eventBus = eventBus;
this.pdfSidebar = new PDFSidebar(sidebarConfig, this.l10n);
this.pdfSidebar.onToggled = this.forceRendering.bind(this);
this.pdfSidebarResizer = new PDFSidebarResizer(appConfig.sidebarResizer,
eventBus, this.l10n);
}, },
run(config) { run(config) {
@ -582,12 +576,12 @@ let PDFViewerApplication = {
* @returns {Promise} - Returns the promise, which is resolved when all * @returns {Promise} - Returns the promise, which is resolved when all
* destruction is completed. * destruction is completed.
*/ */
close() { async close() {
let errorWrapper = this.appConfig.errorWrapper.container; let errorWrapper = this.appConfig.errorWrapper.container;
errorWrapper.setAttribute('hidden', 'true'); errorWrapper.setAttribute('hidden', 'true');
if (!this.pdfLoadingTask) { if (!this.pdfLoadingTask) {
return Promise.resolve(); return;
} }
let promise = this.pdfLoadingTask.destroy(); let promise = this.pdfLoadingTask.destroy();
@ -632,13 +626,10 @@ let PDFViewerApplication = {
* @returns {Promise} - Returns the promise, which is resolved when document * @returns {Promise} - Returns the promise, which is resolved when document
* is opened. * is opened.
*/ */
open(file, args) { async open(file, args) {
if (this.pdfLoadingTask) { if (this.pdfLoadingTask) {
// We need to destroy already opened document. // We need to destroy already opened document.
return this.close().then(() => { await this.close();
// ... and repeat the open() call.
return this.open(file, args);
});
} }
// Set the necessary global worker parameters, using the available options. // Set the necessary global worker parameters, using the available options.
const workerParameters = AppOptions.getAll('worker'); const workerParameters = AppOptions.getAll('worker');
@ -951,10 +942,6 @@ let PDFViewerApplication = {
} }
} }
let initialParams = {
bookmark: null,
hash: null,
};
let storePromise = store.getMultiple({ let storePromise = store.getMultiple({
page: null, page: null,
zoom: DEFAULT_SCALE_VALUE, zoom: DEFAULT_SCALE_VALUE,
@ -966,8 +953,10 @@ let PDFViewerApplication = {
spreadMode: null, spreadMode: null,
}).catch(() => { /* Unable to read from storage; ignoring errors. */ }); }).catch(() => { /* Unable to read from storage; ignoring errors. */ });
Promise.all([storePromise, pageModePromise]).then( Promise.all([
([values = {}, pageMode]) => { storePromise, pageModePromise,
]).then(async ([values = {}, pageMode]) => {
const initialBookmark = this.initialBookmark;
// Initialize the default values, from user preferences. // Initialize the default values, from user preferences.
const zoom = AppOptions.get('defaultZoomValue'); const zoom = AppOptions.get('defaultZoomValue');
let hash = zoom ? `zoom=${zoom}` : null; let hash = zoom ? `zoom=${zoom}` : null;
@ -990,52 +979,40 @@ let PDFViewerApplication = {
// Always let the user preference/history take precedence. // Always let the user preference/history take precedence.
sidebarView = sidebarView || apiPageModeToSidebarView(pageMode); sidebarView = sidebarView || apiPageModeToSidebarView(pageMode);
} }
return {
hash,
rotation,
sidebarView,
scrollMode,
spreadMode,
};
}).then(({ hash, rotation, sidebarView, scrollMode, spreadMode, }) => {
initialParams.bookmark = this.initialBookmark;
initialParams.hash = hash;
this.setInitialView(hash, { this.setInitialView(hash, {
rotation, sidebarView, scrollMode, spreadMode, rotation, sidebarView, scrollMode, spreadMode,
}); });
this.eventBus.dispatch('documentinit', { source: this, }); this.eventBus.dispatch('documentinit', { source: this, });
// Make all navigation keys work on document load, // Make all navigation keys work on document load,
// unless the viewer is embedded in a web page. // unless the viewer is embedded in a web page.
if (!this.isViewerEmbedded) { if (!this.isViewerEmbedded) {
pdfViewer.focus(); pdfViewer.focus();
} }
return Promise.race([ // For documents with different page sizes, once all pages are resolved,
// ensure that the correct location becomes visible on load.
// (To reduce the risk, in very large and/or slow loading documents,
// that the location changes *after* the user has started interacting
// with the viewer, wait for either `pagesPromise` or a timeout.)
await Promise.race([
pagesPromise, pagesPromise,
new Promise((resolve) => { new Promise((resolve) => {
setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);
}), }),
]); ]);
}).then(() => { if (!initialBookmark && !hash) {
// For documents with different page sizes, once all pages are resolved,
// ensure that the correct location becomes visible on load.
// To reduce the risk, in very large and/or slow loading documents,
// that the location changes *after* the user has started interacting
// with the viewer, wait for either `pagesPromise` or a timeout above.
if (!initialParams.bookmark && !initialParams.hash) {
return; return;
} }
if (pdfViewer.hasEqualPageSizes) { if (pdfViewer.hasEqualPageSizes) {
return; return;
} }
this.initialBookmark = initialParams.bookmark; this.initialBookmark = initialBookmark;
// eslint-disable-next-line no-self-assign // eslint-disable-next-line no-self-assign
pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; pdfViewer.currentScaleValue = pdfViewer.currentScaleValue;
this.setInitialView(initialParams.hash); // Re-apply the initial document location.
this.setInitialView(hash);
}).then(function() { }).then(function() {
// At this point, rendering of the initial page(s) should always have // At this point, rendering of the initial page(s) should always have
// started (and may even have completed). // started (and may even have completed).
@ -1629,14 +1606,14 @@ function webViewerInitialized() {
PDFViewerApplication.pdfSidebar.toggle(); PDFViewerApplication.pdfSidebar.toggle();
}); });
Promise.resolve().then(function() { try {
webViewerOpenFileViaURL(file); webViewerOpenFileViaURL(file);
}).catch(function(reason) { } catch (reason) {
PDFViewerApplication.l10n.get('loading_error', null, PDFViewerApplication.l10n.get('loading_error', null,
'An error occurred while loading the PDF.').then((msg) => { 'An error occurred while loading the PDF.').then((msg) => {
PDFViewerApplication.error(msg, reason); PDFViewerApplication.error(msg, reason);
}); });
}); }
} }
let webViewerOpenFileViaURL; let webViewerOpenFileViaURL;

View File

@ -300,7 +300,7 @@ function setReferer(url, callback) {
let storageArea = chrome.storage.sync || chrome.storage.local; let storageArea = chrome.storage.sync || chrome.storage.local;
class ChromePreferences extends BasePreferences { class ChromePreferences extends BasePreferences {
_writeToStorage(prefObj) { async _writeToStorage(prefObj) {
return new Promise((resolve) => { return new Promise((resolve) => {
if (prefObj === this.defaults) { if (prefObj === this.defaults) {
let keysToRemove = Object.keys(this.defaults); let keysToRemove = Object.keys(this.defaults);
@ -317,7 +317,7 @@ class ChromePreferences extends BasePreferences {
}); });
} }
_readFromStorage(prefObj) { async _readFromStorage(prefObj) {
return new Promise((resolve) => { return new Promise((resolve) => {
let getPreferences = (defaultPrefs) => { let getPreferences = (defaultPrefs) => {
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {

View File

@ -124,13 +124,13 @@ class DownloadManager {
} }
class FirefoxPreferences extends BasePreferences { class FirefoxPreferences extends BasePreferences {
_writeToStorage(prefObj) { async _writeToStorage(prefObj) {
return new Promise(function(resolve) { return new Promise(function(resolve) {
FirefoxCom.request('setPreferences', prefObj, resolve); FirefoxCom.request('setPreferences', prefObj, resolve);
}); });
} }
_readFromStorage(prefObj) { async _readFromStorage(prefObj) {
return new Promise(function(resolve) { return new Promise(function(resolve) {
FirefoxCom.request('getPreferences', prefObj, function(prefStr) { FirefoxCom.request('getPreferences', prefObj, function(prefStr) {
let readPrefs = JSON.parse(prefStr); let readPrefs = JSON.parse(prefStr);
@ -145,21 +145,20 @@ class MozL10n {
this.mozL10n = mozL10n; this.mozL10n = mozL10n;
} }
getLanguage() { async getLanguage() {
return Promise.resolve(this.mozL10n.getLanguage()); return this.mozL10n.getLanguage();
} }
getDirection() { async getDirection() {
return Promise.resolve(this.mozL10n.getDirection()); return this.mozL10n.getDirection();
} }
get(property, args, fallback) { async get(property, args, fallback) {
return Promise.resolve(this.mozL10n.get(property, args, fallback)); return this.mozL10n.get(property, args, fallback);
} }
translate(element) { async translate(element) {
this.mozL10n.translate(element); this.mozL10n.translate(element);
return Promise.resolve();
} }
} }

View File

@ -26,18 +26,12 @@ if (typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('GENERIC')) {
let GenericCom = {}; let GenericCom = {};
class GenericPreferences extends BasePreferences { class GenericPreferences extends BasePreferences {
_writeToStorage(prefObj) { async _writeToStorage(prefObj) {
return new Promise(function(resolve) { localStorage.setItem('pdfjs.preferences', JSON.stringify(prefObj));
localStorage.setItem('pdfjs.preferences', JSON.stringify(prefObj));
resolve();
});
} }
_readFromStorage(prefObj) { async _readFromStorage(prefObj) {
return new Promise(function(resolve) { return JSON.parse(localStorage.getItem('pdfjs.preferences'));
let readPrefs = JSON.parse(localStorage.getItem('pdfjs.preferences'));
resolve(readPrefs);
});
} }
} }

View File

@ -27,28 +27,24 @@ class GenericL10n {
}); });
} }
getLanguage() { async getLanguage() {
return this._ready.then((l10n) => { const l10n = await this._ready;
return l10n.getLanguage(); return l10n.getLanguage();
});
} }
getDirection() { async getDirection() {
return this._ready.then((l10n) => { const l10n = await this._ready;
return l10n.getDirection(); return l10n.getDirection();
});
} }
get(property, args, fallback) { async get(property, args, fallback) {
return this._ready.then((l10n) => { const l10n = await this._ready;
return l10n.get(property, args, fallback); return l10n.get(property, args, fallback);
});
} }
translate(element) { async translate(element) {
return this._ready.then((l10n) => { const l10n = await this._ready;
return l10n.translate(element); return l10n.translate(element);
});
} }
} }

View File

@ -163,12 +163,12 @@ class IL10n {
/** /**
* @returns {Promise<string>} - Resolves to the current locale. * @returns {Promise<string>} - Resolves to the current locale.
*/ */
getLanguage() {} async getLanguage() {}
/** /**
* @returns {Promise<string>} - Resolves to 'rtl' or 'ltr'. * @returns {Promise<string>} - Resolves to 'rtl' or 'ltr'.
*/ */
getDirection() {} async getDirection() {}
/** /**
* Translates text identified by the key and adds/formats data using the args * Translates text identified by the key and adds/formats data using the args
@ -179,12 +179,12 @@ class IL10n {
* @param {string} fallback * @param {string} fallback
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
get(key, args, fallback) { } async get(key, args, fallback) { }
/** /**
* Translates HTML element. * Translates HTML element.
* @param {HTMLElement} element * @param {HTMLElement} element
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
translate(element) { } async translate(element) { }
} }

View File

@ -37,22 +37,20 @@ class OverlayManager {
* @returns {Promise} A promise that is resolved when the overlay has been * @returns {Promise} A promise that is resolved when the overlay has been
* registered. * registered.
*/ */
register(name, element, callerCloseMethod = null, canForceClose = false) { async register(name, element, callerCloseMethod = null,
return new Promise((resolve) => { canForceClose = false) {
let container; let container;
if (!name || !element || !(container = element.parentNode)) { if (!name || !element || !(container = element.parentNode)) {
throw new Error('Not enough parameters.'); throw new Error('Not enough parameters.');
} else if (this._overlays[name]) { } else if (this._overlays[name]) {
throw new Error('The overlay is already registered.'); throw new Error('The overlay is already registered.');
} }
this._overlays[name] = { this._overlays[name] = {
element, element,
container, container,
callerCloseMethod, callerCloseMethod,
canForceClose, canForceClose,
}; };
resolve();
});
} }
/** /**
@ -60,16 +58,13 @@ class OverlayManager {
* @returns {Promise} A promise that is resolved when the overlay has been * @returns {Promise} A promise that is resolved when the overlay has been
* unregistered. * unregistered.
*/ */
unregister(name) { async unregister(name) {
return new Promise((resolve) => { if (!this._overlays[name]) {
if (!this._overlays[name]) { throw new Error('The overlay does not exist.');
throw new Error('The overlay does not exist.'); } else if (this._active === name) {
} else if (this._active === name) { throw new Error('The overlay cannot be removed while it is active.');
throw new Error('The overlay cannot be removed while it is active.'); }
} delete this._overlays[name];
delete this._overlays[name];
resolve();
});
} }
/** /**
@ -77,26 +72,23 @@ class OverlayManager {
* @returns {Promise} A promise that is resolved when the overlay has been * @returns {Promise} A promise that is resolved when the overlay has been
* opened. * opened.
*/ */
open(name) { async open(name) {
return new Promise((resolve) => { if (!this._overlays[name]) {
if (!this._overlays[name]) { throw new Error('The overlay does not exist.');
throw new Error('The overlay does not exist.'); } else if (this._active) {
} else if (this._active) { if (this._overlays[name].canForceClose) {
if (this._overlays[name].canForceClose) { this._closeThroughCaller();
this._closeThroughCaller(); } else if (this._active === name) {
} else if (this._active === name) { throw new Error('The overlay is already active.');
throw new Error('The overlay is already active.'); } else {
} else { throw new Error('Another overlay is currently active.');
throw new Error('Another overlay is currently active.');
}
} }
this._active = name; }
this._overlays[this._active].element.classList.remove('hidden'); this._active = name;
this._overlays[this._active].container.classList.remove('hidden'); this._overlays[this._active].element.classList.remove('hidden');
this._overlays[this._active].container.classList.remove('hidden');
window.addEventListener('keydown', this._keyDownBound); window.addEventListener('keydown', this._keyDownBound);
resolve();
});
} }
/** /**
@ -104,22 +96,19 @@ class OverlayManager {
* @returns {Promise} A promise that is resolved when the overlay has been * @returns {Promise} A promise that is resolved when the overlay has been
* closed. * closed.
*/ */
close(name) { async close(name) {
return new Promise((resolve) => { if (!this._overlays[name]) {
if (!this._overlays[name]) { throw new Error('The overlay does not exist.');
throw new Error('The overlay does not exist.'); } else if (!this._active) {
} else if (!this._active) { throw new Error('The overlay is currently not active.');
throw new Error('The overlay is currently not active.'); } else if (this._active !== name) {
} else if (this._active !== name) { throw new Error('Another overlay is currently active.');
throw new Error('Another overlay is currently active.'); }
} this._overlays[this._active].container.classList.add('hidden');
this._overlays[this._active].container.classList.add('hidden'); this._overlays[this._active].element.classList.add('hidden');
this._overlays[this._active].element.classList.add('hidden'); this._active = null;
this._active = null;
window.removeEventListener('keydown', this._keyDownBound); window.removeEventListener('keydown', this._keyDownBound);
resolve();
});
} }
/** /**

View File

@ -83,8 +83,8 @@ class BasePreferences {
* @return {Promise} A promise that is resolved when the preference values * @return {Promise} A promise that is resolved when the preference values
* have been written. * have been written.
*/ */
_writeToStorage(prefObj) { async _writeToStorage(prefObj) {
return Promise.reject(new Error('Not implemented: _writeToStorage')); throw new Error('Not implemented: _writeToStorage');
} }
/** /**
@ -93,8 +93,8 @@ class BasePreferences {
* @return {Promise} A promise that is resolved with an {Object} containing * @return {Promise} A promise that is resolved with an {Object} containing
* the preferences that have been read. * the preferences that have been read.
*/ */
_readFromStorage(prefObj) { async _readFromStorage(prefObj) {
return Promise.reject(new Error('Not implemented: _readFromStorage')); throw new Error('Not implemented: _readFromStorage');
} }
/** /**
@ -102,11 +102,10 @@ class BasePreferences {
* @return {Promise} A promise that is resolved when the preference values * @return {Promise} A promise that is resolved when the preference values
* have been reset. * have been reset.
*/ */
reset() { async reset() {
return this._initializedPromise.then(() => { await this._initializedPromise;
this.prefs = Object.assign(Object.create(null), this.defaults); this.prefs = Object.assign(Object.create(null), this.defaults);
return this._writeToStorage(this.defaults); return this._writeToStorage(this.defaults);
});
} }
/** /**
@ -116,31 +115,32 @@ class BasePreferences {
* @return {Promise} A promise that is resolved when the value has been set, * @return {Promise} A promise that is resolved when the value has been set,
* provided that the preference exists and the types match. * provided that the preference exists and the types match.
*/ */
set(name, value) { async set(name, value) {
return this._initializedPromise.then(() => { await this._initializedPromise;
if (this.defaults[name] === undefined) { let defaultValue = this.defaults[name];
throw new Error(`Set preference: "${name}" is undefined.`);
} else if (value === undefined) {
throw new Error('Set preference: no value is specified.');
}
let valueType = typeof value;
let defaultType = typeof this.defaults[name];
if (valueType !== defaultType) { if (defaultValue === undefined) {
if (valueType === 'number' && defaultType === 'string') { throw new Error(`Set preference: "${name}" is undefined.`);
value = value.toString(); } else if (value === undefined) {
} else { throw new Error('Set preference: no value is specified.');
throw new Error(`Set preference: "${value}" is a ${valueType}, ` + }
`expected a ${defaultType}.`); let valueType = typeof value;
} let defaultType = typeof defaultValue;
if (valueType !== defaultType) {
if (valueType === 'number' && defaultType === 'string') {
value = value.toString();
} else { } else {
if (valueType === 'number' && !Number.isInteger(value)) { throw new Error(`Set preference: "${value}" is a ${valueType}, ` +
throw new Error(`Set preference: "${value}" must be an integer.`); `expected a ${defaultType}.`);
}
} }
this.prefs[name] = value; } else {
return this._writeToStorage(this.prefs); if (valueType === 'number' && !Number.isInteger(value)) {
}); throw new Error(`Set preference: "${value}" must be an integer.`);
}
}
this.prefs[name] = value;
return this._writeToStorage(this.prefs);
} }
/** /**
@ -149,21 +149,20 @@ class BasePreferences {
* @return {Promise} A promise that is resolved with a {boolean|number|string} * @return {Promise} A promise that is resolved with a {boolean|number|string}
* containing the value of the preference. * containing the value of the preference.
*/ */
get(name) { async get(name) {
return this._initializedPromise.then(() => { await this._initializedPromise;
let defaultValue = this.defaults[name]; let defaultValue = this.defaults[name];
if (defaultValue === undefined) { if (defaultValue === undefined) {
throw new Error(`Get preference: "${name}" is undefined.`); throw new Error(`Get preference: "${name}" is undefined.`);
} else { } else {
let prefValue = this.prefs[name]; let prefValue = this.prefs[name];
if (prefValue !== undefined) { if (prefValue !== undefined) {
return prefValue; return prefValue;
}
} }
return defaultValue; }
}); return defaultValue;
} }
/** /**
@ -171,10 +170,9 @@ class BasePreferences {
* @return {Promise} A promise that is resolved with an {Object} containing * @return {Promise} A promise that is resolved with an {Object} containing
* the values of all preferences. * the values of all preferences.
*/ */
getAll() { async getAll() {
return this._initializedPromise.then(() => { await this._initializedPromise;
return Object.assign(Object.create(null), this.defaults, this.prefs); return Object.assign(Object.create(null), this.defaults, this.prefs);
});
} }
} }

View File

@ -56,21 +56,19 @@ function formatL10nValue(text, args) {
* @implements {IL10n} * @implements {IL10n}
*/ */
let NullL10n = { let NullL10n = {
getLanguage() { async getLanguage() {
return Promise.resolve('en-us'); return 'en-us';
}, },
getDirection() { async getDirection() {
return Promise.resolve('ltr'); return 'ltr';
}, },
get(property, args, fallback) { async get(property, args, fallback) {
return Promise.resolve(formatL10nValue(fallback, args)); return formatL10nValue(fallback, args);
}, },
translate(element) { async translate(element) { },
return Promise.resolve();
},
}; };
/** /**

View File

@ -54,64 +54,54 @@ class ViewHistory {
}); });
} }
_writeToStorage() { async _writeToStorage() {
return new Promise((resolve) => { let databaseStr = JSON.stringify(this.database);
let databaseStr = JSON.stringify(this.database);
if (typeof PDFJSDev !== 'undefined' && if (typeof PDFJSDev !== 'undefined' &&
PDFJSDev.test('FIREFOX || MOZCENTRAL')) { PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
sessionStorage.setItem('pdfjs.history', databaseStr); sessionStorage.setItem('pdfjs.history', databaseStr);
} else { return;
localStorage.setItem('pdfjs.history', databaseStr); }
} localStorage.setItem('pdfjs.history', databaseStr);
resolve();
});
} }
_readFromStorage() { async _readFromStorage() {
return new Promise(function(resolve) { if (typeof PDFJSDev !== 'undefined' &&
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
PDFJSDev.test('FIREFOX || MOZCENTRAL')) { return sessionStorage.getItem('pdfjs.history');
resolve(sessionStorage.getItem('pdfjs.history')); }
} else { return localStorage.getItem('pdfjs.history');
resolve(localStorage.getItem('pdfjs.history'));
}
});
} }
set(name, val) { async set(name, val) {
return this._initializedPromise.then(() => { await this._initializedPromise;
this.file[name] = val; this.file[name] = val;
return this._writeToStorage(); return this._writeToStorage();
});
} }
setMultiple(properties) { async setMultiple(properties) {
return this._initializedPromise.then(() => { await this._initializedPromise;
for (let name in properties) { for (let name in properties) {
this.file[name] = properties[name]; this.file[name] = properties[name];
} }
return this._writeToStorage(); return this._writeToStorage();
});
} }
get(name, defaultValue) { async get(name, defaultValue) {
return this._initializedPromise.then(() => { await this._initializedPromise;
let val = this.file[name];
return val !== undefined ? val : defaultValue;
}
async getMultiple(properties) {
await this._initializedPromise;
let values = Object.create(null);
for (let name in properties) {
let val = this.file[name]; let val = this.file[name];
return val !== undefined ? val : defaultValue; values[name] = val !== undefined ? val : properties[name];
}); }
} return values;
getMultiple(properties) {
return this._initializedPromise.then(() => {
let values = Object.create(null);
for (let name in properties) {
let val = this.file[name];
values[name] = val !== undefined ? val : properties[name];
}
return values;
});
} }
} }