summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources/pdf
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-23 17:21:03 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-23 16:25:15 +0000
commitc551f43206405019121bd2b2c93714319a0a3300 (patch)
tree1f48c30631c421fd4bbb3c36da20183c8a2ed7d7 /chromium/chrome/browser/resources/pdf
parent7961cea6d1041e3e454dae6a1da660b453efd238 (diff)
BASELINE: Update Chromium to 79.0.3945.139
Change-Id: I336b7182fab9bca80b709682489c07db112eaca5 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/pdf')
-rw-r--r--chromium/chrome/browser/resources/pdf/BUILD.gn57
-rw-r--r--chromium/chrome/browser/resources/pdf/annotation_tool.js15
-rw-r--r--chromium/chrome/browser/resources/pdf/controller.js494
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/BUILD.gn118
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js)19
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn19
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html)10
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js)3
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn20
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.js)5
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/BUILD.gn14
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js)1
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn15
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.js)0
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html)2
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js (renamed from chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js)8
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn25
-rw-r--r--chromium/chrome/browser/resources/pdf/index.html17
-rw-r--r--chromium/chrome/browser/resources/pdf/ink/BUILD.gn3
-rw-r--r--chromium/chrome/browser/resources/pdf/ink/ink_api.js11
-rw-r--r--chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js13
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf_scripting_api.js185
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf_viewer.js1482
-rw-r--r--chromium/chrome/browser/resources/pdf/toolbar_manager.js147
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport.js22
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport_scroller.js83
48 files changed, 1614 insertions, 1278 deletions
diff --git a/chromium/chrome/browser/resources/pdf/BUILD.gn b/chromium/chrome/browser/resources/pdf/BUILD.gn
index 89a0223ca86..079381842d8 100644
--- a/chromium/chrome/browser/resources/pdf/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/BUILD.gn
@@ -4,28 +4,19 @@
import("//third_party/closure_compiler/compile_js.gni")
-# TODO(dpapad): Add compile targets for all files, crbug.com/721073.
group("closure_compile") {
deps = [
":pdf_resources",
- "elements/viewer-bookmark:closure_compile",
- "elements/viewer-error-screen:closure_compile",
- "elements/viewer-form-warning:closure_compile",
- "elements/viewer-page-indicator:closure_compile",
- "elements/viewer-page-selector:closure_compile",
- "elements/viewer-password-screen:closure_compile",
- "elements/viewer-pdf-toolbar:closure_compile",
- "elements/viewer-toolbar-dropdown:closure_compile",
- "elements/viewer-zoom-toolbar:closure_compile",
+ "elements:closure_compile",
]
if (is_chromeos) {
- deps += [
- "elements/viewer-ink-host:closure_compile",
- "ink:closure_compile",
- ]
+ deps += [ "ink:closure_compile" ]
}
}
+js_library("annotation_tool") {
+}
+
js_library("browser_api") {
deps = [
"//ui/webui/resources/js:assert",
@@ -86,15 +77,53 @@ js_library("navigator") {
]
}
+js_library("toolbar_manager") {
+ deps = [
+ "elements:viewer-pdf-toolbar",
+ "elements:viewer-zoom-toolbar",
+ ]
+}
+
+js_library("controller") {
+ deps = [
+ ":annotation_tool",
+ ":viewport",
+ "elements:viewer-pdf-toolbar",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js/cr:event_target",
+ ]
+}
+
+js_library("pdf_viewer") {
+ deps = [
+ ":controller",
+ ":navigator",
+ ":toolbar_manager",
+ ":viewport",
+ "elements:viewer-bookmark",
+ "elements:viewer-error-screen",
+ "elements:viewer-page-indicator",
+ "elements:viewer-password-screen",
+ "elements:viewer-pdf-toolbar",
+ "elements:viewer-zoom-toolbar",
+ "//ui/webui/resources/js:event_tracker",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+ externs_list = [ "$externs_path/resources_private.js" ]
+}
+
js_type_check("pdf_resources") {
deps = [
":browser_api",
+ ":controller",
":gesture_detector",
":metrics",
":navigator",
":open_pdf_params_parser",
":pdf_fitting_type",
":pdf_scripting_api",
+ ":pdf_viewer",
+ ":toolbar_manager",
":viewport",
":viewport_scroller",
":zoom_manager",
diff --git a/chromium/chrome/browser/resources/pdf/annotation_tool.js b/chromium/chrome/browser/resources/pdf/annotation_tool.js
new file mode 100644
index 00000000000..5e887b048b7
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/annotation_tool.js
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @fileoverview This file is not included in the build. Only used for type
+// checking purposes.
+
+/**
+ * @typedef {{
+ * tool: string,
+ * size: number,
+ * color: (string|null),
+ * }}
+ */
+let AnnotationTool;
diff --git a/chromium/chrome/browser/resources/pdf/controller.js b/chromium/chrome/browser/resources/pdf/controller.js
new file mode 100644
index 00000000000..ea790f32d0f
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/controller.js
@@ -0,0 +1,494 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/** @typedef {{ type: string }} */
+let MessageData;
+
+/**
+ * @typedef {{
+ * dataToSave: Array,
+ * token: string,
+ * fileName: string
+ * }}
+ */
+let SaveDataMessageData;
+
+/**
+ * @typedef {{
+ * type: string,
+ * to: string,
+ * cc: string,
+ * bcc: string,
+ * subject: string,
+ * body: string,
+ * }}
+ */
+let EmailMessageData;
+
+/**
+ * @typedef {{
+ * type: string,
+ * url: string,
+ * grayscale: boolean,
+ * modifiable: boolean,
+ * pageNumbers: !Array<number>
+ * }}
+ */
+let PrintPreviewParams;
+
+// Note: Redefining this type here, to work around the fact that ink externs
+// are only available on Chrome OS, so the targets that contain them cannot be
+// built on other platforms.
+// TODO (rbpotter): Break InkController into its own file that is only included
+// on Chrome OS.
+
+/**
+ * @typedef {{
+ * setAnnotationTool: function(AnnotationTool):void,
+ * viewportChanged: function():void,
+ * saveDocument: function():!Promise,
+ * undo: function():void,
+ * redo: function():void,
+ * load: function(string, !ArrayBuffer):!Promise,
+ * viewport: !Viewport,
+ * }}
+ */
+let ViewerInkHostElement;
+
+/**
+ * Creates a cryptographically secure pseudorandom 128-bit token.
+ * @return {string} The generated token as a hex string.
+ */
+function createToken() {
+ const randomBytes = new Uint8Array(16);
+ return window.crypto.getRandomValues(randomBytes)
+ .map(b => b.toString(16).padStart(2, '0'))
+ .join('');
+}
+
+/** @abstract */
+class ContentController {
+ constructor() {}
+
+ beforeZoom() {}
+
+ afterZoom() {}
+
+ viewportChanged() {}
+
+ /** @abstract */
+ rotateClockwise() {}
+
+ /** @abstract */
+ rotateCounterclockwise() {}
+
+ /** Triggers printing of the current document. */
+ print() {}
+
+ /** Undo an edit action. */
+ undo() {}
+
+ /** Redo an edit action. */
+ redo() {}
+
+ /**
+ * Requests that the current document be saved.
+ * @param {boolean} requireResult whether a response is required, otherwise
+ * the controller may save the document to disk internally.
+ * @return {Promise<{fileName: string, dataToSave: ArrayBuffer}>}
+ * @abstract
+ */
+ save(requireResult) {}
+
+ /**
+ * Loads PDF document from `data` activates UI.
+ * @param {string} fileName
+ * @param {!ArrayBuffer} data
+ * @return {Promise<void>}
+ * @abstract
+ */
+ load(fileName, data) {}
+
+ /**
+ * Unloads the current document and removes the UI.
+ * @abstract
+ */
+ unload() {}
+}
+
+/**
+ * Controller for annotation mode, on Chrome OS only. Fires the following events
+ * from its event target:
+ * has-unsaved-changes: Fired to indicate there are ink annotations that have
+ * not been saved.
+ * set-annotation-undo-state: Contains information about whether undo or redo
+ * options are available.
+ */
+class InkController extends ContentController {
+ /** @param {!Viewport} viewport */
+ constructor(viewport) {
+ super();
+
+ /** @private {!Viewport} */
+ this.viewport_ = viewport;
+
+ /** @private {?ViewerInkHostElement} */
+ this.inkHost_ = null;
+
+ /** @private {!EventTarget} */
+ this.eventTarget_ = new cr.EventTarget();
+
+ /** @type {?AnnotationTool} */
+ this.tool_ = null;
+ }
+
+ /** @return {!EventTarget} */
+ getEventTarget() {
+ return this.eventTarget_;
+ }
+
+ /** @param {AnnotationTool} tool */
+ setAnnotationTool(tool) {
+ this.tool_ = tool;
+ if (this.inkHost_) {
+ this.inkHost_.setAnnotationTool(tool);
+ }
+ }
+
+ /** @override */
+ rotateClockwise() {
+ // TODO(dstockwell): implement rotation
+ }
+
+ /** @override */
+ rotateCounterclockwise() {
+ // TODO(dstockwell): implement rotation
+ }
+
+ /** @override */
+ viewportChanged() {
+ this.inkHost_.viewportChanged();
+ }
+
+ /** @override */
+ save(requireResult) {
+ return this.inkHost_.saveDocument();
+ }
+
+ /** @override */
+ undo() {
+ this.inkHost_.undo();
+ }
+
+ /** @override */
+ redo() {
+ this.inkHost_.redo();
+ }
+
+ /** @override */
+ load(filename, data) {
+ if (!this.inkHost_) {
+ const inkHost = document.createElement('viewer-ink-host');
+ $('content').appendChild(inkHost);
+ this.inkHost_ = /** @type {!ViewerInkHostElement} */ (inkHost);
+ this.inkHost_.viewport = this.viewport_;
+ inkHost.addEventListener('stroke-added', e => {
+ this.eventTarget_.dispatchEvent(new CustomEvent('has-unsaved-changes'));
+ });
+ inkHost.addEventListener('undo-state-changed', e => {
+ this.eventTarget_.dispatchEvent(
+ new CustomEvent('set-annotation-undo-state', {detail: e.detail}));
+ });
+ }
+ return this.inkHost_.load(filename, data);
+ }
+
+ /** @override */
+ unload() {
+ this.inkHost_.remove();
+ this.inkHost_ = null;
+ }
+}
+
+/**
+ * PDF plugin controller, responsible for communicating with the embedded plugin
+ * element. Dispatches a 'plugin-message' event containing the message from the
+ * plugin, if a message type not handled by this controller is received.
+ */
+class PluginController extends ContentController {
+ /**
+ * @param {!HTMLEmbedElement} plugin
+ * @param {!Viewport} viewport
+ * @param {function():boolean} getIsUserInitiatedCallback
+ * @param {function():?Promise} getLoadedCallback
+ */
+ constructor(plugin, viewport, getIsUserInitiatedCallback, getLoadedCallback) {
+ super();
+
+ /** @private {!HTMLEmbedElement} */
+ this.plugin_ = plugin;
+
+ /** @private {!Viewport} */
+ this.viewport_ = viewport;
+
+ /** @private {!function():boolean} */
+ this.getIsUserInitiatedCallback_ = getIsUserInitiatedCallback;
+
+ /** @private {!function():?Promise} */
+ this.getLoadedCallback_ = getLoadedCallback;
+
+ /** @private {!Map<string, PromiseResolver>} */
+ this.pendingTokens_ = new Map();
+ this.plugin_.addEventListener(
+ 'message', e => this.handlePluginMessage_(e), false);
+
+ /** @private {!EventTarget} */
+ this.eventTarget_ = new cr.EventTarget();
+ }
+
+ /** @return {!EventTarget} */
+ getEventTarget() {
+ return this.eventTarget_;
+ }
+
+ /**
+ * Notify the plugin to stop reacting to scroll events while zoom is taking
+ * place to avoid flickering.
+ * @override
+ */
+ beforeZoom() {
+ this.postMessage_({type: 'stopScrolling'});
+
+ if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) {
+ const position = this.viewport_.position;
+ const zoom = this.viewport_.getZoom();
+ const pinchPhase = this.viewport_.pinchPhase;
+ const layoutOptions = this.viewport_.getLayoutOptions();
+ this.postMessage_({
+ type: 'viewport',
+ userInitiated: true,
+ zoom: zoom,
+ layoutOptions: layoutOptions,
+ xOffset: position.x,
+ yOffset: position.y,
+ pinchPhase: pinchPhase
+ });
+ }
+ }
+
+ /**
+ * Notify the plugin of the zoom change and to continue reacting to scroll
+ * events.
+ * @override
+ */
+ afterZoom() {
+ const position = this.viewport_.position;
+ const zoom = this.viewport_.getZoom();
+ const layoutOptions = this.viewport_.getLayoutOptions();
+ const pinchVector = this.viewport_.pinchPanVector || {x: 0, y: 0};
+ const pinchCenter = this.viewport_.pinchCenter || {x: 0, y: 0};
+ const pinchPhase = this.viewport_.pinchPhase;
+
+ this.postMessage_({
+ type: 'viewport',
+ userInitiated: this.getIsUserInitiatedCallback_(),
+ zoom: zoom,
+ layoutOptions: layoutOptions,
+ xOffset: position.x,
+ yOffset: position.y,
+ pinchPhase: pinchPhase,
+ pinchX: pinchCenter.x,
+ pinchY: pinchCenter.y,
+ pinchVectorX: pinchVector.x,
+ pinchVectorY: pinchVector.y
+ });
+ }
+
+ /**
+ * Post a message to the PPAPI plugin. Some messages will cause an async reply
+ * to be received through handlePluginMessage_().
+ * @param {!MessageData} message Message to post.
+ * @private
+ */
+ postMessage_(message) {
+ this.plugin_.postMessage(message);
+ }
+
+ /** @override */
+ rotateClockwise() {
+ this.postMessage_({type: 'rotateClockwise'});
+ }
+
+ /** @override */
+ rotateCounterclockwise() {
+ this.postMessage_({type: 'rotateCounterclockwise'});
+ }
+
+ /** @override */
+ print() {
+ this.postMessage_({type: 'print'});
+ }
+
+ selectAll() {
+ this.postMessage_({type: 'selectAll'});
+ }
+
+ getSelectedText() {
+ this.postMessage_({type: 'getSelectedText'});
+ }
+
+ /** @param {!PrintPreviewParams} printPreviewParams */
+ resetPrintPreviewMode(printPreviewParams) {
+ this.postMessage_({
+ type: 'resetPrintPreviewMode',
+ url: printPreviewParams.url,
+ grayscale: printPreviewParams.grayscale,
+ // If the PDF isn't modifiable we send 0 as the page count so that no
+ // blank placeholder pages get appended to the PDF.
+ pageCount:
+ (printPreviewParams.modifiable ?
+ printPreviewParams.pageNumbers.length :
+ 0)
+ });
+ }
+
+ /** @param {string} newColor New color, in hex, for the PDF plugin. */
+ backgroundColorChanged(newColor) {
+ this.postMessage_({
+ type: 'backgroundColorChanged',
+ backgroundColor: newColor,
+ });
+ }
+
+ /**
+ * @param {string} url
+ * @param {number} index
+ */
+ loadPreviewPage(url, index) {
+ this.postMessage_({type: 'loadPreviewPage', url: url, index: index});
+ }
+
+ /** @param {string} password */
+ getPasswordComplete(password) {
+ this.postMessage_({type: 'getPasswordComplete', password: password});
+ }
+
+ /** @param {string} destination */
+ getNamedDestination(destination) {
+ this.postMessage_({
+ type: 'getNamedDestination',
+ namedDestination: destination,
+ });
+ }
+
+ /** @override */
+ save(requireResult) {
+ const resolver = new PromiseResolver();
+ const newToken = createToken();
+ this.pendingTokens_.set(newToken, resolver);
+ this.postMessage_({type: 'save', token: newToken, force: requireResult});
+ return resolver.promise;
+ }
+
+ /** @override */
+ async load(fileName, data) {
+ const url = URL.createObjectURL(new Blob([data]));
+ this.plugin_.removeAttribute('headers');
+ this.plugin_.setAttribute('stream-url', url);
+ this.plugin_.style.display = 'block';
+ try {
+ await this.getLoadedCallback_();
+ } finally {
+ URL.revokeObjectURL(url);
+ }
+ }
+
+ /** @override */
+ unload() {
+ this.plugin_.style.display = 'none';
+ }
+
+ /**
+ * An event handler for handling message events received from the plugin.
+ * @param {!Event} messageEvent a message event.
+ * @private
+ */
+ handlePluginMessage_(messageEvent) {
+ const messageData = /** @type {!MessageData} */ (messageEvent.data);
+ switch (messageData.type) {
+ case 'email':
+ const emailData = /** @type {!EmailMessageData} */ (messageData);
+ const href = 'mailto:' + emailData.to + '?cc=' + emailData.cc +
+ '&bcc=' + emailData.bcc + '&subject=' + emailData.subject +
+ '&body=' + emailData.body;
+ window.location.href = href;
+ break;
+ case 'goToPage':
+ this.viewport_.goToPage(
+ /** @type {{type: string, page: number}} */ (messageData).page);
+ break;
+ case 'setScrollPosition':
+ this.viewport_.scrollTo(/** @type {!PartialPoint} */ (messageData));
+ break;
+ case 'scrollBy':
+ this.viewport_.scrollBy(/** @type {!Point} */ (messageData));
+ break;
+ case 'saveData':
+ this.saveData_(/** @type {!SaveDataMessageData} */ (messageData));
+ break;
+ case 'consumeSaveToken':
+ const saveTokenData =
+ /** @type {{ type: string, token: string }} */ (messageData);
+ const resolver = this.pendingTokens_.get(saveTokenData.token);
+ assert(this.pendingTokens_.delete(saveTokenData.token));
+ resolver.resolve(null);
+ break;
+ default:
+ this.eventTarget_.dispatchEvent(
+ new CustomEvent('plugin-message', {detail: messageData}));
+ }
+ }
+
+ /**
+ * Handles the pdf file buffer received from the plugin.
+ *
+ * @param {!SaveDataMessageData} messageData data of the message event.
+ * @private
+ */
+ saveData_(messageData) {
+ assert(
+ loadTimeData.getBoolean('pdfFormSaveEnabled') ||
+ loadTimeData.getBoolean('pdfAnnotationsEnabled'));
+
+ // Verify a token that was created by this instance is included to avoid
+ // being spammed.
+ const resolver = this.pendingTokens_.get(messageData.token);
+ assert(this.pendingTokens_.delete(messageData.token));
+
+ if (!messageData.dataToSave) {
+ resolver.reject();
+ return;
+ }
+
+ // Verify the file size and the first bytes to make sure it's a PDF. Cap at
+ // 100 MB. This cap should be kept in sync with and is also enforced in
+ // pdf/out_of_process_instance.cc.
+ const MIN_FILE_SIZE = '%PDF1.0'.length;
+ const MAX_FILE_SIZE = 100 * 1000 * 1000;
+
+ const buffer = messageData.dataToSave;
+ const bufView = new Uint8Array(buffer);
+ assert(
+ bufView.length <= MAX_FILE_SIZE,
+ `File too large to be saved: ${bufView.length} bytes.`);
+ assert(bufView.length >= MIN_FILE_SIZE);
+ assert(
+ String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) ==
+ '%PDF');
+
+ resolver.resolve(messageData);
+ }
+}
diff --git a/chromium/chrome/browser/resources/pdf/elements/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn
new file mode 100644
index 00000000000..248059ae74f
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -0,0 +1,118 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":viewer-bookmark",
+ ":viewer-error-screen",
+ ":viewer-page-indicator",
+ ":viewer-page-selector",
+ ":viewer-password-screen",
+ ":viewer-pdf-toolbar",
+ ":viewer-toolbar-dropdown",
+ ":viewer-zoom-button",
+ ":viewer-zoom-toolbar",
+ ]
+ if (is_chromeos) {
+ deps += [
+ ":viewer-form-warning",
+ ":viewer-ink-host",
+ ":viewer-pen-options",
+ ]
+ }
+}
+
+js_library("viewer-bookmark") {
+ deps = [
+ "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
+ ]
+}
+
+js_library("viewer-error-screen") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
+ ]
+}
+
+if (is_chromeos) {
+ js_library("viewer-form-warning") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
+ "//ui/webui/resources/js:promise_resolver",
+ ]
+ }
+
+ js_library("viewer-ink-host") {
+ deps = [
+ "//chrome/browser/resources/pdf:metrics",
+ "//chrome/browser/resources/pdf:viewport",
+ "//chrome/browser/resources/pdf/ink:ink_api",
+ ]
+ }
+}
+
+js_library("viewer-page-indicator") {
+ deps = [
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:util",
+ ]
+}
+
+js_library("viewer-page-selector") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ ]
+}
+
+js_library("viewer-password-screen") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ ]
+}
+
+js_library("viewer-pdf-toolbar") {
+ deps = [
+ ":viewer-bookmark",
+ ":viewer-page-selector",
+ ":viewer-toolbar-dropdown",
+ "..:annotation_tool",
+ ]
+ externs_list = [ "$externs_path/pending.js" ]
+}
+
+js_library("viewer-pen-options") {
+ externs_list = [ "$externs_path/pending_polymer.js" ]
+}
+
+js_library("viewer-toolbar-dropdown") {
+ deps = []
+}
+
+js_library("viewer-zoom-toolbar") {
+ deps = [
+ ":viewer-zoom-button",
+ "..:pdf_fitting_type",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:util",
+ ]
+}
+
+js_library("viewer-zoom-button") {
+ deps = []
+}
+
+polymer_modulizer("shared-vars") {
+ js_file = "shared-vars.m.js"
+ html_file = "shared-vars.html"
+ html_type = "custom-style"
+}
+
+group("polymer3_elements") {
+ deps = [
+ ":shared-vars_module",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html
index 004aa1b1677..004aa1b1677 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js
index f1cce48abaa..f25ebcef472 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js
@@ -7,8 +7,9 @@
*
* The bookmark may point at a location in the PDF or a URI.
* If it points at a location, |page| indicates which 0-based page it leads to.
- * Optionally, |y| is the y position in that page, in pixel coordinates.
- * If it points at an URI, |uri| is the target for that bookmark.
+ * Optionally, |x| is the x position in that page, |y| is the y position in that
+ * page, in pixel coordinates and |zoom| is the new zoom value. If it points at
+ * an URI, |uri| is the target for that bookmark.
*
* |children| is an array of the |Bookmark|s that are below this in a table of
* contents tree
@@ -16,7 +17,9 @@
* @typedef {{
* title: string,
* page: (number | undefined),
+ * x: (number | undefined),
* y: (number | undefined),
+ * zoom: (number | undefined),
* uri: (string | undefined),
* children: !Array<!Bookmark>
* }}
@@ -80,11 +83,15 @@ Polymer({
/** @private */
onClick_: function() {
- if (this.bookmark.hasOwnProperty('page')) {
- if (this.bookmark.hasOwnProperty('y')) {
+ if (this.bookmark.page != null) {
+ if (this.bookmark.zoom != null) {
+ this.fire('change-zoom', {zoom: this.bookmark.zoom});
+ }
+ if (this.bookmark.x != null &&
+ this.bookmark.y != null) {
this.fire('change-page-and-xy', {
page: this.bookmark.page,
- x: 0,
+ x: this.bookmark.x,
y: this.bookmark.y,
origin: 'bookmark'
});
@@ -92,7 +99,7 @@ Polymer({
this.fire(
'change-page', {page: this.bookmark.page, origin: 'bookmark'});
}
- } else if (this.bookmark.hasOwnProperty('uri')) {
+ } else if (this.bookmark.uri != null) {
this.fire('navigate', {uri: this.bookmark.uri, newtab: true});
}
},
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/BUILD.gn
deleted file mode 100644
index fa2b15b86f7..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-bookmark",
- ]
-}
-
-js_library("viewer-bookmark") {
- deps = [
- "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html
index 25737d45127..25737d45127 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js
index 082220a4c92..082220a4c92 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/BUILD.gn
deleted file mode 100644
index 3beeb5d21b0..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-error-screen",
- ]
-}
-
-js_library("viewer-error-screen") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.html b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html
index 1e9e1ee4f67..1e9e1ee4f67 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.js b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js
index 539eddd6b67..539eddd6b67 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/viewer-form-warning.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/BUILD.gn
deleted file mode 100644
index e27ead67627..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-form-warning",
- ]
-}
-
-js_library("viewer-form-warning") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
- "//ui/webui/resources/js:promise_resolver",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.html b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.html
index 1a7a2ff73ea..1a7a2ff73ea 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js
index 285edf8a35d..285edf8a35d 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn
deleted file mode 100644
index 32ca2b04311..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-ink-host",
- ]
-}
-
-js_library("viewer-ink-host") {
- deps = [
- "//chrome/browser/resources/pdf:metrics",
- "//chrome/browser/resources/pdf:viewport",
- "//chrome/browser/resources/pdf/ink:ink_api",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html
index 70ad2578685..70ad2578685 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js
index 50ad4f4cb49..50ad4f4cb49 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn
deleted file mode 100644
index aa1906c65e5..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-page-indicator",
- ]
-}
-
-js_library("viewer-page-indicator") {
- deps = [
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:util",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html
index e1fdc869efe..e1fdc869efe 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js
index b7999237a98..b7999237a98 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn
deleted file mode 100644
index 725e3f96591..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-page-selector",
- ]
-}
-
-js_library("viewer-page-selector") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html
index aebc16bf138..aebc16bf138 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js
index 5506ad2915c..5506ad2915c 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/BUILD.gn
deleted file mode 100644
index 5078ae7403f..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-password-screen",
- ]
-}
-
-js_library("viewer-password-screen") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
- ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html
index e183debc86d..348e2215fed 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html
@@ -4,13 +4,13 @@
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="../icons.html">
-<link rel="import" href="../viewer-bookmark/viewer-bookmark.html">
-<link rel="import" href="../viewer-page-selector/viewer-page-selector.html">
+<link rel="import" href="icons.html">
+<link rel="import" href="viewer-bookmark.html">
+<link rel="import" href="viewer-page-selector.html">
<if expr="chromeos">
-<link rel="import" href="../viewer-pen-options/viewer-pen-options.html">
+<link rel="import" href="viewer-pen-options.html">
</if>
-<link rel="import" href="../viewer-toolbar-dropdown/viewer-toolbar-dropdown.html">
+<link rel="import" href="viewer-toolbar-dropdown.html">
<dom-module id="viewer-pdf-toolbar">
<template>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
index afb87dfe6b7..07407cfee75 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
(function() {
Polymer({
is: 'viewer-pdf-toolbar',
@@ -24,7 +25,7 @@ Polymer({
reflectToAttribute: true,
},
- /** @type {?Object} */
+ /** @type {?AnnotationTool} */
annotationTool: {
type: Object,
value: null,
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn
deleted file mode 100644
index fdc650f55b9..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-pdf-toolbar",
- ]
-}
-
-js_library("viewer-pdf-toolbar") {
- deps = [
- "../viewer-bookmark:viewer-bookmark",
- "../viewer-page-selector:viewer-page-selector",
- "../viewer-toolbar-dropdown:viewer-toolbar-dropdown",
- ]
- externs_list = [ "$externs_path/pending.js" ]
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html
index dbf18b0bfda..dbf18b0bfda 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js
index 3970e0ff630..d63343404fb 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/viewer-pen-options.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js
@@ -81,7 +81,7 @@ Polymer({
strings: Object,
},
- /** @type {Array<Animation>} */
+ /** @type {Array<!Animation>} */
expandAnimations_: null,
/** @param {Event} e */
@@ -103,7 +103,8 @@ Polymer({
/** @private */
updateExpandedStateAndFinishAnimations_: function() {
this.updateExpandedState_();
- for (const animation of this.expandAnimations_) {
+ for (const animation of /** @type {!Array<!Animation>} */ (
+ this.expandAnimations_)) {
animation.finish();
}
},
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/BUILD.gn
deleted file mode 100644
index b542932ff9c..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options/BUILD.gn
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-pen-options",
- ]
-}
-
-js_library("viewer-pen-options") {
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html
index 1ebf0df604f..1ebf0df604f 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js
index 00b2b676b45..191f4cfcfbf 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js
@@ -216,5 +216,4 @@ Polymer({
});
}
});
-
})();
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn
deleted file mode 100644
index 7a2ca5ce91a..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-toolbar-dropdown",
- ]
-}
-
-js_library("viewer-toolbar-dropdown") {
- deps = []
-}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
index 000d098cfb3..000d098cfb3 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.js b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js
index 2359900d83c..2359900d83c 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html
index e0f2bdd15ba..0807c5dfe64 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html
@@ -1,7 +1,7 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="../icons.html">
+<link rel="import" href="icons.html">
<link rel="import" href="viewer-zoom-button.html">
<dom-module id="viewer-zoom-toolbar">
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js
index fe24ab64645..fe28ef8c96a 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js
@@ -2,6 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * @typedef {{
+ * fittingType: !FittingType,
+ * userInitiated: boolean,
+ * }}
+ */
+let FitToChangedEvent;
+
(function() {
const FIT_TO_PAGE_BUTTON_STATE = 0;
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn
deleted file mode 100644
index 4c75971c261..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":viewer-zoom-button",
- ":viewer-zoom-toolbar",
- ]
-}
-
-js_library("viewer-zoom-toolbar") {
- deps = [
- ":viewer-zoom-button",
- "../..:pdf_fitting_type",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:util",
- ]
-}
-
-js_library("viewer-zoom-button") {
- deps = []
-}
diff --git a/chromium/chrome/browser/resources/pdf/index.html b/chromium/chrome/browser/resources/pdf/index.html
index 06d219a6c7e..00d96432fd0 100644
--- a/chromium/chrome/browser/resources/pdf/index.html
+++ b/chromium/chrome/browser/resources/pdf/index.html
@@ -4,20 +4,20 @@
<meta charset="utf-8">
<script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js">
</script>
- <link rel="import" href="elements/viewer-error-screen/viewer-error-screen.html">
- <link rel="import" href="elements/viewer-page-indicator/viewer-page-indicator.html">
- <link rel="import" href="elements/viewer-page-selector/viewer-page-selector.html">
- <link rel="import" href="elements/viewer-password-screen/viewer-password-screen.html">
- <link rel="import" href="elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html">
- <link rel="import" href="elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html">
+ <link rel="import" href="elements/viewer-error-screen.html">
+ <link rel="import" href="elements/viewer-page-indicator.html">
+ <link rel="import" href="elements/viewer-page-selector.html">
+ <link rel="import" href="elements/viewer-password-screen.html">
+ <link rel="import" href="elements/viewer-pdf-toolbar.html">
+ <link rel="import" href="elements/viewer-zoom-toolbar.html">
<link rel="import" href="elements/shared-vars.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/html/cr/event_target.html">
<link rel="import" href="chrome://resources/html/event_tracker.html">
<if expr="chromeos">
- <link rel="import" href="elements/viewer-ink-host/viewer-ink-host.html">
- <link rel="import" href="elements/viewer-form-warning/viewer-form-warning.html">
+ <link rel="import" href="elements/viewer-ink-host.html">
+ <link rel="import" href="elements/viewer-form-warning.html">
</if>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
@@ -58,6 +58,7 @@
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="browser_api.js"></script>
<script src="metrics.js"></script>
+<script src="controller.js"></script>
<script src="pdf_viewer.js"></script>
<script src="main.js"></script>
</html>
diff --git a/chromium/chrome/browser/resources/pdf/ink/BUILD.gn b/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
index 38908ee25a1..b1c2be215bd 100644
--- a/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
@@ -11,6 +11,9 @@ js_type_check("closure_compile") {
}
js_library("ink_api") {
+ deps = [
+ "..:annotation_tool",
+ ]
externs_list = [
"//third_party/ink/build/ink_lib_externs.js",
"$externs_path/pending.js",
diff --git a/chromium/chrome/browser/resources/pdf/ink/ink_api.js b/chromium/chrome/browser/resources/pdf/ink/ink_api.js
index 04e0d56dcf6..99eed15d900 100644
--- a/chromium/chrome/browser/resources/pdf/ink/ink_api.js
+++ b/chromium/chrome/browser/resources/pdf/ink/ink_api.js
@@ -4,15 +4,6 @@
/**
* @typedef {{
- * tool: string,
- * size: number,
- * color: string,
- * }}
- */
-let AnnotationTool;
-
-/**
- * @typedef {{
* canUndo: boolean,
* canRedo: boolean,
* }}
@@ -88,7 +79,7 @@ class InkAPI {
}[tool.tool];
this.brush_.setShape(shape);
if (tool.tool != 'eraser') {
- this.brush_.setColor(tool.color);
+ this.brush_.setColor(/** @type {string} */ (tool.color));
}
this.brush_.setStrokeWidth(tool.size);
}
diff --git a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
index d4a502a135f..c33c46b6d75 100644
--- a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
+++ b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
@@ -10,15 +10,15 @@
*/
class OpenPdfParamsParser {
/**
- * @param {function(Object)} postMessageCallback
+ * @param {function(string):void} getNamedDestinationCallback
* Function called to fetch information for a named destination.
*/
- constructor(postMessageCallback) {
+ constructor(getNamedDestinationCallback) {
/** @private {!Array<!Object>} */
this.outstandingRequests_ = [];
- /** @private {!function(Object)} */
- this.postMessageCallback_ = postMessageCallback;
+ /** @private {!function(string):void} */
+ this.getNamedDestinationCallback_ = getNamedDestinationCallback;
}
/**
@@ -181,10 +181,7 @@ class OpenPdfParamsParser {
if (params.page === undefined && 'nameddest' in urlParams) {
this.outstandingRequests_.push({callback: callback, params: params});
- this.postMessageCallback_({
- type: 'getNamedDestination',
- namedDestination: urlParams['nameddest']
- });
+ this.getNamedDestinationCallback_(urlParams['nameddest']);
} else {
callback(params);
}
diff --git a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
index 0ab77f41f3f..5957e13c178 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
+++ b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
@@ -6,7 +6,7 @@
* Turn a dictionary received from postMessage into a key event.
*
* @param {Object} dict A dictionary representing the key event.
- * @return {Event} A key event.
+ * @return {!Event} A key event.
*/
function DeserializeKeyEvent(dict) {
const e = document.createEvent('Event');
@@ -53,66 +53,83 @@ const LoadState = {
* Create a new PDFScriptingAPI. This provides a scripting interface to
* the PDF viewer so that it can be customized by things like print preview.
*
- * @param {Window} window the window of the page containing the pdf viewer.
- * @param {Object} plugin the plugin element containing the pdf viewer.
- * @constructor
*/
-function PDFScriptingAPI(window, plugin) {
- this.loadState_ = LoadState.LOADING;
- this.pendingScriptingMessages_ = [];
- this.setPlugin(plugin);
+class PDFScriptingAPI {
+ /**
+ * @param {Window} window the window of the page containing the pdf viewer.
+ * @param {Object} plugin the plugin element containing the pdf viewer.
+ */
+ constructor(window, plugin) {
+ this.loadState_ = LoadState.LOADING;
+ this.pendingScriptingMessages_ = [];
+ this.setPlugin(plugin);
- window.addEventListener('message', event => {
- if (event.origin != 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai' &&
- event.origin != 'chrome://print') {
- console.error(
- 'Received message that was not from the extension: ' + event);
- return;
- }
- switch (event.data.type) {
- case 'viewport':
- /**
- * @type {{
- * pageX: number,
- * pageY: number,
- * pageWidth: number,
- * viewportWidth: number,
- * viewportHeight: number
- * }}
- */
- const viewportData = event.data;
- if (this.viewportChangedCallback_) {
- this.viewportChangedCallback_(
- viewportData.pageX, viewportData.pageY, viewportData.pageWidth,
- viewportData.viewportWidth, viewportData.viewportHeight);
- }
- break;
- case 'documentLoaded': {
- const data = /** @type {{load_state: LoadState}} */ (event.data);
- this.loadState_ = data.load_state;
- if (this.loadCallback_) {
- this.loadCallback_(this.loadState_ == LoadState.SUCCESS);
- }
- break;
+ /** @private {Function} */
+ this.viewportChangedCallback_;
+
+ /** @private {Function} */
+ this.loadCallback_;
+
+ /** @private {Function} */
+ this.selectedTextCallback_;
+
+ /** @private {Function} */
+ this.keyEventCallback_;
+
+ /** @private {Object} */
+ this.plugin_;
+
+ window.addEventListener('message', event => {
+ if (event.origin !=
+ 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai' &&
+ event.origin != 'chrome://print') {
+ console.error(
+ 'Received message that was not from the extension: ' + event);
+ return;
}
- case 'getSelectedTextReply': {
- const data = /** @type {{selectedText: string}} */ (event.data);
- if (this.selectedTextCallback_) {
- this.selectedTextCallback_(data.selectedText);
- this.selectedTextCallback_ = null;
+ switch (event.data.type) {
+ case 'viewport':
+ /**
+ * @type {{
+ * pageX: number,
+ * pageY: number,
+ * pageWidth: number,
+ * viewportWidth: number,
+ * viewportHeight: number
+ * }}
+ */
+ const viewportData = event.data;
+ if (this.viewportChangedCallback_) {
+ this.viewportChangedCallback_(
+ viewportData.pageX, viewportData.pageY, viewportData.pageWidth,
+ viewportData.viewportWidth, viewportData.viewportHeight);
+ }
+ break;
+ case 'documentLoaded': {
+ const data = /** @type {{load_state: LoadState}} */ (event.data);
+ this.loadState_ = data.load_state;
+ if (this.loadCallback_) {
+ this.loadCallback_(this.loadState_ == LoadState.SUCCESS);
+ }
+ break;
}
- break;
- }
- case 'sendKeyEvent':
- if (this.keyEventCallback_) {
- this.keyEventCallback_(DeserializeKeyEvent(event.data.keyEvent));
+ case 'getSelectedTextReply': {
+ const data = /** @type {{selectedText: string}} */ (event.data);
+ if (this.selectedTextCallback_) {
+ this.selectedTextCallback_(data.selectedText);
+ this.selectedTextCallback_ = null;
+ }
+ break;
}
- break;
- }
- }, false);
-}
+ case 'sendKeyEvent':
+ if (this.keyEventCallback_) {
+ this.keyEventCallback_(DeserializeKeyEvent(event.data.keyEvent));
+ }
+ break;
+ }
+ }, false);
+ }
-PDFScriptingAPI.prototype = {
/**
* Send a message to the extension. If messages try to get sent before there
* is a plugin element set, then we queue them up and send them later (this
@@ -121,13 +138,13 @@ PDFScriptingAPI.prototype = {
* @param {Object} message The message to send.
* @private
*/
- sendMessage_: function(message) {
+ sendMessage_(message) {
if (this.plugin_) {
this.plugin_.postMessage(message, '*');
} else {
this.pendingScriptingMessages_.push(message);
}
- },
+ }
/**
* Sets the plugin element containing the PDF viewer. The element will usually
@@ -135,7 +152,7 @@ PDFScriptingAPI.prototype = {
*
* @param {Object} plugin the plugin element containing the PDF viewer.
*/
- setPlugin: function(plugin) {
+ setPlugin(plugin) {
this.plugin_ = plugin;
if (this.plugin_) {
@@ -147,16 +164,16 @@ PDFScriptingAPI.prototype = {
this.sendMessage_(this.pendingScriptingMessages_.shift());
}
}
- },
+ }
/**
* Sets the callback which will be run when the PDF viewport changes.
*
* @param {Function} callback the callback to be called.
*/
- setViewportChangedCallback: function(callback) {
+ setViewportChangedCallback(callback) {
this.viewportChangedCallback_ = callback;
- },
+ }
/**
* Sets the callback which will be run when the PDF document has finished
@@ -164,20 +181,20 @@ PDFScriptingAPI.prototype = {
*
* @param {Function} callback the callback to be called.
*/
- setLoadCallback: function(callback) {
+ setLoadCallback(callback) {
this.loadCallback_ = callback;
if (this.loadState_ != LoadState.LOADING && this.loadCallback_) {
this.loadCallback_(this.loadState_ == LoadState.SUCCESS);
}
- },
+ }
/**
* Sets a callback that gets run when a key event is fired in the PDF viewer.
* @param {Function} callback the callback to be called with a key event.
*/
- setKeyEventCallback: function(callback) {
+ setKeyEventCallback(callback) {
this.keyEventCallback_ = callback;
- },
+ }
/**
* Resets the PDF viewer into print preview mode.
@@ -187,7 +204,7 @@ PDFScriptingAPI.prototype = {
* @param {Array<number>} pageNumbers an array of the page numbers.
* @param {boolean} modifiable whether or not the document is modifiable.
*/
- resetPrintPreviewMode: function(url, grayscale, pageNumbers, modifiable) {
+ resetPrintPreviewMode(url, grayscale, pageNumbers, modifiable) {
this.loadState_ = LoadState.LOADING;
this.sendMessage_({
type: 'resetPrintPreviewMode',
@@ -196,14 +213,14 @@ PDFScriptingAPI.prototype = {
pageNumbers: pageNumbers,
modifiable: modifiable
});
- },
+ }
/**
* Hide the toolbars after a delay.
*/
- hideToolbars: function() {
+ hideToolbars() {
this.sendMessage_({type: 'hideToolbars'});
- },
+ }
/**
* Load a page into the document while in print preview mode.
@@ -211,22 +228,22 @@ PDFScriptingAPI.prototype = {
* @param {string} url the url of the pdf page to load.
* @param {number} index the index of the page to load.
*/
- loadPreviewPage: function(url, index) {
+ loadPreviewPage(url, index) {
this.sendMessage_({type: 'loadPreviewPage', url: url, index: index});
- },
+ }
/** @param {boolean} darkMode Whether the page is in dark mode. */
- darkModeChanged: function(darkMode) {
+ darkModeChanged(darkMode) {
this.sendMessage_({type: 'darkModeChanged', darkMode: darkMode});
- },
+ }
/**
* Select all the text in the document. May only be called after document
* load.
*/
- selectAll: function() {
+ selectAll() {
this.sendMessage_({type: 'selectAll'});
- },
+ }
/**
* Get the selected text in the document. The callback will be called with the
@@ -236,40 +253,40 @@ PDFScriptingAPI.prototype = {
* @return {boolean} true if the function is successful, false if there is an
* outstanding request for selected text that has not been answered.
*/
- getSelectedText: function(callback) {
+ getSelectedText(callback) {
if (this.selectedTextCallback_) {
return false;
}
this.selectedTextCallback_ = callback;
this.sendMessage_({type: 'getSelectedText'});
return true;
- },
+ }
/**
* Print the document. May only be called after document load.
*/
- print: function() {
+ print() {
this.sendMessage_({type: 'print'});
- },
+ }
/**
* Send a key event to the extension.
*
* @param {Event} keyEvent the key event to send to the extension.
*/
- sendKeyEvent: function(keyEvent) {
+ sendKeyEvent(keyEvent) {
this.sendMessage_(
{type: 'sendKeyEvent', keyEvent: SerializeKeyEvent(keyEvent)});
- },
+ }
/**
* @param {number} scrollX The amount to horizontally scroll in pixels.
* @param {number} scrollY The amount to vertically scroll in pixels.
*/
- scrollPosition: function(scrollX, scrollY) {
+ scrollPosition(scrollX, scrollY) {
this.sendMessage_({type: 'scrollPosition', x: scrollX, y: scrollY});
- },
-};
+ }
+}
/**
* Creates a PDF viewer with a scripting interface. This is basically 1) an
diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer.js b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
index 375663f029c..d85d80a2101 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
@@ -6,16 +6,64 @@
/**
* @typedef {{
- * dataToSave: Array,
- * token: string,
- * fileName: string
+ * source: Object,
+ * origin: string,
+ * data: !MessageData,
* }}
*/
-let SaveDataMessageData;
+let MessageObject;
/**
- * @return {number} Width of a scrollbar in pixels
+ * @typedef {{
+ * type: string,
+ * height: number,
+ * width: number,
+ * layoutOptions: (!LayoutOptions|undefined),
+ * pageDimensions: Array
+ * }}
+ */
+let DocumentDimensionsMessageData;
+
+/**
+ * @typedef {{
+ * type: string,
+ * url: string,
+ * disposition: !PdfNavigator.WindowOpenDisposition,
+ * }}
+ */
+let NavigateMessageData;
+
+/**
+ * @typedef {{
+ * type: string,
+ * page: number,
+ * x: number,
+ * y: number,
+ * zoom: number
+ * }}
+ */
+let DestinationMessageData;
+
+/**
+ * @typedef {{
+ * type: string,
+ * title: string,
+ * bookmarks: !Array<!Bookmark>,
+ * canSerializeDocument: boolean,
+ * }}
*/
+let MetadataMessageData;
+
+/**
+ * @typedef {{
+ * hasUnsavedChanges: (boolean|undefined),
+ * fileName: string,
+ * dataToSave: !ArrayBuffer
+ * }}
+ */
+let RequiredSaveResult;
+
+/** @return {number} Width of a scrollbar in pixels */
function getScrollbarWidth() {
const div = document.createElement('div');
div.style.visibility = 'hidden';
@@ -31,7 +79,6 @@ function getScrollbarWidth() {
/**
* Return the filename component of a URL, percent decoded if possible.
- *
* @param {string} url The URL to get the filename from.
* @return {string} The filename component.
*/
@@ -53,8 +100,7 @@ function getFilenameFromURL(url) {
/**
* Whether keydown events should currently be ignored. Events are ignored when
* an editable element has focus, to allow for proper editing controls.
- *
- * @param {HTMLElement} activeElement The currently selected DOM node.
+ * @param {Element} activeElement The currently selected DOM node.
* @return {boolean} True if keydown events should be ignored.
*/
function shouldIgnoreKeyEvents(activeElement) {
@@ -70,285 +116,341 @@ function shouldIgnoreKeyEvents(activeElement) {
}
/**
- * Creates a cryptographically secure pseudorandom 128-bit token.
- *
- * @return {string} The generated token as a hex string.
+ * Creates a new PDFViewer. There should only be one of these objects per
+ * document.
*/
-function createToken() {
- const randomBytes = new Uint8Array(16);
- return window.crypto.getRandomValues(randomBytes)
- .map(b => b.toString(16).padStart(2, '0'))
- .join('');
-}
+class PDFViewer {
+ /**
+ * @param {!BrowserApi} browserApi An object providing an API to the browser.
+ */
+ constructor(browserApi) {
+ /** @private {!BrowserApi} */
+ this.browserApi_ = browserApi;
-/**
- * The minimum number of pixels to offset the toolbar by from the bottom and
- * right side of the screen.
- */
-PDFViewer.MIN_TOOLBAR_OFFSET = 15;
+ /** @private {string} */
+ this.originalUrl_ = this.browserApi_.getStreamInfo().originalUrl;
-/**
- * The height of the toolbar along the top of the page. The document will be
- * shifted down by this much in the viewport.
- */
-PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56;
+ /** @private {string} */
+ this.javascript_ = this.browserApi_.getStreamInfo().javascript || 'block';
-/**
- * Minimum height for the material toolbar to show (px). Should match the media
- * query in index-material.css. If the window is smaller than this at load,
- * leave no space for the toolbar.
- */
-PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT = 250;
+ /** @private {!LoadState} */
+ this.loadState_ = LoadState.LOADING;
-/**
- * The background color used for print preview (--google-grey-refresh-300).
- */
-PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR = '0xFFDADCE0';
+ /** @private {?Object} */
+ this.parentWindow_ = null;
-/**
- * The background color used for print preview when dark mode is enabled
- * (--google-grey-refresh-700).
- */
-PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR = '0xFF5F6368';
+ /** @private {?string} */
+ this.parentOrigin_ = null;
-/**
- * The background color used for the regular viewer.
- */
-PDFViewer.BACKGROUND_COLOR = '0xFF525659';
+ /** @private {boolean} */
+ this.isFormFieldFocused_ = false;
-/**
- * Creates a new PDFViewer. There should only be one of these objects per
- * document.
- *
- * @param {!BrowserApi} browserApi An object providing an API to the browser.
- * @constructor
- */
-function PDFViewer(browserApi) {
- this.browserApi_ = browserApi;
- this.originalUrl_ = this.browserApi_.getStreamInfo().originalUrl;
- this.javascript_ = this.browserApi_.getStreamInfo().javascript || 'block';
- this.loadState_ = LoadState.LOADING;
- this.parentWindow_ = null;
- this.parentOrigin_ = null;
- this.isFormFieldFocused_ = false;
- this.beepCount_ = 0;
- this.delayedScriptingMessages_ = [];
- this.loaded_ = new PromiseResolver();
-
- this.isPrintPreview_ = location.origin === 'chrome://print';
- this.isPrintPreviewLoadingFinished_ = false;
- this.isUserInitiatedEvent_ = true;
-
- /** @private {boolean} */
- this.hasEnteredAnnotationMode_ = false;
-
- /** @private {boolean} */
- this.hadPassword_ = false;
-
- /** @private {boolean} */
- this.canSerializeDocument_ = false;
-
- PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED);
-
- // Parse open pdf parameters.
- this.paramsParser_ = new OpenPdfParamsParser(
- message => this.pluginController_.postMessage(message));
- const toolbarEnabled =
- this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar &&
- !this.isPrintPreview_;
-
- // The sizer element is placed behind the plugin element to cause scrollbars
- // to be displayed in the window. It is sized according to the document size
- // of the pdf and zoom level.
- this.sizer_ = $('sizer');
-
- if (this.isPrintPreview_) {
- this.pageIndicator_ = $('page-indicator');
- }
- this.passwordScreen_ = $('password-screen');
- this.passwordScreen_.addEventListener(
- 'password-submitted', e => this.onPasswordSubmitted_(e));
- this.errorScreen_ = $('error-screen');
- // Can only reload if we are in a normal tab.
- if (chrome.tabs && this.browserApi_.getStreamInfo().tabId != -1) {
- this.errorScreen_.reloadFn = () => {
- chrome.tabs.reload(this.browserApi_.getStreamInfo().tabId);
- };
- }
+ /** @private {number} */
+ this.beepCount_ = 0;
- // Create the viewport.
- const shortWindow = window.innerHeight < PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT;
- const topToolbarHeight =
- (toolbarEnabled) ? PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0;
- const defaultZoom =
- this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ?
- this.browserApi_.getDefaultZoom() :
- 1.0;
- this.viewport_ = new Viewport(
- window, this.sizer_, getScrollbarWidth(), defaultZoom, topToolbarHeight);
- this.viewport_.setViewportChangedCallback(() => this.viewportChanged_());
- this.viewport_.setBeforeZoomCallback(
- () => this.currentController_.beforeZoom());
- this.viewport_.setAfterZoomCallback(
- () => this.currentController_.afterZoom());
- this.viewport_.setUserInitiatedCallback(
- userInitiated => this.setUserInitiated_(userInitiated));
- window.addEventListener('beforeunload', () => this.viewport_.resetTracker());
-
- // Create the plugin object dynamically so we can set its src. The plugin
- // element is sized to fill the entire window and is set to be fixed
- // positioning, acting as a viewport. The plugin renders into this viewport
- // according to the scroll position of the window.
- this.plugin_ = document.createElement('embed');
- // NOTE: The plugin's 'id' field must be set to 'plugin' since
- // chrome/renderer/printing/print_render_frame_helper.cc actually
- // references it.
- this.plugin_.id = 'plugin';
- this.plugin_.type = 'application/x-google-chrome-pdf';
-
- // Handle scripting messages from outside the extension that wish to interact
- // with it. We also send a message indicating that extension has loaded and
- // is ready to receive messages.
- window.addEventListener(
- 'message', message => this.handleScriptingMessage(message), false);
-
- this.plugin_.setAttribute('src', this.originalUrl_);
- this.plugin_.setAttribute(
- 'stream-url', this.browserApi_.getStreamInfo().streamUrl);
- let headers = '';
- for (const header in this.browserApi_.getStreamInfo().responseHeaders) {
- headers += header + ': ' +
- this.browserApi_.getStreamInfo().responseHeaders[header] + '\n';
- }
- this.plugin_.setAttribute('headers', headers);
+ /** @private {!Array} */
+ this.delayedScriptingMessages_ = [];
+
+ /** @private {!PromiseResolver} */
+ this.loaded_;
+
+ /** @private {boolean} */
+ this.initialLoadComplete_ = false;
+
+ /** @private {boolean} */
+ this.isPrintPreview_ = location.origin === 'chrome://print';
- this.plugin_.setAttribute('background-color', PDFViewer.BACKGROUND_COLOR);
- this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight);
- this.plugin_.setAttribute('javascript', this.javascript_);
+ /** @private {boolean} */
+ this.isPrintPreviewLoadingFinished_ = false;
- if (this.browserApi_.getStreamInfo().embedded) {
+ /** @private {boolean} */
+ this.isUserInitiatedEvent_ = true;
+
+ /** @private {boolean} */
+ this.hasEnteredAnnotationMode_ = false;
+
+ /** @private {boolean} */
+ this.hadPassword_ = false;
+
+ /** @private {boolean} */
+ this.canSerializeDocument_ = false;
+
+ /** @private {!EventTracker} */
+ this.tracker_ = new EventTracker();
+
+ PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED);
+
+ // Parse open pdf parameters.
+ /** @private {!OpenPdfParamsParser} */
+ this.paramsParser_ = new OpenPdfParamsParser(
+ destination => this.pluginController_.getNamedDestination(destination));
+ const toolbarEnabled =
+ this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar &&
+ !this.isPrintPreview_;
+
+ // The sizer element is placed behind the plugin element to cause scrollbars
+ // to be displayed in the window. It is sized according to the document size
+ // of the pdf and zoom level.
+ this.sizer_ = /** @type {!HTMLDivElement} */ ($('sizer'));
+
+ /** @private {?ViewerPageIndicatorElement} */
+ this.pageIndicator_ = this.isPrintPreview_ ?
+ /** @type {!ViewerPageIndicatorElement} */ ($('page-indicator')) :
+ null;
+
+ /** @private {?ViewerPasswordScreenElement} */
+ this.passwordScreen_ =
+ /** @type {!ViewerPasswordScreenElement} */ ($('password-screen'));
+ this.passwordScreen_.addEventListener('password-submitted', e => {
+ this.onPasswordSubmitted_(
+ /** @type {!CustomEvent<{password: string}>} */ (e));
+ });
+
+ /** @private {?ViewerErrorScreenElement} */
+ this.errorScreen_ =
+ /** @type {!ViewerErrorScreenElement} */ ($('error-screen'));
+ // Can only reload if we are in a normal tab.
+ if (chrome.tabs && this.browserApi_.getStreamInfo().tabId != -1) {
+ this.errorScreen_.reloadFn = () => {
+ chrome.tabs.reload(this.browserApi_.getStreamInfo().tabId);
+ };
+ }
+
+ // Create the viewport.
+ const shortWindow =
+ window.innerHeight < PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT;
+ const topToolbarHeight =
+ (toolbarEnabled) ? PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0;
+ const defaultZoom =
+ this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ?
+ this.browserApi_.getDefaultZoom() :
+ 1.0;
+
+ /** @private {!Viewport} */
+ this.viewport_ = new Viewport(
+ window, this.sizer_, getScrollbarWidth(), defaultZoom,
+ topToolbarHeight);
+ this.viewport_.setViewportChangedCallback(() => this.viewportChanged_());
+ this.viewport_.setBeforeZoomCallback(
+ () => this.currentController_.beforeZoom());
+ this.viewport_.setAfterZoomCallback(
+ () => this.currentController_.afterZoom());
+ this.viewport_.setUserInitiatedCallback(
+ userInitiated => this.setUserInitiated_(userInitiated));
+ window.addEventListener('beforeunload', () => this.resetTrackers_());
+
+ // Create the plugin object dynamically so we can set its src. The plugin
+ // element is sized to fill the entire window and is set to be fixed
+ // positioning, acting as a viewport. The plugin renders into this viewport
+ // according to the scroll position of the window.
+ /** @private {!HTMLEmbedElement} */
+ this.plugin_ =
+ /** @type {!HTMLEmbedElement} */ (document.createElement('embed'));
+
+ // NOTE: The plugin's 'id' field must be set to 'plugin' since
+ // chrome/renderer/printing/print_render_frame_helper.cc actually
+ // references it.
+ this.plugin_.id = 'plugin';
+ this.plugin_.type = 'application/x-google-chrome-pdf';
+
+ // Handle scripting messages from outside the extension that wish to
+ // interact with it. We also send a message indicating that extension has
+ // loaded and is ready to receive messages.
+ window.addEventListener('message', message => {
+ this.handleScriptingMessage(/** @type {!MessageObject} */ (message));
+ }, false);
+
+ this.plugin_.setAttribute('src', this.originalUrl_);
this.plugin_.setAttribute(
- 'top-level-url', this.browserApi_.getStreamInfo().tabUrl);
- } else {
- this.plugin_.setAttribute('full-frame', '');
- }
+ 'stream-url', this.browserApi_.getStreamInfo().streamUrl);
+ let headers = '';
+ for (const header in this.browserApi_.getStreamInfo().responseHeaders) {
+ headers += header + ': ' +
+ this.browserApi_.getStreamInfo().responseHeaders[header] + '\n';
+ }
+ this.plugin_.setAttribute('headers', headers);
- $('content').appendChild(this.plugin_);
-
- this.pluginController_ =
- new PluginController(this.plugin_, this, this.viewport_);
- this.inkController_ = new InkController(this, this.viewport_);
- this.currentController_ = this.pluginController_;
-
- // Setup the button event listeners.
- this.zoomToolbar_ = $('zoom-toolbar');
- this.zoomToolbar_.setIsPrintPreview(this.isPrintPreview_);
- this.zoomToolbar_.addEventListener(
- 'fit-to-changed', e => this.fitToChanged_(e));
- this.zoomToolbar_.addEventListener('zoom-in', () => this.viewport_.zoomIn());
- this.zoomToolbar_.addEventListener(
- 'zoom-out', () => this.viewport_.zoomOut());
-
- this.gestureDetector_ = new GestureDetector($('content'));
- this.gestureDetector_.addEventListener(
- 'pinchstart', e => this.onPinchStart_(e));
- this.sentPinchEvent_ = false;
- this.gestureDetector_.addEventListener(
- 'pinchupdate', e => this.onPinchUpdate_(e));
- this.gestureDetector_.addEventListener('pinchend', e => this.onPinchEnd_(e));
-
- if (toolbarEnabled) {
- this.toolbar_ = $('toolbar');
- this.toolbar_.hidden = false;
- this.toolbar_.addEventListener('save', () => this.save());
- this.toolbar_.addEventListener('print', () => this.print());
- this.toolbar_.addEventListener(
- 'undo', () => this.currentController_.undo());
- this.toolbar_.addEventListener(
- 'redo', () => this.currentController_.redo());
- this.toolbar_.addEventListener(
- 'rotate-right', () => this.rotateClockwise());
- this.toolbar_.addEventListener(
- 'annotation-mode-toggled', e => this.annotationModeToggled_(e));
- this.toolbar_.addEventListener(
- 'annotation-tool-changed',
- e => this.inkController_.setAnnotationTool(e.detail.value));
-
- this.toolbar_.docTitle = getFilenameFromURL(this.originalUrl_);
- }
+ this.plugin_.setAttribute('background-color', PDFViewer.BACKGROUND_COLOR);
+ this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight);
+ this.plugin_.setAttribute('javascript', this.javascript_);
- document.body.addEventListener('change-page', e => {
- this.viewport_.goToPage(e.detail.page);
- if (e.detail.origin == 'bookmark') {
- PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK);
- } else if (e.detail.origin == 'pageselector') {
- PDFMetrics.record(PDFMetrics.UserAction.PAGE_SELECTOR_NAVIGATE);
+ if (this.browserApi_.getStreamInfo().embedded) {
+ this.plugin_.setAttribute(
+ 'top-level-url', this.browserApi_.getStreamInfo().tabUrl);
+ } else {
+ this.plugin_.setAttribute('full-frame', '');
}
- });
-
- document.body.addEventListener('change-page-and-xy', e => {
- const point = this.viewport_.convertPageToScreen(e.detail.page, e.detail);
- this.goToPageAndXY_(e.detail.origin, e.detail.page, point);
- });
-
- document.body.addEventListener('navigate', e => {
- const disposition = e.detail.newtab ?
- PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
- PdfNavigator.WindowOpenDisposition.CURRENT_TAB;
- this.navigator_.navigate(e.detail.uri, disposition);
- });
-
- document.body.addEventListener('dropdown-opened', e => {
- if (e.detail == 'bookmarks') {
- PDFMetrics.record(PDFMetrics.UserAction.OPEN_BOOKMARKS_PANEL);
+
+ $('content').appendChild(this.plugin_);
+
+ /** @private {!PluginController} */
+ this.pluginController_ = new PluginController(
+ this.plugin_, this.viewport_, () => this.isUserInitiatedEvent_,
+ () => this.loaded);
+ this.tracker_.add(
+ this.pluginController_.getEventTarget(), 'plugin-message',
+ e => this.handlePluginMessage_(e));
+
+ /** @private {!InkController} */
+ this.inkController_ = new InkController(this.viewport_);
+ this.tracker_.add(
+ this.inkController_.getEventTarget(), 'stroke-added',
+ () => chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(true));
+ this.tracker_.add(
+ this.inkController_.getEventTarget(), 'set-annotation-undo-state',
+ e => this.setAnnotationUndoState_(e));
+
+ /** @private {!ContentController} */
+ this.currentController_ = this.pluginController_;
+
+ // Setup the button event listeners.
+ /** @private {!ViewerZoomToolbarElement} */
+ this.zoomToolbar_ =
+ /** @type {!ViewerZoomToolbarElement} */ ($('zoom-toolbar'));
+ this.zoomToolbar_.setIsPrintPreview(this.isPrintPreview_);
+ this.zoomToolbar_.addEventListener(
+ 'fit-to-changed',
+ e => this.fitToChanged_(
+ /** @type {!CustomEvent<FitToChangedEvent>}} */ (e)));
+ this.zoomToolbar_.addEventListener(
+ 'zoom-in', () => this.viewport_.zoomIn());
+ this.zoomToolbar_.addEventListener(
+ 'zoom-out', () => this.viewport_.zoomOut());
+
+ /** @private {!GestureDetector} */
+ this.gestureDetector_ = new GestureDetector(assert($('content')));
+ this.gestureDetector_.addEventListener(
+ 'pinchstart', e => this.onPinchStart_(e));
+ this.sentPinchEvent_ = false;
+ this.gestureDetector_.addEventListener(
+ 'pinchupdate', e => this.onPinchUpdate_(e));
+ this.gestureDetector_.addEventListener(
+ 'pinchend', e => this.onPinchEnd_(e));
+
+ /** @private {?ViewerPdfToolbarElement} */
+ this.toolbar_ = null;
+ if (toolbarEnabled) {
+ this.toolbar_ = /** @type {!ViewerPdfToolbarElement} */ ($('toolbar'));
+ this.toolbar_.hidden = false;
+ this.toolbar_.addEventListener('save', () => this.save_());
+ this.toolbar_.addEventListener('print', () => this.print_());
+ this.toolbar_.addEventListener(
+ 'undo', () => this.currentController_.undo());
+ this.toolbar_.addEventListener(
+ 'redo', () => this.currentController_.redo());
+ this.toolbar_.addEventListener(
+ 'rotate-right', () => this.rotateClockwise_());
+ this.toolbar_.addEventListener('annotation-mode-toggled', e => {
+ this.annotationModeToggled_(
+ /** @type {!CustomEvent<{value: boolean}>} */ (e));
+ });
+ this.toolbar_.addEventListener(
+ 'annotation-tool-changed',
+ e => this.inkController_.setAnnotationTool(e.detail.value));
+
+ this.toolbar_.docTitle = getFilenameFromURL(this.originalUrl_);
+ }
+
+ document.body.addEventListener('change-page', e => {
+ this.viewport_.goToPage(e.detail.page);
+ if (e.detail.origin == 'bookmark') {
+ PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK);
+ } else if (e.detail.origin == 'pageselector') {
+ PDFMetrics.record(PDFMetrics.UserAction.PAGE_SELECTOR_NAVIGATE);
+ }
+ });
+
+ document.body.addEventListener('change-zoom', e => {
+ this.viewport_.setZoom(e.detail.zoom);
+ });
+
+ document.body.addEventListener('change-page-and-xy', e => {
+ const point = this.viewport_.convertPageToScreen(e.detail.page, e.detail);
+ this.goToPageAndXY_(e.detail.origin, e.detail.page, point);
+ });
+
+ document.body.addEventListener('navigate', e => {
+ const disposition = e.detail.newtab ?
+ PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
+ PdfNavigator.WindowOpenDisposition.CURRENT_TAB;
+ this.navigator_.navigate(e.detail.uri, disposition);
+ });
+
+ document.body.addEventListener('dropdown-opened', e => {
+ if (e.detail == 'bookmarks') {
+ PDFMetrics.record(PDFMetrics.UserAction.OPEN_BOOKMARKS_PANEL);
+ }
+ });
+
+ /** @private {!ToolbarManager} */
+ this.toolbarManager_ =
+ new ToolbarManager(window, this.toolbar_, this.zoomToolbar_);
+
+ // Set up the ZoomManager.
+ /** @private {!ZoomManager} */
+ this.zoomManager_ = ZoomManager.create(
+ this.browserApi_.getZoomBehavior(), () => this.viewport_.getZoom(),
+ zoom => this.browserApi_.setZoom(zoom),
+ this.browserApi_.getInitialZoom());
+ this.viewport_.setZoomManager(this.zoomManager_);
+ this.browserApi_.addZoomEventListener(
+ zoom => this.zoomManager_.onBrowserZoomChange(zoom));
+
+ // Setup the keyboard event listener.
+ document.addEventListener(
+ 'keydown',
+ e => this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (e)));
+ document.addEventListener('mousemove', e => this.handleMouseEvent_(e));
+ document.addEventListener('mouseout', e => this.handleMouseEvent_(e));
+ document.addEventListener(
+ 'contextmenu', e => this.handleContextMenuEvent_(e));
+
+ const tabId = this.browserApi_.getStreamInfo().tabId;
+ /** @private {!PdfNavigator} */
+ this.navigator_ = new PdfNavigator(
+ this.originalUrl_, this.viewport_, this.paramsParser_,
+ new NavigatorDelegate(tabId));
+
+ /** @private {!ViewportScroller} */
+ this.viewportScroller_ =
+ new ViewportScroller(this.viewport_, this.plugin_, window);
+
+ /** @private {!Array<!Bookmark>} */
+ this.bookmarks_;
+
+ /** @private {!Point} */
+ this.lastViewportPosition_;
+
+ /** @private {boolean} */
+ this.reverseZoomToolbar_;
+
+ /** @private {boolean} */
+ this.inPrintPreviewMode_;
+
+ /** @private {boolean} */
+ this.dark_;
+
+ /** @private {!DocumentDimensionsMessageData} */
+ this.documentDimensions_;
+
+ // Request translated strings.
+ chrome.resourcesPrivate.getStrings(
+ chrome.resourcesPrivate.Component.PDF,
+ strings => this.handleStrings_(strings));
+
+ // Listen for save commands from the browser.
+ if (chrome.mimeHandlerPrivate && chrome.mimeHandlerPrivate.onSave) {
+ chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave_(url));
}
- });
-
- this.toolbarManager_ =
- new ToolbarManager(window, this.toolbar_, this.zoomToolbar_);
-
- // Set up the ZoomManager.
- this.zoomManager_ = ZoomManager.create(
- this.browserApi_.getZoomBehavior(), () => this.viewport_.getZoom(),
- zoom => this.browserApi_.setZoom(zoom),
- this.browserApi_.getInitialZoom());
- this.viewport_.setZoomManager(this.zoomManager_);
- this.browserApi_.addZoomEventListener(
- zoom => this.zoomManager_.onBrowserZoomChange(zoom));
-
- // Setup the keyboard event listener.
- document.addEventListener('keydown', e => this.handleKeyEvent_(e));
- document.addEventListener('mousemove', e => this.handleMouseEvent_(e));
- document.addEventListener('mouseout', e => this.handleMouseEvent_(e));
- document.addEventListener(
- 'contextmenu', e => this.handleContextMenuEvent_(e));
-
- const tabId = this.browserApi_.getStreamInfo().tabId;
- this.navigator_ = new PdfNavigator(
- this.originalUrl_, this.viewport_, this.paramsParser_,
- new NavigatorDelegate(tabId));
- this.viewportScroller_ =
- new ViewportScroller(this.viewport_, this.plugin_, window);
-
- // Request translated strings.
- chrome.resourcesPrivate.getStrings(
- 'pdf', strings => this.handleStrings_(strings));
-
- // Listen for save commands from the browser.
- if (chrome.mimeHandlerPrivate && chrome.mimeHandlerPrivate.onSave) {
- chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave(url));
}
-}
-PDFViewer.prototype = {
/**
* Handle key events. These may come from the user directly or via the
* scripting API.
- *
- * @param {KeyboardEvent} e the event to handle.
+ * @param {!KeyboardEvent} e the event to handle.
* @private
*/
- handleKeyEvent_: function(e) {
+ handleKeyEvent_(e) {
const position = this.viewport_.position;
// Certain scroll events may be sent from outside of the extension.
const fromScriptingAPI = e.fromScriptingAPI;
@@ -357,7 +459,7 @@ PDFViewer.prototype = {
return;
}
- this.toolbarManager_.hideToolbarsAfterTimeout(e);
+ this.toolbarManager_.hideToolbarsAfterTimeout();
const pageUpHandler = () => {
// Go to the previous page if we are fit-to-page or fit-to-height.
@@ -366,8 +468,8 @@ PDFViewer.prototype = {
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
- position.y -= this.viewport.size.height;
- this.viewport.position = position;
+ position.y -= this.viewport_.size.height;
+ this.viewport_.position = position;
}
};
const pageDownHandler = () => {
@@ -377,8 +479,8 @@ PDFViewer.prototype = {
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
- position.y += this.viewport.size.height;
- this.viewport.position = position;
+ position.y += this.viewport_.size.height;
+ this.viewport_.position = position;
}
};
@@ -416,14 +518,14 @@ PDFViewer.prototype = {
e.preventDefault();
} else if (fromScriptingAPI) {
position.x -= Viewport.SCROLL_INCREMENT;
- this.viewport.position = position;
+ this.viewport_.position = position;
}
}
return;
case 38: // Up arrow key.
if (fromScriptingAPI) {
position.y -= Viewport.SCROLL_INCREMENT;
- this.viewport.position = position;
+ this.viewport_.position = position;
}
return;
case 39: // Right arrow key.
@@ -437,19 +539,19 @@ PDFViewer.prototype = {
e.preventDefault();
} else if (fromScriptingAPI) {
position.x += Viewport.SCROLL_INCREMENT;
- this.viewport.position = position;
+ this.viewport_.position = position;
}
}
return;
case 40: // Down arrow key.
if (fromScriptingAPI) {
position.y += Viewport.SCROLL_INCREMENT;
- this.viewport.position = position;
+ this.viewport_.position = position;
}
return;
case 65: // 'a' key.
if (e.ctrlKey || e.metaKey) {
- this.pluginController_.postMessage({type: 'selectAll'});
+ this.pluginController_.selectAll();
// Since we do selection ourselves.
e.preventDefault();
}
@@ -462,7 +564,7 @@ PDFViewer.prototype = {
return;
case 219: // Left bracket key.
if (e.ctrlKey) {
- this.rotateCounterclockwise();
+ this.rotateCounterclockwise_();
}
return;
case 220: // Backslash key.
@@ -472,7 +574,7 @@ PDFViewer.prototype = {
return;
case 221: // Right bracket key.
if (e.ctrlKey) {
- this.rotateClockwise();
+ this.rotateClockwise_();
}
return;
}
@@ -487,42 +589,49 @@ PDFViewer.prototype = {
this.toolbarManager_.showToolbars();
}
}
- },
+ }
- handleMouseEvent_: function(e) {
+ handleMouseEvent_(e) {
if (e.type == 'mousemove') {
this.toolbarManager_.handleMouseMove(e);
} else if (e.type == 'mouseout') {
this.toolbarManager_.hideToolbarsForMouseOut();
}
- },
+ }
- handleContextMenuEvent_: function(e) {
+ /**
+ * @param {!Event} e The context menu event
+ * @private
+ */
+ handleContextMenuEvent_(e) {
// Stop Chrome from popping up the context menu on long press. We need to
// make sure the start event did not have 2 touches because we don't want
// to block two finger tap opening the context menu. We check for
// firesTouchEvents in order to not block the context menu on right click.
- if (e.sourceCapabilities.firesTouchEvents &&
+ const capabilities =
+ /** @type {{ sourceCapabilities: Object }} */ (e).sourceCapabilities;
+ if (capabilities.firesTouchEvents &&
!this.gestureDetector_.wasTwoFingerTouch()) {
e.preventDefault();
}
- },
+ }
/**
* Handles the annotation mode being toggled on or off.
- *
* @param {!CustomEvent<{value: boolean}>} e
* @private
*/
- annotationModeToggled_: async function(e) {
+ async annotationModeToggled_(e) {
const annotationMode = e.detail.value;
if (annotationMode) {
// Enter annotation mode.
assert(this.currentController_ == this.pluginController_);
// TODO(dstockwell): set plugin read-only, begin transition
- this.updateProgress(0);
+ this.updateProgress_(0);
// TODO(dstockwell): handle save failure
- const result = await this.pluginController_.save(true);
+ const saveResult = await this.pluginController_.save(true);
+ // Data always exists when save is called with requireResult = true.
+ const result = /** @type {!RequiredSaveResult} */ (saveResult);
if (result.hasUnsavedChanges) {
assert(!loadTimeData.getBoolean('pdfFormSaveEnabled'));
try {
@@ -530,25 +639,26 @@ PDFViewer.prototype = {
} catch (e) {
// The user aborted entering annotation mode. Revert to the plugin.
this.toolbar_.annotationMode = false;
- this.updateProgress(100);
+ this.updateProgress_(100);
return;
}
}
PDFMetrics.record(PDFMetrics.UserAction.ENTER_ANNOTATION_MODE);
this.hasEnteredAnnotationMode_ = true;
// TODO(dstockwell): feed real progress data from the Ink component
- this.updateProgress(50);
+ this.updateProgress_(50);
await this.inkController_.load(result.fileName, result.dataToSave);
- this.inkController_.setAnnotationTool(this.toolbar_.annotationTool);
+ this.inkController_.setAnnotationTool(
+ assert(this.toolbar_.annotationTool));
this.currentController_ = this.inkController_;
this.pluginController_.unload();
- this.updateProgress(100);
+ this.updateProgress_(100);
} else {
// Exit annotation mode.
PDFMetrics.record(PDFMetrics.UserAction.EXIT_ANNOTATION_MODE);
assert(this.currentController_ == this.inkController_);
// TODO(dstockwell): set ink read-only, begin transition
- this.updateProgress(0);
+ this.updateProgress_(0);
// This runs separately to allow other consumers of `loaded` to queue
// up after this task.
this.loaded.then(() => {
@@ -556,36 +666,33 @@ PDFViewer.prototype = {
this.inkController_.unload();
});
// TODO(dstockwell): handle save failure
- const result = await this.inkController_.save(true);
+ const saveResult = await this.inkController_.save(true);
+ // Data always exists when save is called with requireResult = true.
+ const result = /** @type {!RequiredSaveResult} */ (saveResult);
await this.pluginController_.load(result.fileName, result.dataToSave);
// Ensure the plugin gets the initial viewport.
this.pluginController_.afterZoom();
}
- },
+ }
/**
* Exits annotation mode if active.
- *
* @return {Promise<void>}
*/
- exitAnnotationMode_: async function() {
+ async exitAnnotationMode_() {
if (!this.toolbar_.annotationMode) {
return;
}
this.toolbar_.toggleAnnotation();
await this.loaded;
- },
+ }
/**
* Request to change the viewport fitting type.
- *
- * @param {!CustomEvent<{
- * fittingType: FittingType,
- * userInitiated: boolean
- * }>} e
+ * @param {!CustomEvent<FitToChangedEvent>} e
* @private
*/
- fitToChanged_: function(e) {
+ fitToChanged_(e) {
if (e.detail.fittingType == FittingType.FIT_TO_PAGE) {
this.viewport_.fitToPage();
this.toolbarManager_.forceHideTopToolbar();
@@ -599,15 +706,14 @@ PDFViewer.prototype = {
if (e.detail.userInitiated) {
PDFMetrics.recordFitTo(e.detail.fittingType);
}
- },
+ }
/**
* Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has
* finished loading.
- *
* @private
*/
- sendDocumentLoadedMessage_: function() {
+ sendDocumentLoadedMessage_() {
if (this.loadState_ == LoadState.LOADING) {
return;
}
@@ -616,17 +722,16 @@ PDFViewer.prototype = {
}
this.sendScriptingMessage_(
{type: 'documentLoaded', load_state: this.loadState_});
- },
+ }
/**
* Handle open pdf parameters. This function updates the viewport as per
* the parameters mentioned in the url while opening pdf. The order is
* important as later actions can override the effects of previous actions.
- *
* @param {Object} params The open params passed in the URL.
* @private
*/
- handleURLParams_: function(params) {
+ handleURLParams_(params) {
if (params.zoom) {
this.viewport_.setZoom(params.zoom);
}
@@ -654,32 +759,42 @@ PDFViewer.prototype = {
}
this.isUserInitiatedEvent_ = true;
}
- },
+ }
/**
* Moves the viewport to a point in a page. Called back after a
* 'transformPagePointReply' is returned from the plugin.
- *
* @param {string} origin Identifier for the caller for logging purposes.
* @param {number} page The index of the page to go to. zero-based.
- * @param {Object} message Message received from the plugin containing the
+ * @param {Point} message Message received from the plugin containing the
* x and y to navigate to in screen coordinates.
* @private
*/
- goToPageAndXY_: function(origin, page, message) {
+ goToPageAndXY_(origin, page, message) {
this.viewport_.goToPageAndXY(page, message.x, message.y);
if (origin == 'bookmark') {
PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK);
}
- },
+ }
/**
- * @return {Promise} Resolved when the load state reaches LOADED,
- * rejects on FAILED.
+ * @return {?Promise} Resolved when the load state reaches LOADED,
+ * rejects on FAILED. Returns null if no promise has been created, which
+ * is the case for initial load of the PDF.
*/
get loaded() {
- return this.loaded_.promise;
- },
+ return this.loaded_ ? this.loaded_.promise : null;
+ }
+
+ /** @return {!Viewport} The viewport. Used for testing. */
+ get viewport() {
+ return this.viewport_;
+ }
+
+ /** @return {!Array<!Bookmark>} The bookmarks. Used for testing. */
+ get bookmarks() {
+ return this.bookmarks_;
+ }
/**
* Updates the load state and triggers completion of the `loaded`
@@ -691,26 +806,29 @@ PDFViewer.prototype = {
if (this.loadState_ == loadState) {
return;
}
+ assert(
+ loadState == LoadState.LOADING || this.loadState_ == LoadState.LOADING);
+ this.loadState_ = loadState;
+ if (!this.initialLoadComplete_) {
+ this.initialLoadComplete_ = true;
+ return;
+ }
if (loadState == LoadState.SUCCESS) {
- assert(this.loadState_ == LoadState.LOADING);
this.loaded_.resolve();
} else if (loadState == LoadState.FAILED) {
- assert(this.loadState_ == LoadState.LOADING);
this.loaded_.reject();
} else {
- assert(loadState == LoadState.LOADING);
this.loaded_ = new PromiseResolver();
}
- this.loadState_ = loadState;
- },
+ }
/**
* Update the loading progress of the document in response to a progress
* message being received from the content controller.
- *
* @param {number} progress the progress as a percentage.
+ * @private
*/
- updateProgress: function(progress) {
+ updateProgress_(progress) {
if (this.toolbar_) {
this.toolbar_.loadProgress = progress;
}
@@ -743,28 +861,26 @@ PDFViewer.prototype = {
} else {
this.setLoadState_(LoadState.LOADING);
}
- },
+ }
/** @private */
- sendBackgroundColorForPrintPreview_: function() {
- this.pluginController_.postMessage({
- type: 'backgroundColorChanged',
- backgroundColor: this.dark_ ?
- PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR :
- PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR,
- });
- },
+ sendBackgroundColorForPrintPreview_() {
+ this.pluginController_.backgroundColorChanged(
+ this.dark_ ? PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR :
+ PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR);
+ }
/**
* Load a dictionary of translated strings into the UI. Used as a callback for
* chrome.resourcesPrivate.
- *
* @param {Object} strings Dictionary of translated strings
* @private
*/
- handleStrings_: function(strings) {
- document.documentElement.dir = strings.textdirection;
- document.documentElement.lang = strings.language;
+ handleStrings_(strings) {
+ const stringsDictionary =
+ /** @type {{ textdirection: string, language: string }} */ (strings);
+ document.documentElement.dir = stringsDictionary.textdirection;
+ document.documentElement.lang = stringsDictionary.language;
loadTimeData.data = strings;
const isNewPrintPreview = this.isPrintPreview_ &&
@@ -786,38 +902,34 @@ PDFViewer.prototype = {
if ($('form-warning')) {
$('form-warning').strings = strings;
}
- },
+ }
/**
* An event handler for handling password-submitted events. These are fired
* when an event is entered into the password screen.
- *
- * @param {Object} event a password-submitted event.
+ * @param {!CustomEvent<{password: string}>} event a password-submitted event.
* @private
*/
- onPasswordSubmitted_: function(event) {
- this.pluginController_.postMessage(
- {type: 'getPasswordComplete', password: event.detail.password});
- },
+ onPasswordSubmitted_(event) {
+ this.pluginController_.getPasswordComplete(event.detail.password);
+ }
/**
* A callback that sets |isUserInitiatedEvent_| to |userInitiated|.
- *
* @param {boolean} userInitiated The value to set |isUserInitiatedEvent_| to.
* @private
*/
- setUserInitiated_: function(userInitiated) {
+ setUserInitiated_(userInitiated) {
assert(this.isUserInitiatedEvent_ != userInitiated);
this.isUserInitiatedEvent_ = userInitiated;
- },
+ }
/**
* A callback that's called when an update to a pinch zoom is detected.
- *
* @param {!Object} e the pinch event.
* @private
*/
- onPinchUpdate_: function(e) {
+ onPinchUpdate_(e) {
// Throttle number of pinch events to one per frame.
if (!this.sentPinchEvent_) {
this.sentPinchEvent_ = true;
@@ -826,42 +938,39 @@ PDFViewer.prototype = {
this.viewport_.pinchZoom(e);
});
}
- },
+ }
/**
* A callback that's called when the end of a pinch zoom is detected.
- *
* @param {!Object} e the pinch event.
* @private
*/
- onPinchEnd_: function(e) {
+ onPinchEnd_(e) {
// Using rAF for pinch end prevents pinch updates scheduled by rAF getting
// sent after the pinch end.
window.requestAnimationFrame(() => {
this.viewport_.pinchZoomEnd(e);
});
- },
+ }
/**
* A callback that's called when the start of a pinch zoom is detected.
- *
* @param {!Object} e the pinch event.
* @private
*/
- onPinchStart_: function(e) {
+ onPinchStart_(e) {
// We also use rAF for pinch start, so that if there is a pinch end event
// scheduled by rAF, this pinch start will be sent after.
window.requestAnimationFrame(() => {
this.viewport_.pinchZoomStart(e);
});
- },
+ }
/**
* A callback that's called after the viewport changes.
- *
* @private
*/
- viewportChanged_: function() {
+ viewportChanged_() {
if (!this.documentDimensions_) {
return;
}
@@ -900,9 +1009,10 @@ PDFViewer.prototype = {
// TODO(raymes): Give pageIndicator_ the same API as toolbar_.
if (this.pageIndicator_) {
+ const lastIndex = this.pageIndicator_.index;
this.pageIndicator_.index = visiblePage;
if (this.documentDimensions_.pageDimensions.length > 1 &&
- hasScrollbars.vertical) {
+ hasScrollbars.vertical && lastIndex !== undefined) {
this.pageIndicator_.style.visibility = 'visible';
} else {
this.pageIndicator_.style.visibility = 'hidden';
@@ -921,16 +1031,15 @@ PDFViewer.prototype = {
viewportWidth: size.width,
viewportHeight: size.height
});
- },
+ }
/**
* Handle a scripting message from outside the extension (typically sent by
* PDFScriptingAPI in a page containing the extension) to interact with the
* plugin.
- *
- * @param {MessageObject} message the message to handle.
+ * @param {!MessageObject} message The message to handle.
*/
- handleScriptingMessage: function(message) {
+ handleScriptingMessage(message) {
if (this.parentWindow_ != message.source) {
this.parentWindow_ = message.source;
this.parentOrigin_ = message.origin;
@@ -953,30 +1062,38 @@ PDFViewer.prototype = {
switch (message.data.type.toString()) {
case 'getSelectedText':
+ this.pluginController_.getSelectedText();
+ break;
case 'print':
+ this.pluginController_.print();
+ break;
case 'selectAll':
- this.pluginController_.postMessage(message.data);
+ this.pluginController_.selectAll();
break;
}
- },
+ }
/**
* Handle scripting messages specific to print preview.
- *
- * @param {MessageObject} message the message to handle.
+ * @param {!MessageObject} message the message to handle.
* @return {boolean} true if the message was handled, false otherwise.
* @private
*/
- handlePrintPreviewScriptingMessage_: function(message) {
+ handlePrintPreviewScriptingMessage_(message) {
if (!this.isPrintPreview_) {
return false;
}
- switch (message.data.type.toString()) {
+ let messageData = message.data;
+ switch (messageData.type.toString()) {
case 'loadPreviewPage':
- this.pluginController_.postMessage(message.data);
+ messageData =
+ /** @type {{ url: string, index: number }} */ (messageData);
+ this.pluginController_.loadPreviewPage(
+ messageData.url, messageData.index);
return true;
case 'resetPrintPreviewMode':
+ messageData = /** @type {!PrintPreviewParams} */ (messageData);
this.setLoadState_(LoadState.LOADING);
if (!this.inPrintPreviewMode_) {
this.inPrintPreviewMode_ = true;
@@ -999,49 +1116,42 @@ PDFViewer.prototype = {
saveButton.parentNode.removeChild(saveButton);
}
- this.pageIndicator_.pageLabels = message.data.pageNumbers;
+ this.pageIndicator_.pageLabels = messageData.pageNumbers;
- this.pluginController_.postMessage({
- type: 'resetPrintPreviewMode',
- url: message.data.url,
- grayscale: message.data.grayscale,
- // If the PDF isn't modifiable we send 0 as the page count so that no
- // blank placeholder pages get appended to the PDF.
- pageCount:
- (message.data.modifiable ? message.data.pageNumbers.length : 0)
- });
+ this.pluginController_.resetPrintPreviewMode(messageData);
return true;
case 'sendKeyEvent':
- this.handleKeyEvent_(DeserializeKeyEvent(message.data.keyEvent));
+ this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (DeserializeKeyEvent(
+ /** @type {{ keyEvent: Object }} */ (message.data).keyEvent)));
return true;
case 'hideToolbars':
this.toolbarManager_.resetKeyboardNavigationAndHideToolbars();
return true;
case 'darkModeChanged':
- this.dark_ = message.data.darkMode;
+ this.dark_ = /** @type {{darkMode: boolean}} */ (message.data).darkMode;
if (this.isPrintPreview_) {
this.sendBackgroundColorForPrintPreview_();
}
return true;
case 'scrollPosition':
const position = this.viewport_.position;
- position.y += message.data.y;
- position.x += message.data.x;
- this.viewport.position = position;
+ messageData = /** @type {{ x: number, y: number }} */ (message.data);
+ position.y += messageData.y;
+ position.x += messageData.x;
+ this.viewport_.position = position;
return true;
}
return false;
- },
+ }
/**
* Send a scripting message outside the extension (typically to
* PDFScriptingAPI in a page containing the extension).
- *
* @param {Object} message the message to send.
* @private
*/
- sendScriptingMessage_: function(message) {
+ sendScriptingMessage_(message) {
if (this.parentWindow_ && this.parentOrigin_) {
let targetOrigin;
// Only send data back to the embedder if it is from the same origin,
@@ -1057,34 +1167,73 @@ PDFViewer.prototype = {
}
this.parentWindow_.postMessage(message, targetOrigin);
}
- },
-
- /**
- * @type {Viewport} the viewport of the PDF viewer.
- */
- get viewport() {
- return this.viewport_;
- },
+ }
/**
- * Each bookmark is an Object containing a:
- * - title
- * - page (optional)
- * - array of children (themselves bookmarks)
- *
- * @type {Array} the top-level bookmarks of the PDF.
+ * @param {!CustomEvent<MessageData>} e
+ * @private
*/
- get bookmarks() {
- return this.bookmarks_;
- },
+ handlePluginMessage_(e) {
+ const data = e.detail;
+ switch (data.type.toString()) {
+ case 'beep':
+ this.handleBeep_();
+ return;
+ case 'documentDimensions':
+ this.setDocumentDimensions_(
+ /** @type {!DocumentDimensionsMessageData} */ (data));
+ return;
+ case 'getPassword':
+ this.handlePasswordRequest_();
+ return;
+ case 'getSelectedTextReply':
+ this.handleSelectedTextReply_(
+ /** @type {{ selectedText: string }} */ (data).selectedText);
+ return;
+ case 'loadProgress':
+ this.updateProgress_(
+ /** @type {{ progress: number }} */ (data).progress);
+ return;
+ case 'navigate':
+ const navigateData = /** @type {!NavigateMessageData} */ (data);
+ this.handleNavigate_(navigateData.url, navigateData.disposition);
+ return;
+ case 'navigateToDestination':
+ const destinationData = /** @type {!DestinationMessageData} */ (data);
+ this.handleNavigateToDestination_(
+ destinationData.page, destinationData.x, destinationData.y,
+ destinationData.zoom);
+ return;
+ case 'printPreviewLoaded':
+ this.handlePrintPreviewLoaded_();
+ return;
+ case 'metadata':
+ const metadata = /** @type {!MetadataMessageData} */ (data);
+ this.setDocumentMetadata_(
+ metadata.title, metadata.bookmarks, metadata.canSerializeDocument);
+ return;
+ case 'setIsSelecting':
+ this.setIsSelecting_(
+ /** @type {{ isSelecting: boolean }} */ (data).isSelecting);
+ return;
+ case 'getNamedDestinationReply':
+ this.paramsParser_.onNamedDestinationReceived(
+ /** @type {{ pageNumber: number }} */ (data).pageNumber);
+ return;
+ case 'formFocusChange':
+ this.isFormFieldFocused_ =
+ /** @type {{ focused: boolean }} */ (data).focused;
+ return;
+ }
+ assertNotReached('Unknown message type received: ' + data.type);
+ }
/**
* Sets document dimensions from the current controller.
- *
- * @param {{height: number, width: number, pageDimensions: Array}}
- * documentDimensions
+ * @param {!DocumentDimensionsMessageData} documentDimensions
+ * @private
*/
- setDocumentDimensions: function(documentDimensions) {
+ setDocumentDimensions_(documentDimensions) {
this.documentDimensions_ = documentDimensions;
this.isUserInitiatedEvent_ = false;
this.viewport_.setDocumentDimensions(this.documentDimensions_);
@@ -1098,20 +1247,22 @@ PDFViewer.prototype = {
if (this.toolbar_) {
this.toolbar_.docLength = this.documentDimensions_.pageDimensions.length;
}
- },
+ }
/**
* Handles a beep request from the current controller.
+ * @private
*/
- handleBeep: function() {
+ handleBeep_() {
// Beeps are annoying, so just track count for now.
this.beepCount_ += 1;
- },
+ }
/**
* Handles a password request from the current controller.
+ * @private
*/
- handlePasswordRequest: function() {
+ handlePasswordRequest_() {
// If the password screen isn't up, put it up. Otherwise we're
// responding to an incorrect password so deny it.
if (!this.passwordScreen_.active) {
@@ -1121,26 +1272,27 @@ PDFViewer.prototype = {
} else {
this.passwordScreen_.deny();
}
- },
+ }
/**
* Handles a selected text reply from the current controller.
* @param {string} selectedText
+ * @private
*/
- handleSelectedTextReply: function(selectedText) {
+ handleSelectedTextReply_(selectedText) {
this.sendScriptingMessage_({
type: 'getSelectedTextReply',
selectedText: selectedText,
});
- },
+ }
/**
* Handles a navigation request from the current controller.
- *
* @param {string} url
- * @param {string} disposition
+ * @param {!PdfNavigator.WindowOpenDisposition} disposition
+ * @private
*/
- handleNavigate: function(url, disposition) {
+ handleNavigate_(url, disposition) {
// If in print preview, always open a new tab.
if (this.isPrintPreview_) {
this.navigator_.navigate(
@@ -1148,24 +1300,48 @@ PDFViewer.prototype = {
} else {
this.navigator_.navigate(url, disposition);
}
- },
+ }
+
+ /**
+ * Handles an internal navigation request to a destination from the current
+ * controller.
+ *
+ * @param {number} page
+ * @param {number} x
+ * @param {number} y
+ * @param {number} zoom
+ * @private
+ */
+ handleNavigateToDestination_(page, x, y, zoom) {
+ if (zoom) {
+ this.viewport_.setZoom(zoom);
+ }
+
+ if (x || y) {
+ this.viewport_.goToPageAndXY(page, x ? x : 0, y ? y : 0);
+ } else {
+ this.viewport_.goToPage(page);
+ }
+ }
/**
* Handles a notification that print preview has loaded from the
* current controller.
+ * @private
*/
- handlePrintPreviewLoaded: function() {
+ handlePrintPreviewLoaded_() {
this.isPrintPreviewLoadingFinished_ = true;
this.sendDocumentLoadedMessage_();
- },
+ }
/**
* Sets document metadata from the current controller.
* @param {string} title
- * @param {Array} bookmarks
+ * @param {!Array<!Bookmark>} bookmarks
* @param {boolean} canSerializeDocument
+ * @private
*/
- setDocumentMetadata: function(title, bookmarks, canSerializeDocument) {
+ setDocumentMetadata_(title, bookmarks, canSerializeDocument) {
if (title) {
document.title = title;
} else {
@@ -1174,47 +1350,40 @@ PDFViewer.prototype = {
this.bookmarks_ = bookmarks;
if (this.toolbar_) {
this.toolbar_.docTitle = document.title;
- this.toolbar_.bookmarks = this.bookmarks;
+ this.toolbar_.bookmarks = this.bookmarks_;
}
this.canSerializeDocument_ = canSerializeDocument;
this.updateAnnotationAvailable_();
- },
+ }
/**
* Sets the is selecting flag from the current controller.
* @param {boolean} isSelecting
+ * @private
*/
- setIsSelecting: function(isSelecting) {
+ setIsSelecting_(isSelecting) {
this.viewportScroller_.setEnableScrolling(isSelecting);
- },
-
- /**
- * Sets the form field focused flag from the current controller.
- * @param {boolean} focused
- */
- setIsFormFieldFocused: function(focused) {
- this.isFormFieldFocused_ = focused;
- },
+ }
/**
* An event handler for when the browser tells the PDF Viewer to perform a
* save.
- *
* @param {string} streamUrl unique identifier for a PDF Viewer instance.
* @private
*/
- onSave: async function(streamUrl) {
+ async onSave_(streamUrl) {
if (streamUrl != this.browserApi_.getStreamInfo().streamUrl) {
return;
}
- this.save();
- },
+ this.save_();
+ }
/**
* Saves the current PDF document to disk.
+ * @private
*/
- save: async function() {
+ async save_() {
PDFMetrics.record(PDFMetrics.UserAction.SAVE);
if (this.hasEnteredAnnotationMode_) {
PDFMetrics.record(PDFMetrics.UserAction.SAVE_WITH_ANNOTATION);
@@ -1257,17 +1426,19 @@ PDFViewer.prototype = {
// Saving in Annotation mode is destructive: crbug.com/919364
this.exitAnnotationMode_();
- },
+ }
- print: async function() {
+ /** @private */
+ async print_() {
PDFMetrics.record(PDFMetrics.UserAction.PRINT);
await this.exitAnnotationMode_();
this.currentController_.print();
- },
+ }
/**
* Updates the toolbar's annotation available flag depending on current
* conditions.
+ * @private
*/
updateAnnotationAvailable_() {
if (!this.toolbar_) {
@@ -1284,408 +1455,67 @@ PDFViewer.prototype = {
annotationAvailable = false;
}
this.toolbar_.annotationAvailable = annotationAvailable;
- },
+ }
- rotateClockwise() {
+ /** @private */
+ rotateClockwise_() {
PDFMetrics.record(PDFMetrics.UserAction.ROTATE);
this.viewport_.rotateClockwise(1);
this.currentController_.rotateClockwise();
this.updateAnnotationAvailable_();
- },
+ }
- rotateCounterclockwise() {
+ /** @private */
+ rotateCounterclockwise_() {
PDFMetrics.record(PDFMetrics.UserAction.ROTATE);
this.viewport_.rotateClockwise(3);
this.currentController_.rotateCounterclockwise();
this.updateAnnotationAvailable_();
- },
-
- setHasUnsavedChanges: function() {
- // Warn the user if they attempt to close the window without saving.
- chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(true);
- },
-
- /** @param {UndoState} state */
- setAnnotationUndoState(state) {
- this.toolbar_.canUndoAnnotation = state.canUndo;
- this.toolbar_.canRedoAnnotation = state.canRedo;
- },
-};
-
-/** @abstract */
-class ContentController {
- constructor() {}
-
- /**
- * A callback that's called before the zoom changes.
- */
- beforeZoom() {}
-
- /**
- * A callback that's called after the zoom changes.
- */
- afterZoom() {}
-
- /**
- * Handles a change to the viewport.
- */
- viewportChanged() {}
-
- /**
- * Rotates the document 90 degrees in the clockwise direction.
- * @abstract
- */
- rotateClockwise() {}
-
- /**
- * Rotates the document 90 degrees in the counter clockwise direction.
- * @abstract
- */
- rotateCounterclockwise() {}
-
- /**
- * Triggers printing of the current document.
- */
- print() {}
-
- /**
- * Undo an edit action.
- */
- undo() {}
-
- /**
- * Redo an edit action.
- */
- redo() {}
-
- /**
- * Requests that the current document be saved.
- * @param {boolean} requireResult whether a response is required, otherwise
- * the controller may save the document to disk internally.
- * @return {Promise<{fileName: string, dataToSave: ArrayBuffer}}
- * @abstract
- */
- save(requireResult) {}
-
- /**
- * Loads PDF document from `data` activates UI.
- * @param {string} fileName
- * @param {ArrayBuffer} data
- * @return {Promise<void>}
- * @abstract
- */
- load(fileName, data) {}
-
- /**
- * Unloads the current document and removes the UI.
- * @abstract
- */
- unload() {}
-}
-
-class InkController extends ContentController {
- /**
- * @param {PDFViewer} viewer
- * @param {Viewport} viewport
- */
- constructor(viewer, viewport) {
- super();
- this.viewer_ = viewer;
- this.viewport_ = viewport;
-
- /** @type {ViewerInkHost} */
- this.inkHost_ = null;
}
- /** @param {AnnotationTool} tool */
- setAnnotationTool(tool) {
- this.tool_ = tool;
- if (this.inkHost_) {
- this.inkHost_.setAnnotationTool(tool);
- }
- }
-
- /** @override */
- rotateClockwise() {
- // TODO(dstockwell): implement rotation
- }
-
- /** @override */
- rotateCounterclockwise() {
- // TODO(dstockwell): implement rotation
- }
-
- /** @override */
- viewportChanged() {
- this.inkHost_.viewportChanged();
- }
-
- /** @override */
- save(requireResult) {
- return this.inkHost_.saveDocument();
- }
-
- /** @override */
- undo() {
- this.inkHost_.undo();
- }
-
- /** @override */
- redo() {
- this.inkHost_.redo();
- }
-
- /** @override */
- load(filename, data) {
- if (!this.inkHost_) {
- this.inkHost_ = document.createElement('viewer-ink-host');
- $('content').appendChild(this.inkHost_);
- this.inkHost_.viewport = this.viewport_;
- this.inkHost_.addEventListener('stroke-added', e => {
- this.viewer_.setHasUnsavedChanges();
- });
- this.inkHost_.addEventListener('undo-state-changed', e => {
- this.viewer_.setAnnotationUndoState(e.detail);
- });
- }
- return this.inkHost_.load(filename, data);
- }
-
- /** @override */
- unload() {
- this.inkHost_.remove();
- this.inkHost_ = null;
- }
-}
-
-class PluginController extends ContentController {
/**
- * @param {HTMLEmbedElement} plugin
- * @param {PDFViewer} viewer
- * @param {Viewport} viewport
- */
- constructor(plugin, viewer, viewport) {
- super();
- this.plugin_ = plugin;
- this.viewer_ = viewer;
- this.viewport_ = viewport;
-
- /** @private {!Map<string, PromiseResolver>} */
- this.pendingTokens_ = new Map();
- this.plugin_.addEventListener(
- 'message', e => this.handlePluginMessage_(e), false);
- }
-
- /**
- * Notify the plugin to stop reacting to scroll events while zoom is taking
- * place to avoid flickering.
- * @override
- */
- beforeZoom() {
- this.postMessage({type: 'stopScrolling'});
-
- if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) {
- const position = this.viewport_.position;
- const zoom = this.viewport_.getZoom();
- const pinchPhase = this.viewport_.pinchPhase;
- this.postMessage({
- type: 'viewport',
- userInitiated: true,
- zoom: zoom,
- xOffset: position.x,
- yOffset: position.y,
- pinchPhase: pinchPhase
- });
- }
- }
-
- /**
- * Notify the plugin of the zoom change and to continue reacting to scroll
- * events.
- * @override
- */
- afterZoom() {
- const position = this.viewport_.position;
- const zoom = this.viewport_.getZoom();
- const pinchVector = this.viewport_.pinchPanVector || {x: 0, y: 0};
- const pinchCenter = this.viewport_.pinchCenter || {x: 0, y: 0};
- const pinchPhase = this.viewport_.pinchPhase;
-
- this.postMessage({
- type: 'viewport',
- userInitiated: this.viewer_.isUserInitiatedEvent_,
- zoom: zoom,
- xOffset: position.x,
- yOffset: position.y,
- pinchPhase: pinchPhase,
- pinchX: pinchCenter.x,
- pinchY: pinchCenter.y,
- pinchVectorX: pinchVector.x,
- pinchVectorY: pinchVector.y
- });
- }
-
- // TODO(dstockwell): this method should be private, add controller APIs that
- // map to all of the existing usage. crbug.com/913279
- /**
- * Post a message to the PPAPI plugin. Some messages will cause an async reply
- * to be received through handlePluginMessage_().
- *
- * @param {Object} message Message to post.
+ * @param {!CustomEvent<{canUndo: boolean, canRedo: boolean}>} e
+ * @private
*/
- postMessage(message) {
- this.plugin_.postMessage(message);
- }
-
- /** @override */
- rotateClockwise() {
- this.postMessage({type: 'rotateClockwise'});
- }
-
- /** @override */
- rotateCounterclockwise() {
- this.postMessage({type: 'rotateCounterclockwise'});
- }
-
- /** @override */
- print() {
- this.postMessage({type: 'print'});
- }
-
- /** @override */
- save(requireResult) {
- const resolver = new PromiseResolver();
- const newToken = createToken();
- this.pendingTokens_.set(newToken, resolver);
- this.postMessage({type: 'save', token: newToken, force: requireResult});
- return resolver.promise;
+ setAnnotationUndoState_(e) {
+ this.toolbar_.canUndoAnnotation = e.detail.canUndo;
+ this.toolbar_.canRedoAnnotation = e.detail.canRedo;
}
- /** @override */
- async load(fileName, data) {
- const url = URL.createObjectURL(new Blob([data]));
- this.plugin_.removeAttribute('headers');
- this.plugin_.setAttribute('stream-url', url);
- this.plugin_.style.display = 'block';
- try {
- await this.viewer_.loaded;
- } finally {
- URL.revokeObjectURL(url);
- }
- }
-
- /** @override */
- unload() {
- this.plugin_.style.display = 'none';
- }
-
- /**
- * An event handler for handling message events received from the plugin.
- *
- * @param {MessageObject} message a message event.
- * @private
- */
- handlePluginMessage_(message) {
- switch (message.data.type.toString()) {
- case 'beep':
- this.viewer_.handleBeep();
- break;
- case 'documentDimensions':
- this.viewer_.setDocumentDimensions(message.data);
- break;
- case 'email':
- const href = 'mailto:' + message.data.to + '?cc=' + message.data.cc +
- '&bcc=' + message.data.bcc + '&subject=' + message.data.subject +
- '&body=' + message.data.body;
- window.location.href = href;
- break;
- case 'getPassword':
- this.viewer_.handlePasswordRequest();
- break;
- case 'getSelectedTextReply':
- this.viewer_.handleSelectedTextReply(message.data.selectedText);
- break;
- case 'goToPage':
- this.viewport_.goToPage(message.data.page);
- break;
- case 'loadProgress':
- this.viewer_.updateProgress(message.data.progress);
- break;
- case 'navigate':
- this.viewer_.handleNavigate(message.data.url, message.data.disposition);
- break;
- case 'printPreviewLoaded':
- this.viewer_.handlePrintPreviewLoaded();
- break;
- case 'setScrollPosition':
- this.viewport_.scrollTo(/** @type {!PartialPoint} */ (message.data));
- break;
- case 'scrollBy':
- this.viewport_.scrollBy(/** @type {!Point} */ (message.data));
- break;
- case 'metadata':
- this.viewer_.setDocumentMetadata(
- message.data.title, message.data.bookmarks,
- message.data.canSerializeDocument);
- break;
- case 'setIsSelecting':
- this.viewer_.setIsSelecting(message.data.isSelecting);
- break;
- case 'getNamedDestinationReply':
- this.viewer_.paramsParser_.onNamedDestinationReceived(
- message.data.pageNumber);
- break;
- case 'formFocusChange':
- this.viewer_.setIsFormFieldFocused(message.data.focused);
- break;
- case 'saveData':
- this.saveData_(message.data);
- break;
- case 'consumeSaveToken':
- const resolver = this.pendingTokens_.get(message.data.token);
- assert(this.pendingTokens_.delete(message.data.token));
- resolver.resolve(null);
- break;
+ /** @private */
+ resetTrackers_() {
+ this.viewport_.resetTracker();
+ if (this.tracker_) {
+ this.tracker_.removeAll();
}
}
+}
- /**
- * Handles the pdf file buffer received from the plugin.
- *
- * @param {SaveDataMessageData} messageData data of the message event.
- * @private
- */
- saveData_(messageData) {
- assert(
- loadTimeData.getBoolean('pdfFormSaveEnabled') ||
- loadTimeData.getBoolean('pdfAnnotationsEnabled'));
-
- // Verify a token that was created by this instance is included to avoid
- // being spammed.
- const resolver = this.pendingTokens_.get(messageData.token);
- assert(this.pendingTokens_.delete(messageData.token));
+/**
+ * The height of the toolbar along the top of the page. The document will be
+ * shifted down by this much in the viewport.
+ */
+PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56;
- if (!messageData.dataToSave) {
- resolver.reject();
- return;
- }
+/**
+ * Minimum height for the material toolbar to show (px). Should match the media
+ * query in index-material.css. If the window is smaller than this at load,
+ * leave no space for the toolbar.
+ */
+PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT = 250;
- // Verify the file size and the first bytes to make sure it's a PDF. Cap at
- // 100 MB. This cap should be kept in sync with and is also enforced in
- // pdf/out_of_process_instance.cc.
- const MIN_FILE_SIZE = '%PDF1.0'.length;
- const MAX_FILE_SIZE = 100 * 1000 * 1000;
+/**
+ * The background color used for print preview (--google-grey-refresh-300).
+ */
+PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR = '0xFFDADCE0';
- const buffer = messageData.dataToSave;
- const bufView = new Uint8Array(buffer);
- assert(
- bufView.length <= MAX_FILE_SIZE,
- `File too large to be saved: ${bufView.length} bytes.`);
- assert(bufView.length >= MIN_FILE_SIZE);
- assert(
- String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) ==
- '%PDF');
+/**
+ * The background color used for print preview when dark mode is enabled
+ * (--google-grey-refresh-700).
+ */
+PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR = '0xFF5F6368';
- resolver.resolve(messageData);
- }
-}
+/**
+ * The background color used for the regular viewer.
+ */
+PDFViewer.BACKGROUND_COLOR = '0xFF525659';
diff --git a/chromium/chrome/browser/resources/pdf/toolbar_manager.js b/chromium/chrome/browser/resources/pdf/toolbar_manager.js
index 255bc3394f1..8a2b06c135c 100644
--- a/chromium/chrome/browser/resources/pdf/toolbar_manager.js
+++ b/chromium/chrome/browser/resources/pdf/toolbar_manager.js
@@ -20,10 +20,8 @@ const TOP_TOOLBAR_REVEAL_DISTANCE = 100;
const SIDE_TOOLBAR_REVEAL_DISTANCE_RIGHT = 150;
const SIDE_TOOLBAR_REVEAL_DISTANCE_BOTTOM = 250;
-
-
/**
- * @param {MouseEvent} e Event to test.
+ * @param {!MouseEvent} e Event to test.
* @return {boolean} True if the mouse is close to the top of the screen.
*/
function isMouseNearTopToolbar(e) {
@@ -31,7 +29,7 @@ function isMouseNearTopToolbar(e) {
}
/**
- * @param {MouseEvent} e Event to test.
+ * @param {!MouseEvent} e Event to test.
* @param {Window} window Window to test against.
* @param {boolean} reverse Whether the side toolbar is reversed.
* @return {boolean} True if the mouse is close to the bottom-right of the
@@ -47,47 +45,60 @@ function isMouseNearSideToolbar(e, window, reverse) {
return atSide && atBottom;
}
-/**
- * Constructs a Toolbar Manager, responsible for co-ordinating between multiple
- * toolbar elements.
- *
- * @param {Object} window The window containing the UI.
- * @param {Object} toolbar The top toolbar element.
- * @param {Object} zoomToolbar The zoom toolbar element.
- * @constructor
- */
-function ToolbarManager(window, toolbar, zoomToolbar) {
- this.window_ = window;
- this.toolbar_ = toolbar;
- this.zoomToolbar_ = zoomToolbar;
+/** Responsible for co-ordinating between multiple toolbar elements. */
+class ToolbarManager {
+ /**
+ * @param {!Window} window The window containing the UI.
+ * @param {?ViewerPdfToolbarElement} toolbar
+ * @param {!ViewerZoomToolbarElement} zoomToolbar
+ */
+ constructor(window, toolbar, zoomToolbar) {
+ /** @private {!Window} */
+ this.window_ = window;
- this.toolbarTimeout_ = null;
- this.isMouseNearTopToolbar_ = false;
- this.isMouseNearSideToolbar_ = false;
+ /** @private {?ViewerPdfToolbarElement} */
+ this.toolbar_ = toolbar;
- this.sideToolbarAllowedOnly_ = false;
- this.sideToolbarAllowedOnlyTimer_ = null;
+ /** @private {!ViewerZoomToolbarElement} */
+ this.zoomToolbar_ = zoomToolbar;
- this.keyboardNavigationActive = false;
+ /** @private {?number} */
+ this.toolbarTimeout_ = null;
- this.lastMovementTimestamp = null;
+ /** @private {boolean} */
+ this.isMouseNearTopToolbar_ = false;
- this.reverseSideToolbar_ = false;
+ /** @private {boolean} */
+ this.isMouseNearSideToolbar_ = false;
- this.window_.addEventListener('resize', this.resizeDropdowns_.bind(this));
- this.resizeDropdowns_();
+ /** @private {boolean} */
+ this.sideToolbarAllowedOnly_ = false;
- if (zoomToolbar.isPrintPreview()) {
- this.zoomToolbar_.addEventListener('keyboard-navigation-active', e => {
- this.keyboardNavigationActive = e.detail;
- });
- }
-}
+ /** @private {?number} */
+ this.sideToolbarAllowedOnlyTimer_ = null;
+
+ /** @private {boolean} */
+ this.keyboardNavigationActive = false;
+
+ /** @private {?number} */
+ this.lastMovementTimestamp = null;
-ToolbarManager.prototype = {
+ /** @private {boolean} */
+ this.reverseSideToolbar_ = false;
+
+ this.window_.addEventListener('resize', this.resizeDropdowns_.bind(this));
+ this.resizeDropdowns_();
+
+ if (zoomToolbar.isPrintPreview()) {
+ this.zoomToolbar_.addEventListener('keyboard-navigation-active', e => {
+ this.keyboardNavigationActive = e.detail;
+ });
+ }
+ }
- handleMouseMove: function(e) {
- this.isMouseNearTopToolbar_ = this.toolbar_ && isMouseNearTopToolbar(e);
+ /** @param {!MouseEvent} e */
+ handleMouseMove(e) {
+ this.isMouseNearTopToolbar_ = !!this.toolbar_ && isMouseNearTopToolbar(e);
this.isMouseNearSideToolbar_ =
isMouseNearSideToolbar(e, this.window_, this.reverseSideToolbar_);
@@ -123,17 +134,16 @@ ToolbarManager.prototype = {
}
}
this.hideToolbarsAfterTimeout();
- },
+ }
/**
* Whether a mousemove event is high enough velocity to reveal the toolbars.
- *
- * @param {MouseEvent} e Event to test.
+ * @param {!MouseEvent} e Event to test.
* @return {boolean} true if the event is a high velocity mousemove, false
* otherwise.
* @private
*/
- isHighVelocityMouseMove_: function(e) {
+ isHighVelocityMouseMove_(e) {
if (e.type == 'mousemove') {
if (this.lastMovementTimestamp == null) {
this.lastMovementTimestamp = this.getCurrentTimestamp_();
@@ -150,54 +160,51 @@ ToolbarManager.prototype = {
}
}
return false;
- },
+ }
/**
* Wrapper around Date.now() to make it easily replaceable for testing.
- *
* @return {number}
* @private
*/
- getCurrentTimestamp_: function() {
+ getCurrentTimestamp_() {
return Date.now();
- },
+ }
- /**
- * Display both UI toolbars.
- */
- showToolbars: function() {
+ /** Display both UI toolbars. */
+ showToolbars() {
if (this.toolbar_) {
this.toolbar_.show();
}
this.zoomToolbar_.show();
- },
+ }
/**
* Show toolbars and mark that navigation is being performed with
* tab/shift-tab. This disables toolbar hiding until the mouse is moved or
* escape is pressed.
*/
- showToolbarsForKeyboardNavigation: function() {
+ showToolbarsForKeyboardNavigation() {
this.keyboardNavigationActive = true;
this.showToolbars();
- },
+ }
/**
* Hide toolbars after a delay, regardless of the position of the mouse.
* Intended to be called when the mouse has moved out of the parent window.
*/
- hideToolbarsForMouseOut: function() {
+ hideToolbarsForMouseOut() {
this.isMouseNearTopToolbar_ = false;
this.isMouseNearSideToolbar_ = false;
this.hideToolbarsAfterTimeout();
- },
+ }
/**
* Check if the toolbars are able to be closed, and close them if they are.
* Toolbars may be kept open based on mouse/keyboard activity and active
* elements.
*/
- hideToolbarsIfAllowed: function() {
+ hideToolbarsIfAllowed() {
if (this.isMouseNearSideToolbar_ || this.isMouseNearTopToolbar_) {
return;
}
@@ -221,47 +228,44 @@ ToolbarManager.prototype = {
this.toolbar_.hide();
}
this.zoomToolbar_.hide();
- },
+ }
- /**
- * Hide the toolbar after the HIDE_TIMEOUT has elapsed.
- */
- hideToolbarsAfterTimeout: function() {
+ /** Hide the toolbars after the HIDE_TIMEOUT has elapsed. */
+ hideToolbarsAfterTimeout() {
if (this.toolbarTimeout_) {
this.window_.clearTimeout(this.toolbarTimeout_);
}
this.toolbarTimeout_ = this.window_.setTimeout(
this.hideToolbarsIfAllowed.bind(this), HIDE_TIMEOUT);
- },
+ }
/**
* Hide the 'topmost' layer of toolbars. Hides any dropdowns that are open, or
* hides the basic toolbars otherwise.
*/
- hideSingleToolbarLayer: function() {
+ hideSingleToolbarLayer() {
if (!this.toolbar_ || !this.toolbar_.hideDropdowns()) {
this.keyboardNavigationActive = false;
this.hideToolbarsIfAllowed();
}
- },
+ }
/**
* Clears the keyboard navigation state and hides the toolbars after a delay.
*/
- resetKeyboardNavigationAndHideToolbars: function() {
+ resetKeyboardNavigationAndHideToolbars() {
this.keyboardNavigationActive = false;
this.hideToolbarsAfterTimeout();
- },
+ }
/**
* Hide the top toolbar and keep it hidden until both:
* - The mouse is moved away from the right side of the screen
* - 1 second has passed.
- *
* The top toolbar can be immediately re-opened by moving the mouse to the top
* of the screen.
*/
- forceHideTopToolbar: function() {
+ forceHideTopToolbar() {
if (!this.toolbar_) {
return;
}
@@ -270,20 +274,19 @@ ToolbarManager.prototype = {
this.sideToolbarAllowedOnlyTimer_ = this.window_.setTimeout(() => {
this.sideToolbarAllowedOnlyTimer_ = null;
}, FORCE_HIDE_TIMEOUT);
- },
+ }
/** Reverse the position of the side toolbar. */
- reverseSideToolbar: function() {
+ reverseSideToolbar() {
this.reverseSideToolbar_ = true;
- },
+ }
/**
* Updates the size of toolbar dropdowns based on the positions of the rest of
* the UI.
- *
* @private
*/
- resizeDropdowns_: function() {
+ resizeDropdowns_() {
if (!this.toolbar_) {
return;
}
@@ -291,4 +294,4 @@ ToolbarManager.prototype = {
this.window_.innerHeight - this.zoomToolbar_.clientHeight;
this.toolbar_.setDropdownLowerBound(lowerBound);
}
-};
+}
diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js
index 480664c014c..17986ae5d81 100644
--- a/chromium/chrome/browser/resources/pdf/viewport.js
+++ b/chromium/chrome/browser/resources/pdf/viewport.js
@@ -6,14 +6,21 @@
* @typedef {{
* width: number,
* height: number,
+ * layoutOptions: (!LayoutOptions|undefined),
* pageDimensions: Array<ViewportRect>,
* }}
*/
let DocumentDimensions;
+/** @typedef {{defaultPageOrientation: number}} */
+let LayoutOptions;
+
/** @typedef {{x: number, y: number}} */
let Point;
+/** @typedef {{x: (number|undefined), y: (number|undefined)}} */
+let PartialPoint;
+
/** @typedef {{width: number, height: number}} */
let Size;
@@ -279,6 +286,15 @@ class Viewport {
}
/**
+ * @return {!LayoutOptions|undefined} A dictionary carrying layout options
+ * from the plugin.
+ */
+ getLayoutOptions() {
+ return this.documentDimensions_ ? this.documentDimensions_.layoutOptions :
+ undefined;
+ }
+
+ /**
* @return {!ViewportRect} ViewportRect for the viewport given current zoom.
* @private
*/
@@ -605,7 +621,7 @@ class Viewport {
const bottom =
this.pageDimensions_[page].y + this.pageDimensions_[page].height;
- if (top <= y && bottom > y) {
+ if (top <= y && y <= bottom) {
return page;
}
@@ -1166,7 +1182,9 @@ class Viewport {
this.fittingType_ == FittingType.FIT_TO_HEIGHT);
}
- /** @param {!Point} point The position to which to scroll the viewport. */
+ /**
+ * @param {!PartialPoint} point The position to which to scroll the viewport.
+ */
scrollTo(point) {
let changed = false;
const newPosition = this.position;
diff --git a/chromium/chrome/browser/resources/pdf/viewport_scroller.js b/chromium/chrome/browser/resources/pdf/viewport_scroller.js
index bb8c187d478..ca16c9cf7d2 100644
--- a/chromium/chrome/browser/resources/pdf/viewport_scroller.js
+++ b/chromium/chrome/browser/resources/pdf/viewport_scroller.js
@@ -5,75 +5,61 @@
'use strict';
/**
- * The period of time in milliseconds to wait between updating the viewport
- * position by the scroll velocity.
- *
- * @private
- */
-ViewportScroller.DRAG_TIMER_INTERVAL_MS_ = 100;
-
-/**
- * The maximum drag scroll distance per DRAG_TIMER_INTERVAL in pixels.
- *
- * @private
- */
-ViewportScroller.MAX_DRAG_SCROLL_DISTANCE_ = 100;
-
-/**
* Creates a new ViewportScroller.
* A ViewportScroller scrolls the page in response to drag selection with the
* mouse.
*
- * @param {Object} viewport The viewport info of the page.
- * @param {Object} plugin The PDF plugin element.
- * @param {Object} window The window containing the viewer.
- * @constructor
*/
-function ViewportScroller(viewport, plugin, window) {
- this.viewport_ = viewport;
- this.plugin_ = plugin;
- this.window_ = window;
- this.mousemoveCallback_ = null;
- this.timerId_ = null;
- this.scrollVelocity_ = null;
- this.lastFrameTime_ = 0;
-}
+class ViewportScroller {
+ /**
+ * @param {Object} viewport The viewport info of the page.
+ * @param {Object} plugin The PDF plugin element.
+ * @param {Object} window The window containing the viewer.
+ */
+ constructor(viewport, plugin, window) {
+ this.viewport_ = viewport;
+ this.plugin_ = plugin;
+ this.window_ = window;
+ this.mousemoveCallback_ = null;
+ this.timerId_ = null;
+ this.scrollVelocity_ = null;
+ this.lastFrameTime_ = 0;
+ }
-ViewportScroller.prototype = {
/**
* Start scrolling the page by |scrollVelocity_| every
* |DRAG_TIMER_INTERVAL_MS_|.
*
* @private
*/
- startDragScrollTimer_: function() {
+ startDragScrollTimer_() {
if (this.timerId_ === null) {
this.timerId_ = this.window_.setInterval(
this.dragScrollPage_.bind(this),
ViewportScroller.DRAG_TIMER_INTERVAL_MS_);
this.lastFrameTime_ = Date.now();
}
- },
+ }
/**
* Stops the drag scroll timer if it is active.
*
* @private
*/
- stopDragScrollTimer_: function() {
+ stopDragScrollTimer_() {
if (this.timerId_ !== null) {
this.window_.clearInterval(this.timerId_);
this.timerId_ = null;
this.lastFrameTime_ = 0;
}
- },
+ }
/**
* Scrolls the viewport by the current scroll velocity.
*
* @private
*/
- dragScrollPage_: function() {
+ dragScrollPage_() {
const position = this.viewport_.position;
const currentFrameTime = Date.now();
const timeAdjustment = (currentFrameTime - this.lastFrameTime_) /
@@ -82,7 +68,7 @@ ViewportScroller.prototype = {
position.x += (this.scrollVelocity_.x * timeAdjustment);
this.viewport_.position = position;
this.lastFrameTime_ = currentFrameTime;
- },
+ }
/**
* Calculate the velocity to scroll while dragging using the distance of the
@@ -92,7 +78,7 @@ ViewportScroller.prototype = {
* @return {Object} Object with x and y direction scroll velocity.
* @private
*/
- calculateVelocity_: function(event) {
+ calculateVelocity_(event) {
const x =
Math.min(
Math.max(
@@ -106,7 +92,7 @@ ViewportScroller.prototype = {
ViewportScroller.MAX_DRAG_SCROLL_DISTANCE_) *
Math.sign(event.offsetY);
return {x: x, y: y};
- },
+ }
/**
* Handles mousemove events. It updates the scroll velocity and starts and
@@ -115,14 +101,14 @@ ViewportScroller.prototype = {
* @param {Object} event The mousemove event.
* @private
*/
- onMousemove_: function(event) {
+ onMousemove_(event) {
this.scrollVelocity_ = this.calculateVelocity_(event);
if (!this.scrollVelocity_.x && !this.scrollVelocity_.y) {
this.stopDragScrollTimer_();
} else if (!this.timerId_) {
this.startDragScrollTimer_();
}
- },
+ }
/**
* Sets whether to scroll the viewport when the mouse is outside the
@@ -130,7 +116,7 @@ ViewportScroller.prototype = {
*
* @param {boolean} isSelecting Represents selection status.
*/
- setEnableScrolling: function(isSelecting) {
+ setEnableScrolling(isSelecting) {
if (isSelecting) {
if (!this.mousemoveCallback_) {
this.mousemoveCallback_ = this.onMousemove_.bind(this);
@@ -145,4 +131,19 @@ ViewportScroller.prototype = {
}
}
}
-};
+}
+
+/**
+ * The period of time in milliseconds to wait between updating the viewport
+ * position by the scroll velocity.
+ *
+ * @private
+ */
+ViewportScroller.DRAG_TIMER_INTERVAL_MS_ = 100;
+
+/**
+ * The maximum drag scroll distance per DRAG_TIMER_INTERVAL in pixels.
+ *
+ * @private
+ */
+ViewportScroller.MAX_DRAG_SCROLL_DISTANCE_ = 100;