Skip to content

Commit

Permalink
feat(pdf): Update pdf.js options to reflect api changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jstoffan committed Aug 15, 2019
1 parent 40fe6c7 commit 113b3d6
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 272 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
"test:e2e:open": "npm-run-all -p -r start:dev cy:open",
"test:watch": "yarn test --no-single-run --auto-watch",
"upgrade:annotations": "./build/upgrade_annotations.sh",
"upgrade-pdfjs": "./build/upgrade_pdfjs.sh"
"upgrade:pdfjs": "./build/upgrade_pdfjs.sh"
},
"browserslist": [
"last 2 Chrome versions",
Expand Down
141 changes: 72 additions & 69 deletions src/lib/viewers/doc/DocBaseViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,28 @@ const MAX_SCALE = 10.0;
const MIN_PINCH_SCALE_DELTA = 0.01;
const MIN_PINCH_SCALE_VALUE = 0.25;
const MIN_SCALE = 0.1;
const MINIMUM_RANGE_REQUEST_FILE_SIZE_NON_US = 26214400; // 25MB
const METRICS_WHITELIST = [
USER_DOCUMENT_THUMBNAIL_EVENTS.CLOSE,
USER_DOCUMENT_THUMBNAIL_EVENTS.NAVIGATE,
USER_DOCUMENT_THUMBNAIL_EVENTS.OPEN,
];
const MOBILE_MAX_CANVAS_SIZE = 2949120; // ~3MP 1920x1536
const PAGES_UNIT_NAME = 'pages';
const PDFJS_TEXT_LAYER_MODE = {
DISABLE: 0, // Should match TextLayerMode enum in pdf_viewer.js
ENABLE: 1,
ENABLE_ENHANCE: 2,
};
const PINCH_PAGE_CLASS = 'pinch-page';
const PINCHING_CLASS = 'pinching';
const PRINT_DIALOG_TIMEOUT_MS = 500;
const RANGE_REQUEST_CHUNK_SIZE_NON_US = 524288; // 512KB
const RANGE_REQUEST_CHUNK_SIZE_US = 1048576; // 1MB
const RANGE_CHUNK_SIZE_NON_US = 524288; // 512KB
const RANGE_CHUNK_SIZE_US = 1048576; // 1MB
const RANGE_REQUEST_MINIMUM_SIZE = 26214400; // 25MB
const SAFARI_PRINT_TIMEOUT_MS = 1000; // Wait 1s before trying to print
const SCROLL_EVENT_THROTTLE_INTERVAL = 200;
const THUMBNAILS_SIDEBAR_TRANSITION_TIME = 301; // 301ms
const THUMBNAILS_SIDEBAR_TOGGLED_MAP_KEY = 'doc-thumbnails-toggled-map';
// List of metrics to be emitted only once per session
const METRICS_WHITELIST = [
USER_DOCUMENT_THUMBNAIL_EVENTS.CLOSE,
USER_DOCUMENT_THUMBNAIL_EVENTS.NAVIGATE,
USER_DOCUMENT_THUMBNAIL_EVENTS.OPEN,
];

class DocBaseViewer extends BaseViewer {
//--------------------------------------------------------------------------
Expand Down Expand Up @@ -608,6 +612,7 @@ class DocBaseViewer extends BaseViewer {
*/
initViewer(pdfUrl) {
this.bindDOMListeners();
this.startLoadTimer();

this.pdfEventBus = new this.pdfjsViewer.EventBus();
this.pdfEventBus.on('pagechanging', this.pagechangingHandler);
Expand All @@ -629,43 +634,54 @@ class DocBaseViewer extends BaseViewer {
this.pdfViewer = this.initPdfViewer();
this.pdfLinkService.setViewer(this.pdfViewer);

// If range requests are disabled, request the gzip compressed version of the representation
this.encoding = this.pdfjsLib.disableRange ? ENCODING_TYPES.GZIP : undefined;

// Use chunk size set in viewer options if available
let rangeChunkSize = this.getViewerOption('rangeChunkSize');

// Otherwise, use large chunk size if locale is en-US and the default,
// smaller chunk size if not. This is using a rough assumption that
// en-US users have higher bandwidth to Box.
if (!rangeChunkSize) {
rangeChunkSize =
this.options.location.locale === 'en-US'
? RANGE_REQUEST_CHUNK_SIZE_US
: RANGE_REQUEST_CHUNK_SIZE_NON_US;
}

const { file, location } = this.options;
const { size, watermark_info: watermarkInfo } = file;
const assetUrlCreator = createAssetUrlCreator(location);
const httpHeaders = {};
const queryParams = {};

// Do not disable create object URL in IE11 or iOS Chrome - pdf.js issues #3977 and #8081 are
// not applicable to Box's use case and disabling causes performance issues
const disableCreateObjectURL = false;

// Disable font faces on IOS 10.3.X
const disableFontFace = Browser.hasFontIssue();

// Disable streaming via fetch until performance is improved
const disableStream = true;

// Disable range requests for files smaller than MINIMUM_RANGE_REQUEST_FILE_SIZE (25MB) for
// previews outside of the US since the additional latency overhead per range request can be
// more than the additional time for a continuous request.
const isRangeSupported = location.locale !== 'en-US' && size > RANGE_REQUEST_MINIMUM_SIZE;
const isWatermarked = watermarkInfo && watermarkInfo.is_watermarked;
const disableRange = isWatermarked || !isRangeSupported;

// Use larger chunk sizes because we assume that en-US users have better connections to Box's servers
const rangeChunkSizeDefault = location.locale === 'en-US' ? RANGE_CHUNK_SIZE_US : RANGE_CHUNK_SIZE_NON_US;
const rangeChunkSize = this.getViewerOption('rangeChunkSize') || rangeChunkSizeDefault;

// Fix incorrectly cached range requests on older versions of iOS webkit browsers,
// see: https://bugs.webkit.org/show_bug.cgi?id=82672
if (Browser.isIOS()) {
httpHeaders['If-None-Match'] = 'webkit-no-cache';
}

const queryParams = {};
// If range requests are disabled, request the gzip compressed version of the representation
this.encoding = disableRange ? ENCODING_TYPES.GZIP : undefined;

if (this.encoding) {
queryParams[QUERY_PARAM_ENCODING] = this.encoding;
}

// Start timing document load
this.startLoadTimer();

// Load PDF from representation URL and set as document for pdf.js. Cache task for destruction
this.pdfLoadingTask = this.pdfjsLib.getDocument({
cMapPacked: true,
cMapUrl: this.pdfJsCmapUrl,
cMapUrl: assetUrlCreator(`third-party/doc/${DOC_STATIC_ASSETS_VERSION}/cmaps/`),
disableCreateObjectURL,
disableFontFace,
disableRange,
disableStream,
httpHeaders,
rangeChunkSize,
url: appendQueryParams(pdfUrl, queryParams),
Expand Down Expand Up @@ -703,19 +719,37 @@ class DocBaseViewer extends BaseViewer {
}

/**
* Initialize pdf.js viewer.
* Initialize the pdf.js viewer.
*
* @protected
* @override
* @return {pdfjsViewer.PDFViewer} PDF viewer type
*/
initPdfViewer() {
return new this.pdfjsViewer.PDFViewer({
return this.initPdfViewerClass(this.pdfjsViewer.PDFViewer);
}

/**
* Initialize the inner pdf.js viewer class.
*
* @protected
* @param {Function} PdfViewerClass - the pdf viewer class (PDFViewer, PDFSinglePageViewer, etc.) to initailize
* @returns {*}
*/
initPdfViewerClass(PdfViewerClass) {
const { file, location } = this.options;
const assetUrlCreator = createAssetUrlCreator(location);
const hasDownload = checkPermission(file, PERMISSION_DOWNLOAD);
const hasTextLayer = hasDownload && !this.getViewerOption('disableTextLayer');
const textLayerMode = this.isMobile ? PDFJS_TEXT_LAYER_MODE.ENABLE : PDFJS_TEXT_LAYER_MODE.ENABLE_ENHANCE;

return new PdfViewerClass({
container: this.docEl,
enhanceTextSelection: !this.isMobile, // Uses more memory, so disable on mobile
eventBus: this.pdfEventBus,
findController: this.pdfFindController,
imageResourcesPath: assetUrlCreator(`third-party/doc/${DOC_STATIC_ASSETS_VERSION}/images/`),
linkService: this.pdfLinkService,
maxCanvasPixels: this.isMobile ? MOBILE_MAX_CANVAS_SIZE : -1,
textLayerMode: hasTextLayer ? textLayerMode : PDFJS_TEXT_LAYER_MODE.DISABLE,
});
}

Expand Down Expand Up @@ -833,43 +867,12 @@ class DocBaseViewer extends BaseViewer {
this.pdfjsLib = window.pdfjsLib;
this.pdfjsViewer = window.pdfjsViewer;

// Set pdf.js worker & character maps
const { file, location } = this.options;
const { size, watermark_info: watermarkInfo } = file;
// Set pdf.js worker source location
const { location } = this.options;
const assetUrlCreator = createAssetUrlCreator(location);
const workerSrc = assetUrlCreator(`third-party/doc/${DOC_STATIC_ASSETS_VERSION}/pdf.worker.min.js`);

// Set pdf.js worker, image, and character map locations
this.pdfJsCmapUrl = `${location.staticBaseURI}third-party/doc/${DOC_STATIC_ASSETS_VERSION}/cmaps/`;
this.pdfjsLib.imageResourcesPath = assetUrlCreator(`third-party/doc/${DOC_STATIC_ASSETS_VERSION}/images/`);
this.pdfjsLib.workerSrc = assetUrlCreator(`third-party/doc/${DOC_STATIC_ASSETS_VERSION}/pdf.worker.min.js`);

// Disable streaming via fetch until performance is improved
this.pdfjsLib.disableStream = true;

// Disable font faces on IOS 10.3.X
// @NOTE(JustinHoldstock) 2017-04-11: Check to remove this after next IOS release after 10.3.1
this.pdfjsLib.disableFontFace = this.pdfjsLib.disableFontFace || Browser.hasFontIssue();

// Disable range requests for files smaller than MINIMUM_RANGE_REQUEST_FILE_SIZE (25MB) for
// previews outside of the US since the additional latency overhead per range request can be
// more than the additional time for a continuous request. This also overrides any range request
// disabling that may be set by pdf.js's compatibility checking since the browsers we support
// should all be able to properly handle range requests.
this.pdfjsLib.disableRange = location.locale !== 'en-US' && size < MINIMUM_RANGE_REQUEST_FILE_SIZE_NON_US;

// Disable range requests for watermarked files since they are streamed
this.pdfjsLib.disableRange = this.pdfjsLib.disableRange || (watermarkInfo && watermarkInfo.is_watermarked);

// Disable text layer if user doesn't have download permissions
this.pdfjsLib.disableTextLayer =
!checkPermission(file, PERMISSION_DOWNLOAD) || !!this.getViewerOption('disableTextLayer');

// Decrease mobile canvas size to ~3MP (1920x1536)
this.pdfjsLib.maxCanvasPixels = this.isMobile ? MOBILE_MAX_CANVAS_SIZE : this.pdfjsLib.maxCanvasPixels;

// Do not disable create object URL in IE11 or iOS Chrome - pdf.js issues #3977 and #8081 are
// not applicable to Box's use case and disabling causes performance issues
this.pdfjsLib.disableCreateObjectURL = false;
this.pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
}

/**
Expand Down
8 changes: 1 addition & 7 deletions src/lib/viewers/doc/SinglePageViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ class SinglePageViewer extends DocumentViewer {
* @return {Object} PDF viewer type
*/
initPdfViewer() {
return new this.pdfjsViewer.PDFSinglePageViewer({
container: this.docEl,
enhanceTextSelection: !this.isMobile, // Uses more memory, so disable on mobile
eventBus: this.pdfEventBus,
findController: this.pdfFindController,
linkService: this.pdfLinkService,
});
return this.initPdfViewerClass(this.pdfjsViewer.PDFSinglePageViewer);
}
}

Expand Down
Loading

0 comments on commit 113b3d6

Please sign in to comment.