summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/resources/pdf')
-rw-r--r--chromium/chrome/browser/resources/pdf/BUILD.gn23
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html10
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js63
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.html12
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.js5
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js4
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn20
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html13
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js135
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn15
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html2
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js86
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn25
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html6
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.js86
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js20
-rw-r--r--chromium/chrome/browser/resources/pdf/index.html3
-rw-r--r--chromium/chrome/browser/resources/pdf/navigator.js252
-rw-r--r--chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js8
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf_viewer.js91
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport.js623
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport_interface.js136
-rw-r--r--chromium/chrome/browser/resources/pdf/zoom_manager.js79
23 files changed, 964 insertions, 753 deletions
diff --git a/chromium/chrome/browser/resources/pdf/BUILD.gn b/chromium/chrome/browser/resources/pdf/BUILD.gn
index 1483ff4a9a0..89a0223ca86 100644
--- a/chromium/chrome/browser/resources/pdf/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/BUILD.gn
@@ -14,6 +14,9 @@ group("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",
]
if (is_chromeos) {
deps += [
@@ -54,17 +57,12 @@ js_library("pdf_scripting_api") {
js_library("viewport_scroller") {
}
-js_library("viewport_interface") {
- deps = [
- ":pdf_fitting_type",
- ]
-}
-
js_library("viewport") {
deps = [
":gesture_detector",
- ":viewport_interface",
+ ":pdf_fitting_type",
":zoom_manager",
+ "//ui/webui/resources/js:event_tracker",
"//ui/webui/resources/js:util",
]
externs_list = [ "$externs_path/pending.js" ]
@@ -73,7 +71,7 @@ js_library("viewport") {
js_library("zoom_manager") {
deps = [
":browser_api",
- ":viewport_interface",
+ "//ui/webui/resources/js/cr:event_target",
]
}
@@ -81,16 +79,23 @@ js_library("metrics") {
externs_list = [ "$externs_path/metrics_private.js" ]
}
+js_library("navigator") {
+ deps = [
+ ":open_pdf_params_parser",
+ ":viewport",
+ ]
+}
+
js_type_check("pdf_resources") {
deps = [
":browser_api",
":gesture_detector",
":metrics",
+ ":navigator",
":open_pdf_params_parser",
":pdf_fitting_type",
":pdf_scripting_api",
":viewport",
- ":viewport_interface",
":viewport_scroller",
":zoom_manager",
]
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
index ae14eeb289f..004aa1b1677 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
@@ -49,21 +49,21 @@
transform: rotate(180deg);
}
- :host([children-shown]) #expand {
+ :host([children-shown_]) #expand {
transform: rotate(90deg);
}
</style>
- <div id="item" on-click="onClick">
+ <div id="item" on-click="onClick_">
<paper-ripple></paper-ripple>
<cr-icon-button id="expand" iron-icon="cr:chevron-right"
- on-click="toggleChildren"></cr-icon-button>
+ on-click="toggleChildren_"></cr-icon-button>
<span id="title" tabindex="0">{{bookmark.title}}</span>
</div>
<!-- dom-if will stamp the complex bookmark tree lazily as individual nodes
are opened. -->
- <template is="dom-if" if="[[childrenShown]]" id="sub-bookmarks">
+ <template is="dom-if" if="[[childrenShown_]]">
<template is="dom-repeat" items="[[bookmark.children]]">
- <viewer-bookmark bookmark="{{item}}" depth="{{childDepth}}">
+ <viewer-bookmark bookmark="{{item}}" depth="[[childDepth_]]">
</viewer-bookmark>
</template>
</template>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
index 160191b6ecb..f1cce48abaa 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
@@ -15,9 +15,9 @@
* structure.
* @typedef {{
* title: string,
- * page: number,
- * y: number,
- * uri: string,
+ * page: (number | undefined),
+ * y: (number | undefined),
+ * uri: (string | undefined),
* children: !Array<!Bookmark>
* }}
*/
@@ -32,13 +32,25 @@ Polymer({
properties: {
/** @type {Bookmark} */
- bookmark: {type: Object, observer: 'bookmarkChanged_'},
-
- depth: {type: Number, observer: 'depthChanged'},
-
- childDepth: Number,
-
- childrenShown: {type: Boolean, reflectToAttribute: true, value: false},
+ bookmark: {
+ type: Object,
+ observer: 'bookmarkChanged_',
+ },
+
+ depth: {
+ type: Number,
+ observer: 'depthChanged_'
+ },
+
+ /** @private */
+ childDepth_: Number,
+
+ /** @private */
+ childrenShown_: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ },
/** @type {?HTMLElement} The target for the key bindings below. */
keyEventTarget: Object,
@@ -53,18 +65,21 @@ Polymer({
this.keyEventTarget = this.$.item;
},
+ /** @private */
bookmarkChanged_: function() {
this.$.expand.style.visibility =
this.bookmark.children.length > 0 ? 'visible' : 'hidden';
},
- depthChanged: function() {
- this.childDepth = this.depth + 1;
+ /** @private */
+ depthChanged_: function() {
+ this.childDepth_ = this.depth + 1;
this.$.item.style.paddingInlineStart =
(this.depth * BOOKMARK_INDENT) + 'px';
},
- onClick: function() {
+ /** @private */
+ onClick_: function() {
if (this.bookmark.hasOwnProperty('page')) {
if (this.bookmark.hasOwnProperty('y')) {
this.fire('change-page-and-xy', {
@@ -82,25 +97,37 @@ Polymer({
}
},
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
onEnter_: function(e) {
// Don't allow events which have propagated up from the expand button to
// trigger a click.
if (e.detail.keyboardEvent.target != this.$.expand) {
- this.onClick();
+ this.onClick_();
}
},
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
onSpace_: function(e) {
// cr-icon-button stops propagation of space events, so there's no need
// to check the event source here.
- this.onClick();
+ this.onClick_();
// Prevent default space scroll behavior.
e.detail.keyboardEvent.preventDefault();
},
- toggleChildren: function(e) {
- this.childrenShown = !this.childrenShown;
- e.stopPropagation(); // Prevent the above onClick handler from firing.
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ toggleChildren_: function(e) {
+ this.childrenShown_ = !this.childrenShown_;
+ e.stopPropagation(); // Prevent the above onClick_ handler from firing.
}
});
})();
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.html b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.html
deleted file mode 100644
index 2277ec4d941..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="../viewer-bookmark/viewer-bookmark.html">
-
-<dom-module id="viewer-bookmarks-content">
- <template>
- <template is="dom-repeat" items="[[bookmarks]]">
- <viewer-bookmark bookmark="{{item}}" depth="0"></viewer-bookmark>
- </template>
- </template>
- <script src="viewer-bookmarks-content.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.js b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.js
deleted file mode 100644
index 32f3fd320d5..00000000000
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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.
-
-Polymer({is: 'viewer-bookmarks-content'});
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/viewer-ink-host.js
index 6bb2e4c68ed..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/viewer-ink-host.js
@@ -47,7 +47,7 @@ Polymer({
/** @private {boolean} */
penMode_: false,
- /** @type {Viewport} */
+ /** @type {?Viewport} */
viewport: null,
/** @type {?AnnotationTool} */
@@ -247,7 +247,7 @@ Polymer({
const viewport = this.viewport;
const pos = viewport.position;
const size = viewport.size;
- const zoom = viewport.zoom;
+ const zoom = viewport.getZoom();
const documentWidth = viewport.getDocumentDimensions().width * zoom;
// Adjust for page shadows.
const y = pos.y - Viewport.PAGE_SHADOW.top * zoom;
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
new file mode 100644
index 00000000000..fdc650f55b9
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/BUILD.gn
@@ -0,0 +1,20 @@
+# 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-pdf-toolbar/viewer-pdf-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
index f6454c97a5c..e183debc86d 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/viewer-pdf-toolbar.html
@@ -5,7 +5,7 @@
<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-bookmarks-content/viewer-bookmarks-content.html">
+<link rel="import" href="../viewer-bookmark/viewer-bookmark.html">
<link rel="import" href="../viewer-page-selector/viewer-page-selector.html">
<if expr="chromeos">
<link rel="import" href="../viewer-pen-options/viewer-pen-options.html">
@@ -214,8 +214,9 @@
open-icon="pdf:bookmark"
closed-icon="pdf:bookmark-border"
header="{{strings.bookmarks}}">
- <viewer-bookmarks-content bookmarks="{{bookmarks}}">
- </viewer-bookmarks-content>
+ <template is="dom-repeat" items="[[bookmarks]]">
+ <viewer-bookmark bookmark="[[item]]" depth="0"></viewer-bookmark>
+ </template>
</viewer-toolbar-dropdown>
</div>
</div>
@@ -228,7 +229,7 @@
<div id="annotations-bar" hidden>
<viewer-toolbar-dropdown id="pen"
- selected$="[[equal_('pen', annotationTool.tool)]]"
+ selected$="[[isAnnotationTool_('pen', annotationTool.tool)]]"
open-after-select
on-click="annotationToolClicked_"
open-icon="pdf:marker"
@@ -247,7 +248,7 @@
</viewer-toolbar-dropdown>
<viewer-toolbar-dropdown id="highlighter"
- selected$="[[equal_('highlighter', annotationTool.tool)]]"
+ selected$="[[isAnnotationTool_('highlighter', annotationTool.tool)]]"
open-after-select
on-click="annotationToolClicked_"
open-icon="pdf:highlighter"
@@ -266,7 +267,7 @@
</viewer-toolbar-dropdown>
<cr-icon-button id="eraser"
- selected$="[[equal_('eraser', annotationTool.tool)]]"
+ selected$="[[isAnnotationTool_('eraser', annotationTool.tool)]]"
on-click="annotationToolClicked_" iron-icon="pdf:eraser"
aria-label$="{{strings.annotationEraser}}"
title$="{{strings.annotationEraser}}"></cr-icon-button>
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/viewer-pdf-toolbar.js
index 006aa5ca5b8..afb87dfe6b7 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/viewer-pdf-toolbar.js
@@ -7,38 +7,16 @@ Polymer({
properties: {
/**
- * The current loading progress of the PDF document (0 - 100).
- */
- loadProgress: {type: Number, observer: 'loadProgressChanged_'},
-
- /**
- * The title of the PDF document.
- */
- docTitle: String,
-
- /**
- * The number of the page being viewed (1-based).
- */
- pageNo: Number,
-
- /**
- * Tree of PDF bookmarks (or null if the document has no bookmarks).
- */
- bookmarks: {type: Object, value: null},
-
- /**
- * The number of pages in the PDF document.
- */
- docLength: Number,
-
- /**
- * Whether the toolbar is opened and visible.
+ * Whether annotation mode can be entered. This would be false if for
+ * example the PDF is encrypted or password protected. Note, this is
+ * true regardless of whether the feature flag is enabled.
*/
- opened: {type: Boolean, value: true},
+ annotationAvailable: {
+ type: Boolean,
+ value: true,
+ },
- /**
- * Whether the viewer is currently in annotation mode.
- */
+ /** Whether the viewer is currently in annotation mode. */
annotationMode: {
type: Boolean,
notify: true,
@@ -46,6 +24,7 @@ Polymer({
reflectToAttribute: true,
},
+ /** @type {?Object} */
annotationTool: {
type: Object,
value: null,
@@ -53,13 +32,17 @@ Polymer({
},
/**
- * Whether annotation mode can be entered. This would be false if for
- * example the PDF is encrypted or password protected. Note, this is
- * true regardless of whether the feature flag is enabled.
+ * Tree of PDF bookmarks (empty if the document has no bookmarks).
+ * @type {!Array<!Bookmark>}
*/
- annotationAvailable: {
+ bookmarks: {
+ type: Array,
+ value: () => [],
+ },
+
+ canRedoAnnotation: {
type: Boolean,
- value: true,
+ value: false,
},
canUndoAnnotation: {
@@ -67,22 +50,34 @@ Polymer({
value: false,
},
- canRedoAnnotation: {
+ /** The number of pages in the PDF document. */
+ docLength: Number,
+
+ /** The title of the PDF document. */
+ docTitle: String,
+
+ /** The current loading progress of the PDF document (0 - 100). */
+ loadProgress: {
+ type: Number,
+ observer: 'loadProgressChanged_',
+ },
+
+ /** Whether the toolbar is opened and visible. */
+ opened: {
type: Boolean,
- value: false,
+ value: true,
},
- /**
- * Whether the PDF Annotations feature is enabled.
- */
+ /** The number of the page being viewed (1-based). */
+ pageNo: Number,
+
+ /** Whether the PDF Annotations feature is enabled. */
pdfAnnotationsEnabled: {
type: Boolean,
value: false,
},
- /**
- * Whether the Printing feature is enabled.
- */
+ /** Whether the Printing feature is enabled. */
printingEnabled: {
type: Boolean,
value: false,
@@ -91,6 +86,9 @@ Polymer({
strings: Object,
},
+ /** @type {?Object} */
+ animation_: null,
+
/**
* @param {number} newProgress
* @param {number} oldProgress
@@ -130,22 +128,16 @@ Polymer({
if (this.opened) {
this.animation_ = this.animate(
- {
- transform: ['translateY(-100%)', 'translateY(0%)'],
- },
- {
- easing: 'cubic-bezier(0, 0, 0.2, 1)',
+ [{transform: 'translateY(-100%)'}, {transform: 'translateY(0%)'}], {
duration: 250,
+ easing: 'cubic-bezier(0, 0, 0.2, 1)',
fill: 'forwards',
});
} else {
this.animation_ = this.animate(
- {
- transform: ['translateY(0%)', 'translateY(-100%)'],
- },
- {
- easing: 'cubic-bezier(0.4, 0, 1, 1)',
+ [{transform: 'translateY(0%)'}, {transform: 'translateY(-100%)'}], {
duration: 250,
+ easing: 'cubic-bezier(0.4, 0, 1, 1)',
fill: 'forwards',
});
}
@@ -155,11 +147,13 @@ Polymer({
this.$.pageselector.select();
},
+ /** @return {boolean} Whether the toolbar should be kept open. */
shouldKeepOpen: function() {
return this.$.bookmarks.dropdownOpen || this.loadProgress < 100 ||
this.$.pageselector.isActive() || this.annotationMode;
},
+ /** @return {boolean} Whether a dropdown was open and was hidden. */
hideDropdowns: function() {
let result = false;
if (this.$.bookmarks.dropdownOpen) {
@@ -177,6 +171,7 @@ Polymer({
return result;
},
+ /** @param {number} lowerBound */
setDropdownLowerBound: function(lowerBound) {
this.$.bookmarks.lowerBound = lowerBound;
},
@@ -214,12 +209,18 @@ Polymer({
}));
},
- /** @param {Event} e */
+ /**
+ * @param {!Event} e
+ * @private
+ */
annotationToolClicked_: function(e) {
- this.updateAnnotationTool_(e.currentTarget);
+ this.updateAnnotationTool_(/** @type {!HTMLElement} */ (e.currentTarget));
},
- /** @param {Event} e */
+ /**
+ * @param {!Event} e
+ * @private
+ */
annotationToolOptionChanged_: function(e) {
const element = e.currentTarget.parentElement;
if (!this.annotationTool || element.id != this.annotationTool.tool) {
@@ -228,15 +229,19 @@ Polymer({
this.updateAnnotationTool_(e.currentTarget.parentElement);
},
- /** @param {Element} element */
+ /**
+ * @param {!HTMLElement} element
+ * @private
+ */
updateAnnotationTool_: function(element) {
const tool = element.id;
const options = element.querySelector('viewer-pen-options') || {
selectedSize: 1,
selectedColor: null,
};
- element.attributeStyleMap.set('--pen-tip-fill', options.selectedColor);
- element.attributeStyleMap.set(
+ const attributeStyleMap = element.attributeStyleMap;
+ attributeStyleMap.set('--pen-tip-fill', options.selectedColor);
+ attributeStyleMap.set(
'--pen-tip-border',
options.selectedColor == '#000000' ? 'currentcolor' :
options.selectedColor);
@@ -248,14 +253,12 @@ Polymer({
},
/**
- * Used to determine equality in computed bindings.
- *
- * @param {*} a
- * @param {*} b
+ * @param {string} toolName
+ * @return {boolean} Whether the annotation tool is using tool |toolName|.
+ * @private
*/
- equal_: function(a, b) {
- return a == b;
+ isAnnotationTool_: function(toolName) {
+ return !!this.annotationTool && this.annotationTool.tool === toolName;
},
-
});
})();
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
new file mode 100644
index 00000000000..7a2ca5ce91a
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/BUILD.gn
@@ -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.
+
+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-toolbar-dropdown/viewer-toolbar-dropdown.html b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
index c1964a19a20..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/viewer-toolbar-dropdown.html
@@ -91,7 +91,7 @@
}
</style>
<cr-icon-button on-click="toggleDropdown" id="button"
- iron-icon="[[dropdownIcon]],cr:arrow-drop-down" title$="[[header]]">
+ iron-icon="[[dropdownIcon_]],cr:arrow-drop-down" title$="[[header]]">
</cr-icon-button>
<div id="container">
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/viewer-toolbar-dropdown.js
index 05f044afe47..00b2b676b45 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/viewer-toolbar-dropdown.js
@@ -18,6 +18,23 @@ Polymer({
is: 'viewer-toolbar-dropdown',
properties: {
+ /** Icon to display when the dropdown is closed. */
+ closedIcon: String,
+
+ /** Whether the dropdown should be centered or right aligned. */
+ dropdownCentered: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ },
+
+ /** True if the dropdown is currently open. */
+ dropdownOpen: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ },
+
/**
* String to be displayed at the top of the dropdown and for the tooltip
* of the button.
@@ -25,43 +42,53 @@ Polymer({
header: String,
/** Whether to hide the header at the top of the dropdown. */
- hideHeader: {type: Boolean, value: false},
-
- /** Icon to display when the dropdown is closed. */
- closedIcon: String,
+ hideHeader: {
+ type: Boolean,
+ value: false,
+ },
- /** Icon to display when the dropdown is open. */
- openIcon: String,
+ /** Lowest vertical point that the dropdown should occupy (px). */
+ lowerBound: {
+ type: Number,
+ observer: 'lowerBoundChanged_',
+ },
/** Unique id to identify this dropdown for metrics purposes. */
metricsId: String,
- /** True if the dropdown is currently open. */
- dropdownOpen: {type: Boolean, reflectToAttribute: true, value: false},
+ /** Whether the dropdown must be selected before opening. */
+ openAfterSelect: {
+ type: Boolean,
+ value: false,
+ },
- /** Whether the dropdown should be centered or right aligned. */
- dropdownCentered: {type: Boolean, reflectToAttribute: true, value: false},
+ /** Icon to display when the dropdown is open. */
+ openIcon: String,
/** Whether the dropdown is marked as selected. */
- selected: {type: Boolean, reflectToAttribute: true, value: false},
-
- /** Whether the dropdown must be selected before opening. */
- openAfterSelect: {type: Boolean, reflectToAttribute: true, value: false},
+ selected: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ },
- /** Toolbar icon currently being displayed. */
- dropdownIcon: {
+ /**
+ * Toolbar icon currently being displayed.
+ * @private
+ */
+ dropdownIcon_: {
type: String,
- computed: 'computeIcon_(dropdownOpen, closedIcon, openIcon)'
+ computed: 'computeIcon_(dropdownOpen, closedIcon, openIcon)',
},
-
- /** Lowest vertical point that the dropdown should occupy (px). */
- lowerBound: {type: Number, observer: 'lowerBoundChanged_'},
-
- /** Current animation being played, or null if there is none. */
- animation_: Object
},
/**
+ * Current animation being played, or null if there is none.
+ * @private {?Object}
+ */
+ animation_: null,
+
+ /**
* True if the max-height CSS property for the dropdown scroll container
* is valid. If false, the height will be updated the next time the
* dropdown is visible.
@@ -69,10 +96,15 @@ Polymer({
*/
maxHeightValid_: false,
+ /**
+ * @return {string} Current icon for the dropdown.
+ * @private
+ */
computeIcon_: function(dropdownOpen, closedIcon, openIcon) {
return dropdownOpen ? openIcon : closedIcon;
},
+ /** @private */
lowerBoundChanged_: function() {
this.maxHeightValid_ = false;
if (this.dropdownOpen) {
@@ -137,6 +169,10 @@ Polymer({
};
},
+ /**
+ * @return {!Object} Animation
+ * @private
+ */
animateEntry_: function() {
let maxHeight =
this.$.dropdown.getBoundingClientRect().height - DROPDOWN_OUTER_PADDING;
@@ -164,6 +200,10 @@ Polymer({
});
},
+ /**
+ * @return {!Object} Animation
+ * @private
+ */
animateExit_: function() {
return this.$.dropdown.animate(
[
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
new file mode 100644
index 00000000000..4c75971c261
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/BUILD.gn
@@ -0,0 +1,25 @@
+# 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/elements/viewer-zoom-toolbar/viewer-zoom-button.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html
index a3ae841c93f..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-toolbar/viewer-zoom-button.html
@@ -19,14 +19,14 @@
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
- :host([closed]) #wrapper {
+ :host([closed_]) #wrapper {
/* 132px roughly flips the location of the button across the right edge
* of the page. */
transform: translateX(var(--translate-x-distance));
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
- :host([show-on-left][closed]) #wrapper {
+ :host([show-on-left][closed_]) #wrapper {
transform: translateX(calc(-1 * var(--translate-x-distance)));
}
@@ -76,7 +76,7 @@
}
</style>
<div id="wrapper">
- <cr-icon-button iron-icon="[[visibleIcon_]]" on-click="fireClick"
+ <cr-icon-button iron-icon="[[visibleIcon_]]" on-click="fireClick_"
aria-label$="[[visibleTooltip_]]" title="[[visibleTooltip_]]">
</cr-icon-button>
</div>
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-toolbar/viewer-zoom-button.js
index 361b292e81f..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-toolbar/viewer-zoom-button.js
@@ -6,6 +6,17 @@ Polymer({
is: 'viewer-zoom-button',
properties: {
+ /** Index of the icon currently being displayed. */
+ activeIndex: {
+ type: Number,
+ value: 0,
+ },
+
+ delay: {
+ type: Number,
+ observer: 'delayChanged_',
+ },
+
/**
* Icons to be displayed on the FAB. Multiple icons should be separated with
* spaces, and will be cycled through every time the FAB is clicked.
@@ -13,14 +24,6 @@ Polymer({
icons: String,
/**
- * Array version of the list of icons. Polymer does not allow array
- * properties to be set from HTML, so we must use a string property and
- * perform the conversion manually.
- * @private
- */
- icons_: {type: Array, value: [''], computed: 'computeIconsArray_(icons)'},
-
- /**
* Used to show the appropriate drop shadow when buttons are focused with
* the keyboard.
*/
@@ -29,59 +32,98 @@ Polymer({
reflectToAttribute: true,
},
- tooltips: Array,
-
- closed: {type: Boolean, reflectToAttribute: true, value: false},
+ newPrintPreview: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
- delay: {type: Number, observer: 'delayChanged_'},
+ showOnLeft: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
- newPrintPreview: {type: Boolean, reflectToAttribute: true},
+ /** @type {?Array<string>} */
+ tooltips: Array,
- showOnLeft: {type: Boolean, reflectToAttribute: true},
+ /** @private */
+ closed_: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ },
/**
- * Index of the icon currently being displayed.
+ * Array version of the list of icons. Polymer does not allow array
+ * properties to be set from HTML, so we must use a string property and
+ * perform the conversion manually.
+ * @private {!Array<string>}
*/
- activeIndex: {type: Number, value: 0},
+ icons_: {
+ type: Array,
+ value: [''],
+ computed: 'computeIconsArray_(icons)',
+ },
/**
* Icon currently being displayed on the FAB.
* @private
*/
- visibleIcon_:
- {type: String, computed: 'computeVisibleIcon_(icons_, activeIndex)'},
+ visibleIcon_: {
+ type: String,
+ computed: 'computeVisibleIcon_(icons_, activeIndex)',
+ },
+ /** @private */
visibleTooltip_: {
type: String,
- computed: 'computeVisibleTooltip_(tooltips, activeIndex)'
+ computed: 'computeVisibleTooltip_(tooltips, activeIndex)',
}
},
+ /**
+ * @param {string} icons Icon names in a string, delimited by spaces
+ * @return {!Array<string>} Array of icon name strings
+ * @private
+ */
computeIconsArray_: function(icons) {
return icons.split(' ');
},
+ /**
+ * @param {!Array<string>} icons Array of icon name strings.
+ * @param {number} activeIndex Index of the currently active icon.
+ * @return {string} Icon name for the currently visible icon.
+ * @private
+ */
computeVisibleIcon_: function(icons, activeIndex) {
return icons[activeIndex];
},
+ /**
+ * @param {?Array<string>} tooltips Array of tooltip strings.
+ * @param {number} activeIndex Index of the currently active icon.
+ * @return {string} Tooltip for the currently visible icon.
+ * @private
+ */
computeVisibleTooltip_: function(tooltips, activeIndex) {
return tooltips === undefined ? '' : tooltips[activeIndex];
},
+ /** @private */
delayChanged_: function() {
this.$.wrapper.style.transitionDelay = this.delay + 'ms';
},
show: function() {
- this.closed = false;
+ this.closed_ = false;
},
hide: function() {
- this.closed = true;
+ this.closed_ = true;
},
- fireClick: function() {
+ /** @private */
+ fireClick_: function() {
// We cannot attach an on-click to the entire viewer-zoom-button, as this
// will include clicks on the margins. Instead, proxy clicks on the FAB
// through.
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/viewer-zoom-toolbar.js
index fb817a5a01d..fe24ab64645 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/viewer-zoom-toolbar.js
@@ -52,6 +52,7 @@ Polymer({
return this.isPrintPreview_;
},
+ /** @return {boolean} */
isVisible: function() {
return this.visible_;
},
@@ -94,7 +95,10 @@ Polymer({
/**
* Change button tooltips to match any changes to localized strings.
- * @param {!Object} strings
+ * @param {!{tooltipFitToPage: string,
+ * tooltipFitToWidth: string,
+ * tooltipZoomIn: string,
+ * tooltipZoomOut: string}} strings
*/
setStrings: function(strings) {
this.$['fit-button'].tooltips =
@@ -103,9 +107,7 @@ Polymer({
this.$['zoom-out-button'].tooltips = [strings.tooltipZoomOut];
},
- /**
- * Handle clicks of the fit-button.
- */
+ /** Handle clicks of the fit-button. */
fitToggle: function() {
this.fireFitToChangedEvent_(
this.$['fit-button'].activeIndex == FIT_TO_WIDTH_BUTTON_STATE ?
@@ -114,9 +116,7 @@ Polymer({
true);
},
- /**
- * Handle the keyboard shortcut equivalent of fit-button clicks.
- */
+ /** Handle the keyboard shortcut equivalent of fit-button clicks. */
fitToggleFromHotKey: function() {
this.fitToggle();
@@ -130,7 +130,7 @@ Polymer({
/**
* Handle forcing zoom via scripting to a fitting type.
- * @param {FittingType} fittingType Page fitting type to force.
+ * @param {!FittingType} fittingType Page fitting type to force.
*/
forceFit: function(fittingType) {
this.fireFitToChangedEvent_(fittingType, false);
@@ -143,11 +143,11 @@ Polymer({
},
/**
- * @private
* Fire a 'fit-to-changed' {CustomEvent} with the given FittingType as detail.
- * @param {FittingType} fittingType to include as payload.
+ * @param {!FittingType} fittingType to include as payload.
* @param {boolean} userInitiated whether the event was initiated by a user
* action.
+ * @private
*/
fireFitToChangedEvent_: function(fittingType, userInitiated) {
this.fire(
diff --git a/chromium/chrome/browser/resources/pdf/index.html b/chromium/chrome/browser/resources/pdf/index.html
index c1c362756b3..06d219a6c7e 100644
--- a/chromium/chrome/browser/resources/pdf/index.html
+++ b/chromium/chrome/browser/resources/pdf/index.html
@@ -12,6 +12,8 @@
<link rel="import" href="elements/viewer-zoom-toolbar/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">
@@ -43,7 +45,6 @@
</body>
<script src="pdf_fitting_type.js"></script>
<script src="toolbar_manager.js"></script>
-<script src="viewport_interface.js"></script>
<script src="viewport.js"></script>
<script src="open_pdf_params_parser.js"></script>
<script src="navigator.js"></script>
diff --git a/chromium/chrome/browser/resources/pdf/navigator.js b/chromium/chrome/browser/resources/pdf/navigator.js
index 0282e725de2..d2e21dde43e 100644
--- a/chromium/chrome/browser/resources/pdf/navigator.js
+++ b/chromium/chrome/browser/resources/pdf/navigator.js
@@ -5,42 +5,24 @@
'use strict';
/**
- * Creates a new NavigatorDelegate for calling browser-specific functions to
- * do the actual navigating.
- *
- * @param {number} tabId The tab ID of the PDF viewer or -1 if the viewer is
- * not displayed in a tab.
- * @constructor
+ * NavigatorDelegate for calling browser-specific functions to do the actual
+ * navigating.
*/
-function NavigatorDelegate(tabId) {
- this.tabId_ = tabId;
-}
-
-/**
- * Creates a new Navigator for navigating to links inside or outside the PDF.
- *
- * @param {string} originalUrl The original page URL.
- * @param {Object} viewport The viewport info of the page.
- * @param {Object} paramsParser The object for URL parsing.
- * @param {Object} navigatorDelegate The object with callback functions that
- * get called when navigation happens in the current tab, a new tab,
- * and a new window.
- * @constructor
- */
-function Navigator(originalUrl, viewport, paramsParser, navigatorDelegate) {
- this.originalUrl_ = originalUrl;
- this.viewport_ = viewport;
- this.paramsParser_ = paramsParser;
- this.navigatorDelegate_ = navigatorDelegate;
-}
+class NavigatorDelegate {
+ /**
+ * @param {number} tabId The tab ID of the PDF viewer or -1 if the viewer is
+ * not displayed in a tab.
+ */
+ constructor(tabId) {
+ /** @private {number} */
+ this.tabId_ = tabId;
+ }
-NavigatorDelegate.prototype = {
/**
* Called when navigation should happen in the current tab.
- *
* @param {string} url The url to be opened in the current tab.
*/
- navigateInCurrentTab: function(url) {
+ navigateInCurrentTab(url) {
// When the PDFviewer is inside a browser tab, prefer the tabs API because
// it can navigate from one file:// URL to another.
if (chrome.tabs && this.tabId_ != -1) {
@@ -48,15 +30,14 @@ NavigatorDelegate.prototype = {
} else {
window.location.href = url;
}
- },
+ }
/**
* Called when navigation should happen in the new tab.
- *
* @param {string} url The url to be opened in the new tab.
* @param {boolean} active Indicates if the new tab should be the active tab.
*/
- navigateInNewTab: function(url, active) {
+ navigateInNewTab(url, active) {
// Prefer the tabs API because it guarantees we can just open a new tab.
// window.open doesn't have this guarantee.
if (chrome.tabs) {
@@ -64,14 +45,13 @@ NavigatorDelegate.prototype = {
} else {
window.open(url);
}
- },
+ }
/**
* Called when navigation should happen in the new window.
- *
* @param {string} url The url to be opened in the new window.
*/
- navigateInNewWindow: function(url) {
+ navigateInNewWindow(url) {
// Prefer the windows API because it guarantees we can just open a new
// window. window.open with '_blank' argument doesn't have this guarantee.
if (chrome.windows) {
@@ -80,52 +60,69 @@ NavigatorDelegate.prototype = {
window.open(url, '_blank');
}
}
-};
+}
-/**
- * Represents options when navigating to a new url. C++ counterpart of
- * the enum is in ui/base/window_open_disposition.h. This enum represents
- * the only values that are passed from Plugin.
- * @enum {number}
- */
-Navigator.WindowOpenDisposition = {
- CURRENT_TAB: 1,
- NEW_FOREGROUND_TAB: 3,
- NEW_BACKGROUND_TAB: 4,
- NEW_WINDOW: 6,
- SAVE_TO_DISK: 7
-};
+/** Navigator for navigating to links inside or outside the PDF. */
+class PdfNavigator {
+ /**
+ * @param {string} originalUrl The original page URL.
+ * @param {!Viewport} viewport The viewport info of the page.
+ * @param {!OpenPdfParamsParser} paramsParser The object for URL parsing.
+ * @param {!NavigatorDelegate} navigatorDelegate The object with callback
+ * functions that get called when navigation happens in the current tab,
+ * a new tab, and a new window.
+ */
+ constructor(originalUrl, viewport, paramsParser, navigatorDelegate) {
+ /** @private {?URL} */
+ this.originalUrl_ = null;
+ try {
+ this.originalUrl_ = new URL(originalUrl);
+ } catch (err) {
+ console.warn('Invalid original URL');
+ }
+
+ /** @private {!Viewport} */
+ this.viewport_ = viewport;
+
+ /** @private {!OpenPdfParamsParser} */
+ this.paramsParser_ = paramsParser;
+
+ /** @private {!NavigatorDelegate} */
+ this.navigatorDelegate_ = navigatorDelegate;
+ }
-Navigator.prototype = {
/**
* Function to navigate to the given URL. This might involve navigating
* within the PDF page or opening a new url (in the same tab or a new tab).
- *
- * @param {string} url The URL to navigate to.
- * @param {number} disposition The window open disposition when
- * navigating to the new URL.
+ * @param {string} urlString The URL to navigate to.
+ * @param {!PdfNavigator.WindowOpenDisposition} disposition The window open
+ * disposition when navigating to the new URL.
*/
- navigate: function(url, disposition) {
- if (url.length == 0) {
+ navigate(urlString, disposition) {
+ if (urlString.length == 0) {
return;
}
// If |urlFragment| starts with '#', then it's for the same URL with a
// different URL fragment.
- if (url.charAt(0) == '#') {
+ if (urlString[0] === '#' && this.originalUrl_) {
// if '#' is already present in |originalUrl| then remove old fragment
// and add new url fragment.
- const hashIndex = this.originalUrl_.search('#');
- if (hashIndex != -1) {
- url = this.originalUrl_.substring(0, hashIndex) + url;
- } else {
- url = this.originalUrl_ + url;
- }
+ const newUrl = new URL(this.originalUrl_.href);
+ newUrl.hash = urlString;
+ urlString = newUrl.href;
}
// If there's no scheme, then take a guess at the scheme.
- if (url.indexOf('://') == -1 && url.indexOf('mailto:') == -1) {
- url = this.guessUrlWithoutScheme_(url);
+ if (!urlString.includes('://') && !urlString.includes('mailto:')) {
+ urlString = this.guessUrlWithoutScheme_(urlString);
+ }
+
+ let url = null;
+ try {
+ url = new URL(urlString);
+ } catch (err) {
+ return;
}
if (!this.isValidUrl_(url)) {
@@ -133,147 +130,134 @@ Navigator.prototype = {
}
switch (disposition) {
- case Navigator.WindowOpenDisposition.CURRENT_TAB:
+ case PdfNavigator.WindowOpenDisposition.CURRENT_TAB:
this.paramsParser_.getViewportFromUrlParams(
- url, this.onViewportReceived_.bind(this));
+ url.href, this.onViewportReceived_.bind(this));
break;
- case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
- this.navigatorDelegate_.navigateInNewTab(url, false);
+ case PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
+ this.navigatorDelegate_.navigateInNewTab(url.href, false);
break;
- case Navigator.WindowOpenDisposition.NEW_FOREGROUND_TAB:
- this.navigatorDelegate_.navigateInNewTab(url, true);
+ case PdfNavigator.WindowOpenDisposition.NEW_FOREGROUND_TAB:
+ this.navigatorDelegate_.navigateInNewTab(url.href, true);
break;
- case Navigator.WindowOpenDisposition.NEW_WINDOW:
- this.navigatorDelegate_.navigateInNewWindow(url);
+ case PdfNavigator.WindowOpenDisposition.NEW_WINDOW:
+ this.navigatorDelegate_.navigateInNewWindow(url.href);
break;
- case Navigator.WindowOpenDisposition.SAVE_TO_DISK:
+ case PdfNavigator.WindowOpenDisposition.SAVE_TO_DISK:
// TODO(jaepark): Alt + left clicking a link in PDF should
// download the link.
this.paramsParser_.getViewportFromUrlParams(
- url, this.onViewportReceived_.bind(this));
+ url.href, this.onViewportReceived_.bind(this));
break;
default:
break;
}
- },
+ }
/**
* Called when the viewport position is received.
- *
* @param {Object} viewportPosition Dictionary containing the viewport
* position.
* @private
*/
- onViewportReceived_: function(viewportPosition) {
- let originalUrl = this.originalUrl_;
- let hashIndex = originalUrl.search('#');
- if (hashIndex != -1) {
- originalUrl = originalUrl.substring(0, hashIndex);
- }
-
- let newUrl = viewportPosition.url;
- hashIndex = newUrl.search('#');
- if (hashIndex != -1) {
- newUrl = newUrl.substring(0, hashIndex);
+ onViewportReceived_(viewportPosition) {
+ let newUrl = null;
+ try {
+ newUrl = new URL(viewportPosition.url);
+ } catch (err) {
}
const pageNumber = viewportPosition.page;
- if (pageNumber != undefined && originalUrl == newUrl) {
+ if (pageNumber != undefined && this.originalUrl_ && newUrl &&
+ this.originalUrl_.origin === newUrl.origin &&
+ this.originalUrl_.pathname === newUrl.pathname) {
this.viewport_.goToPage(pageNumber);
} else {
this.navigatorDelegate_.navigateInCurrentTab(viewportPosition.url);
}
- },
+ }
/**
* Checks if the URL starts with a scheme and is not just a scheme.
- *
- * @param {string} url The input URL
+ * @param {!URL} url The input URL
* @return {boolean} Whether the url is valid.
* @private
*/
- isValidUrl_: function(url) {
+ isValidUrl_(url) {
// Make sure |url| starts with a valid scheme.
- if (!url.startsWith('http://') && !url.startsWith('https://') &&
- !url.startsWith('ftp://') && !url.startsWith('file://') &&
- !url.startsWith('mailto:')) {
+ const validSchemes = ['http:', 'https:', 'ftp:', 'file:', 'mailto:'];
+ if (!validSchemes.includes(url.protocol)) {
return false;
}
// Navigations to file:-URLs are only allowed from file:-URLs.
- if (url.startsWith('file:') && !this.originalUrl_.startsWith('file:')) {
- return false;
- }
-
-
- // Make sure |url| is not only a scheme.
- if (url == 'http://' || url == 'https://' || url == 'ftp://' ||
- url == 'file://' || url == 'mailto:') {
+ if (url.protocol === 'file:' && this.originalUrl_ &&
+ this.originalUrl_.protocol !== 'file:') {
return false;
}
return true;
- },
+ }
/**
* Attempt to figure out what a URL is when there is no scheme.
- *
* @param {string} url The input URL
* @return {string} The URL with a scheme or the original URL if it is not
* possible to determine the scheme.
* @private
*/
- guessUrlWithoutScheme_: function(url) {
+ guessUrlWithoutScheme_(url) {
// If the original URL is mailto:, that does not make sense to start with,
// and neither does adding |url| to it.
// If the original URL is not a valid URL, this cannot make a valid URL.
// In both cases, just bail out.
- if (this.originalUrl_.startsWith('mailto:') ||
+ if (!this.originalUrl_ || this.originalUrl_.protocol === 'mailto:' ||
!this.isValidUrl_(this.originalUrl_)) {
return url;
}
// Check for absolute paths.
if (url.startsWith('/')) {
- const schemeEndIndex = this.originalUrl_.indexOf('://');
- const firstSlash = this.originalUrl_.indexOf('/', schemeEndIndex + 3);
- // e.g. http://www.foo.com/bar -> http://www.foo.com
- const domain = firstSlash != -1 ?
- this.originalUrl_.substr(0, firstSlash) :
- this.originalUrl_;
- return domain + url;
- }
-
- // Check for obvious relative paths.
- let isRelative = false;
- if (url.startsWith('.') || url.startsWith('\\')) {
- isRelative = true;
+ return this.originalUrl_.origin + url;
}
+ // Check for other non-relative paths.
// In Adobe Acrobat Reader XI, it looks as though links with less than
// 2 dot separators in the domain are considered relative links, and
- // those with 2 of more are considered http URLs. e.g.
+ // those with 2 or more are considered http URLs. e.g.
//
// www.foo.com/bar -> http
// foo.com/bar -> relative link
- if (!isRelative) {
+ if (url.startsWith('\\')) {
+ // Prepend so that the relative URL will be correctly computed by new
+ // URL() below.
+ url = './' + url;
+ }
+ if (!url.startsWith('.')) {
const domainSeparatorIndex = url.indexOf('/');
const domainName = domainSeparatorIndex == -1 ?
url :
url.substr(0, domainSeparatorIndex);
const domainDotCount = (domainName.match(/\./g) || []).length;
- if (domainDotCount < 2) {
- isRelative = true;
+ if (domainDotCount >= 2) {
+ return 'http://' + url;
}
}
- if (isRelative) {
- const slashIndex = this.originalUrl_.lastIndexOf('/');
- const path = slashIndex != -1 ? this.originalUrl_.substr(0, slashIndex) :
- this.originalUrl_;
- return path + '/' + url;
- }
-
- return 'http://' + url;
+ return new URL(url, this.originalUrl_.href).href;
}
+}
+
+/**
+ * Represents options when navigating to a new url. C++ counterpart of
+ * the enum is in ui/base/window_open_disposition.h. This enum represents
+ * the only values that are passed from Plugin.
+ * @enum {number}
+ */
+PdfNavigator.WindowOpenDisposition = {
+ CURRENT_TAB: 1,
+ NEW_FOREGROUND_TAB: 3,
+ NEW_BACKGROUND_TAB: 4,
+ NEW_WINDOW: 6,
+ SAVE_TO_DISK: 7
};
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 aacb7c437ec..d4a502a135f 100644
--- a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
+++ b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-(function() {
-
'use strict';
/**
* Parses the open pdf parameters passed in the url to set initial viewport
* settings for opening the pdf.
*/
-window.OpenPDFParamsParser = class {
+class OpenPdfParamsParser {
/**
* @param {function(Object)} postMessageCallback
* Function called to fetch information for a named destination.
@@ -206,6 +204,4 @@ window.OpenPDFParamsParser = class {
}
outstandingRequest.callback(outstandingRequest.params);
}
-};
-
-}());
+}
diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer.js b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
index 02763ae00c9..375663f029c 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
@@ -151,7 +151,7 @@ function PDFViewer(browserApi) {
PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED);
// Parse open pdf parameters.
- this.paramsParser_ = new OpenPDFParamsParser(
+ this.paramsParser_ = new OpenPdfParamsParser(
message => this.pluginController_.postMessage(message));
const toolbarEnabled =
this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar &&
@@ -161,12 +161,13 @@ function PDFViewer(browserApi) {
// 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', this.onPasswordSubmitted_.bind(this));
+ '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) {
@@ -183,15 +184,16 @@ function PDFViewer(browserApi) {
this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ?
this.browserApi_.getDefaultZoom() :
1.0;
- this.viewport_ = new ViewportImpl(
- window, this.sizer_, this.viewportChanged_.bind(this),
- () => this.currentController_.beforeZoom(),
- () => {
- this.currentController_.afterZoom();
- this.zoomManager_.onPdfZoomChange();
- },
- this.setUserInitiated_.bind(this), getScrollbarWidth(), defaultZoom,
- topToolbarHeight);
+ 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
@@ -208,7 +210,7 @@ function PDFViewer(browserApi) {
// with it. We also send a message indicating that extension has loaded and
// is ready to receive messages.
window.addEventListener(
- 'message', this.handleScriptingMessage.bind(this), false);
+ 'message', message => this.handleScriptingMessage(message), false);
this.plugin_.setAttribute('src', this.originalUrl_);
this.plugin_.setAttribute(
@@ -242,20 +244,18 @@ function PDFViewer(browserApi) {
this.zoomToolbar_ = $('zoom-toolbar');
this.zoomToolbar_.setIsPrintPreview(this.isPrintPreview_);
this.zoomToolbar_.addEventListener(
- 'fit-to-changed', this.fitToChanged_.bind(this));
- this.zoomToolbar_.addEventListener(
- 'zoom-in', this.viewport_.zoomIn.bind(this.viewport_));
+ 'fit-to-changed', e => this.fitToChanged_(e));
+ this.zoomToolbar_.addEventListener('zoom-in', () => this.viewport_.zoomIn());
this.zoomToolbar_.addEventListener(
- 'zoom-out', this.viewport_.zoomOut.bind(this.viewport_));
+ 'zoom-out', () => this.viewport_.zoomOut());
this.gestureDetector_ = new GestureDetector($('content'));
this.gestureDetector_.addEventListener(
- 'pinchstart', this.onPinchStart_.bind(this));
+ 'pinchstart', e => this.onPinchStart_(e));
this.sentPinchEvent_ = false;
this.gestureDetector_.addEventListener(
- 'pinchupdate', this.onPinchUpdate_.bind(this));
- this.gestureDetector_.addEventListener(
- 'pinchend', this.onPinchEnd_.bind(this));
+ 'pinchupdate', e => this.onPinchUpdate_(e));
+ this.gestureDetector_.addEventListener('pinchend', e => this.onPinchEnd_(e));
if (toolbarEnabled) {
this.toolbar_ = $('toolbar');
@@ -293,8 +293,8 @@ function PDFViewer(browserApi) {
document.body.addEventListener('navigate', e => {
const disposition = e.detail.newtab ?
- Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
- Navigator.WindowOpenDisposition.CURRENT_TAB;
+ PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
+ PdfNavigator.WindowOpenDisposition.CURRENT_TAB;
this.navigator_.navigate(e.detail.uri, disposition);
});
@@ -309,33 +309,34 @@ function PDFViewer(browserApi) {
// Set up the ZoomManager.
this.zoomManager_ = ZoomManager.create(
- this.browserApi_.getZoomBehavior(), this.viewport_,
- this.browserApi_.setZoom.bind(this.browserApi_),
+ this.browserApi_.getZoomBehavior(), () => this.viewport_.getZoom(),
+ zoom => this.browserApi_.setZoom(zoom),
this.browserApi_.getInitialZoom());
- this.viewport_.zoomManager = this.zoomManager_;
+ this.viewport_.setZoomManager(this.zoomManager_);
this.browserApi_.addZoomEventListener(
- this.zoomManager_.onBrowserZoomChange.bind(this.zoomManager_));
+ zoom => this.zoomManager_.onBrowserZoomChange(zoom));
// Setup the keyboard event listener.
- document.addEventListener('keydown', this.handleKeyEvent_.bind(this));
- document.addEventListener('mousemove', this.handleMouseEvent_.bind(this));
- document.addEventListener('mouseout', this.handleMouseEvent_.bind(this));
+ document.addEventListener('keydown', e => this.handleKeyEvent_(e));
+ document.addEventListener('mousemove', e => this.handleMouseEvent_(e));
+ document.addEventListener('mouseout', e => this.handleMouseEvent_(e));
document.addEventListener(
- 'contextmenu', this.handleContextMenuEvent_.bind(this));
+ 'contextmenu', e => this.handleContextMenuEvent_(e));
const tabId = this.browserApi_.getStreamInfo().tabId;
- this.navigator_ = new Navigator(
+ 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', this.handleStrings_.bind(this));
+ 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(this.onSave.bind(this));
+ chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave(url));
}
}
@@ -361,7 +362,7 @@ PDFViewer.prototype = {
const pageUpHandler = () => {
// Go to the previous page if we are fit-to-page or fit-to-height.
if (this.viewport_.isPagedMode()) {
- this.viewport_.goToPage(this.viewport_.getMostVisiblePage() - 1);
+ this.viewport_.goToPreviousPage();
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
@@ -372,7 +373,7 @@ PDFViewer.prototype = {
const pageDownHandler = () => {
// Go to the next page if we are fit-to-page or fit-to-height.
if (this.viewport_.isPagedMode()) {
- this.viewport_.goToPage(this.viewport_.getMostVisiblePage() + 1);
+ this.viewport_.goToNextPage();
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
@@ -410,7 +411,7 @@ PDFViewer.prototype = {
// no form field is focused.
if (!(this.viewport_.documentHasScrollbars().horizontal ||
this.isFormFieldFocused_)) {
- this.viewport_.goToPage(this.viewport_.getMostVisiblePage() - 1);
+ this.viewport_.goToPreviousPage();
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
@@ -431,7 +432,7 @@ PDFViewer.prototype = {
// form field is focused.
if (!(this.viewport_.documentHasScrollbars().horizontal ||
this.isFormFieldFocused_)) {
- this.viewport_.goToPage(this.viewport_.getMostVisiblePage() + 1);
+ this.viewport_.goToNextPage();
// Since we do the movement of the page.
e.preventDefault();
} else if (fromScriptingAPI) {
@@ -558,7 +559,7 @@ PDFViewer.prototype = {
const result = await this.inkController_.save(true);
await this.pluginController_.load(result.fileName, result.dataToSave);
// Ensure the plugin gets the initial viewport.
- this.viewport_.setZoom(this.viewport_.zoom);
+ this.pluginController_.afterZoom();
}
},
@@ -641,7 +642,8 @@ PDFViewer.prototype = {
this.isUserInitiatedEvent_ = false;
this.zoomToolbar_.forceFit(params.view);
if (params.viewPosition) {
- const zoomedPositionShift = params.viewPosition * this.viewport_.zoom;
+ const zoomedPositionShift =
+ params.viewPosition * this.viewport_.getZoom();
const currentViewportPosition = this.viewport_.position;
if (params.view == FittingType.FIT_TO_WIDTH) {
currentViewportPosition.y += zoomedPositionShift;
@@ -730,7 +732,7 @@ PDFViewer.prototype = {
this.viewport_.position = this.lastViewportPosition_;
}
this.paramsParser_.getViewportFromUrlParams(
- this.originalUrl_, this.handleURLParams_.bind(this));
+ this.originalUrl_, params => this.handleURLParams_(params));
this.setLoadState_(LoadState.SUCCESS);
this.sendDocumentLoadedMessage_();
while (this.delayedScriptingMessages_.length > 0) {
@@ -1141,7 +1143,8 @@ PDFViewer.prototype = {
handleNavigate: function(url, disposition) {
// If in print preview, always open a new tab.
if (this.isPrintPreview_) {
- this.navigator_.navigate(url, Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
+ this.navigator_.navigate(
+ url, PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
} else {
this.navigator_.navigate(url, disposition);
}
@@ -1306,7 +1309,7 @@ PDFViewer.prototype = {
setAnnotationUndoState(state) {
this.toolbar_.canUndoAnnotation = state.canUndo;
this.toolbar_.canRedoAnnotation = state.canRedo;
- }
+ },
};
/** @abstract */
@@ -1483,7 +1486,7 @@ class PluginController extends ContentController {
if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) {
const position = this.viewport_.position;
- const zoom = this.viewport_.zoom;
+ const zoom = this.viewport_.getZoom();
const pinchPhase = this.viewport_.pinchPhase;
this.postMessage({
type: 'viewport',
@@ -1503,7 +1506,7 @@ class PluginController extends ContentController {
*/
afterZoom() {
const position = this.viewport_.position;
- const zoom = this.viewport_.zoom;
+ 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;
diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js
index 02664b3fe33..480664c014c 100644
--- a/chromium/chrome/browser/resources/pdf/viewport.js
+++ b/chromium/chrome/browser/resources/pdf/viewport.js
@@ -2,10 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * @typedef {{
+ * width: number,
+ * height: number,
+ * pageDimensions: Array<ViewportRect>,
+ * }}
+ */
+let DocumentDimensions;
+
+/** @typedef {{x: number, y: number}} */
+let Point;
+
+/** @typedef {{width: number, height: number}} */
+let Size;
+
+/** @typedef {{x: number, y: number, width: number, height: number}} */
+let ViewportRect;
/**
* Clamps the zoom factor (or page scale factor) to be within the limits.
- *
* @param {number} factor The zoom/scale factor.
* @return {number} The factor clamped within the limits.
*/
@@ -16,30 +32,36 @@ function clampZoom(factor) {
}
/**
- * Returns the height of the intersection of two rectangles.
- *
- * @param {!ViewportRect} rect1 the first rect
- * @param {!ViewportRect} rect2 the second rect
- * @return {number} the height of the intersection of the rects
+ * @param {!ViewportRect} rect1
+ * @param {!ViewportRect} rect2
+ * @return {number} The area of the intersection of the rects
*/
-function getIntersectionHeight(rect1, rect2) {
- return Math.max(
- 0,
- Math.min(rect1.y + rect1.height, rect2.y + rect2.height) -
- Math.max(rect1.y, rect2.y));
+function getIntersectionArea(rect1, rect2) {
+ const left = Math.max(rect1.x, rect2.x);
+ const top = Math.max(rect1.y, rect2.y);
+ const right = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
+ const bottom = Math.min(rect1.y + rect1.height, rect2.y + rect2.height);
+
+ if (left >= right || top >= bottom) {
+ return 0;
+ }
+
+ return (right - left) * (bottom - top);
}
/**
- * Computes vector between two points.
- *
- * @param {!Point} p1 The first point.
- * @param {!Point} p2 The second point.
- * @return {!Point} The vector.
+ * @param {!Point} p1
+ * @param {!Point} p2
+ * @return {!Point} The vector between the two points.
*/
function vectorDelta(p1, p2) {
return {x: p2.x - p1.x, y: p2.y - p1.y};
}
+/**
+ * @param {!Point} coordinateInFrame
+ * @return {!Point} Coordinate converted to plugin coordinates.
+ */
function frameToPluginCoordinate(coordinateInFrame) {
const container = $('plugin');
return {
@@ -48,83 +70,149 @@ function frameToPluginCoordinate(coordinateInFrame) {
};
}
-/** @implements {Viewport} */
-class ViewportImpl {
+class Viewport {
/**
- * Create a new viewport.
- *
- * @param {Window} window the window
- * @param {Object} sizer is the element which represents the size of the
+ * @param {!Window} window
+ * @param {!HTMLDivElement} sizer The element which represents the size of the
* document in the viewport
- * @param {Function} viewportChangedCallback is run when the viewport changes
- * @param {Function} beforeZoomCallback is run before a change in zoom
- * @param {Function} afterZoomCallback is run after a change in zoom
- * @param {Function} setUserInitiatedCallback is run to indicate whether a
- * zoom event is user initiated.
- * @param {number} scrollbarWidth the width of scrollbars on the page
+ * @param {number} scrollbarWidth The width of scrollbars on the page
* @param {number} defaultZoom The default zoom level.
* @param {number} topToolbarHeight The number of pixels that should initially
* be left blank above the document for the toolbar.
*/
- constructor(
- window, sizer, viewportChangedCallback, beforeZoomCallback,
- afterZoomCallback, setUserInitiatedCallback, scrollbarWidth, defaultZoom,
- topToolbarHeight) {
+ constructor(window, sizer, scrollbarWidth, defaultZoom, topToolbarHeight) {
+ /** @private {!Window} */
this.window_ = window;
+
+ /** @private {!HTMLDivElement} */
this.sizer_ = sizer;
- this.viewportChangedCallback_ = viewportChangedCallback;
- this.beforeZoomCallback_ = beforeZoomCallback;
- this.afterZoomCallback_ = afterZoomCallback;
- this.setUserInitiatedCallback_ = setUserInitiatedCallback;
+
+ /** @private {number} */
+ this.scrollbarWidth_ = scrollbarWidth;
+
+ /** @private {number} */
+ this.defaultZoom_ = defaultZoom;
+
+ /** @private {number} */
+ this.topToolbarHeight_ = topToolbarHeight;
+
+ /** @private {function():void} */
+ this.viewportChangedCallback_ = function() {};
+
+ /** @private {function():void} */
+ this.beforeZoomCallback_ = function() {};
+
+ /** @private {function():void} */
+ this.afterZoomCallback_ = function() {};
+
+ /** @private {function(boolean):void} */
+ this.userInitiatedCallback_ = function() {};
+
+ /** @private {boolean} */
this.allowedToChangeZoom_ = false;
+
+ /** @private {number} */
this.internalZoom_ = 1;
- this.zoomManager_ = new InactiveZoomManager(this, 1);
+
+ /** @private {?ZoomManager} */
+ this.zoomManager_ = null;
+
/** @private {?DocumentDimensions} */
this.documentDimensions_ = null;
+
/** @private {Array<ViewportRect>} */
this.pageDimensions_ = [];
- this.scrollbarWidth_ = scrollbarWidth;
+
+ /** @private {!FittingType} */
this.fittingType_ = FittingType.NONE;
- this.defaultZoom_ = defaultZoom;
- this.topToolbarHeight_ = topToolbarHeight;
+
+ /**
+ * |twoUpView_| should be in sync with |two_up_view_| in PDFiumEngine.
+ * @private {boolean}
+ */
+ this.twoUpView_ = false;
+
+ /** @private {number} */
this.prevScale_ = 1;
+
+ /** @private {!Viewport.PinchPhase} */
this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE;
+
+ /** @private {?Point} */
this.pinchPanVector_ = null;
+
+ /** @private {?Point} */
this.pinchCenter_ = null;
+
/** @private {?Point} */
this.firstPinchCenterInFrame_ = null;
+
+ /** @private {number} */
this.rotations_ = 0;
- // TODO(dstockwell): why isn't this private?
- this.oldCenterInContent = null;
- this.keepContentCentered_ = null;
+
+ /** @private {?Point} */
+ this.oldCenterInContent_ = null;
+
+ /** @private {boolean} */
+ this.keepContentCentered_ = false;
+
+ /** @private {!EventTracker} */
+ this.tracker_ = new EventTracker();
+
+ // Set to a default zoom manager - used in tests.
+ this.setZoomManager(new InactiveZoomManager(this.getZoom.bind(this), 1));
window.addEventListener('scroll', this.updateViewport_.bind(this));
window.addEventListener('resize', this.resizeWrapper_.bind(this));
}
+ /** @param {function():void} viewportChangedCallback */
+ setViewportChangedCallback(viewportChangedCallback) {
+ this.viewportChangedCallback_ = viewportChangedCallback;
+ }
+
+ /** @param {function():void} beforeZoomCallback */
+ setBeforeZoomCallback(beforeZoomCallback) {
+ this.beforeZoomCallback_ = beforeZoomCallback;
+ }
+
+ /** @param {function():void} afterZoomCallback */
+ setAfterZoomCallback(afterZoomCallback) {
+ this.afterZoomCallback_ = afterZoomCallback;
+ }
+
+ /** @param {function(boolean):void} userInitiatedCallback */
+ setUserInitiatedCallback(userInitiatedCallback) {
+ this.userInitiatedCallback_ = userInitiatedCallback;
+ }
+
/**
- * @param {number} n the number of clockwise 90-degree rotations to
- * increment by.
+ * @param {number} n The number of clockwise 90-degree rotations to increment
+ * by.
*/
rotateClockwise(n) {
this.rotations_ = (this.rotations_ + n) % 4;
}
/**
- * @return {number} the number of clockwise 90-degree rotations that have been
+ * @return {number} The number of clockwise 90-degree rotations that have been
* applied.
*/
getClockwiseRotations() {
return this.rotations_;
}
+ /** @param {boolean} twoUpView The new two up view state to set. */
+ setTwoUpView(twoUpView) {
+ this.twoUpView_ = twoUpView;
+ }
+
/**
* Converts a page position (e.g. the location of a bookmark) to a screen
* position.
- *
* @param {number} page
- * @param {Point} point The position on `page`.
- * @return The screen position.
+ * @param {!Point} point The position on `page`.
+ * @return {!Point} The screen position.
*/
convertPageToScreen(page, point) {
const dimensions = this.getPageInsetDimensions(page);
@@ -168,9 +256,8 @@ class ViewportImpl {
* Rounding is necessary when interacting with the renderer which tends to
* operate in integral values (for example for determining if scrollbars
* should be shown).
- *
* @param {number} zoom The zoom to use to compute the scaled dimensions.
- * @return {Object} A dictionary with scaled 'width'/'height' of the document.
+ * @return {?Size} Scaled 'width' and 'height' of the document.
* @private
*/
getZoomedDocumentDimensions_(zoom) {
@@ -183,7 +270,7 @@ class ViewportImpl {
};
}
- /** @override */
+ /** @return {!Size} A dictionary with the 'width'/'height' of the document. */
getDocumentDimensions() {
return {
width: this.documentDimensions_.width,
@@ -192,8 +279,22 @@ class ViewportImpl {
}
/**
- * @param {number} zoom compute whether scrollbars are needed at this zoom
- * @return {{horizontal: boolean, vertical: boolean}} whether horizontal or
+ * @return {!ViewportRect} ViewportRect for the viewport given current zoom.
+ * @private
+ */
+ getViewportRect_() {
+ const zoom = this.getZoom();
+ return {
+ x: this.position.x / zoom,
+ y: this.position.y / zoom,
+ width: this.size.width / zoom,
+ height: this.size.height / zoom
+ };
+ }
+
+ /**
+ * @param {number} zoom Zoom to compute scrollbars for
+ * @return {{horizontal: boolean, vertical: boolean}} Whether horizontal or
* vertical scrollbars are needed.
* @private
*/
@@ -219,23 +320,20 @@ class ViewportImpl {
}
/**
- * Returns true if the document needs scrollbars at the current zoom level.
- *
- * @return {Object} with 'x' and 'y' keys which map to bool values
- * indicating if the horizontal and vertical scrollbars are needed
- * respectively.
+ * @return {!{horizontal: boolean, vertical: boolean}} Whether horizontal and
+ * vertical scrollbars are needed.
*/
documentHasScrollbars() {
- return this.documentNeedsScrollbars_(this.zoom);
+ return this.documentNeedsScrollbars_(this.getZoom());
}
/**
- * Helper function called when the zoomed document size changes.
- *
+ * Helper function called when the zoomed document size changes. Updates the
+ * sizer's width and height.
* @private
*/
contentSizeChanged_() {
- const zoomedDimensions = this.getZoomedDocumentDimensions_(this.zoom);
+ const zoomedDimensions = this.getZoomedDocumentDimensions_(this.getZoom());
if (zoomedDimensions) {
this.sizer_.style.width = zoomedDimensions.width + 'px';
this.sizer_.style.height =
@@ -245,7 +343,6 @@ class ViewportImpl {
/**
* Called when the viewport should be updated.
- *
* @private
*/
updateViewport_() {
@@ -254,18 +351,16 @@ class ViewportImpl {
/**
* Called when the browser window size changes.
- *
* @private
*/
resizeWrapper_() {
- this.setUserInitiatedCallback_(false);
+ this.userInitiatedCallback_(false);
this.resize_();
- this.setUserInitiatedCallback_(true);
+ this.userInitiatedCallback_(true);
}
/**
* Called when the viewport size changes.
- *
* @private
*/
resize_() {
@@ -282,7 +377,7 @@ class ViewportImpl {
}
}
- /** @override */
+ /** @return {!Point} The scroll position of the viewport. */
get position() {
return {
x: this.window_.pageXOffset,
@@ -292,16 +387,15 @@ class ViewportImpl {
/**
* Scroll the viewport to the specified position.
- *
- * @param {Point} position The position to scroll to.
+ * @param {!Point} position The position to scroll to.
*/
set position(position) {
this.window_.scrollTo(position.x, position.y + this.topToolbarHeight_);
}
- /** @override */
+ /** @return {!Size} the size of the viewport excluding scrollbars. */
get size() {
- const needsScrollbars = this.documentNeedsScrollbars_(this.zoom);
+ const needsScrollbars = this.documentNeedsScrollbars_(this.getZoom());
const scrollbarWidth = needsScrollbars.vertical ? this.scrollbarWidth_ : 0;
const scrollbarHeight =
needsScrollbars.horizontal ? this.scrollbarWidth_ : 0;
@@ -311,22 +405,25 @@ class ViewportImpl {
};
}
- /** @override */
- get zoom() {
+ /** @return {number} The current zoom. */
+ getZoom() {
return this.zoomManager_.applyBrowserZoom(this.internalZoom_);
}
- /**
- * Set the zoom manager.
- *
- * @type {ZoomManager} manager the zoom manager to set.
- */
- set zoomManager(manager) {
+ /** @param {!ZoomManager} manager */
+ setZoomManager(manager) {
+ this.resetTracker();
this.zoomManager_ = manager;
+ this.tracker_.add(
+ this.zoomManager_.getEventTarget(), 'set-zoom',
+ e => this.setZoom(e.detail));
+ this.tracker_.add(
+ this.zoomManager_.getEventTarget(), 'update-zoom-from-browser',
+ this.updateZoomFromBrowserChange_.bind(this));
}
/**
- * @return {Viewport.PinchPhase} The phase of the current pinch gesture for
+ * @return {!Viewport.PinchPhase} The phase of the current pinch gesture for
* the viewport.
*/
get pinchPhase() {
@@ -334,7 +431,7 @@ class ViewportImpl {
}
/**
- * @return {Object} The panning caused by the current pinch gesture (as
+ * @return {?Point} The panning caused by the current pinch gesture (as
* the deltas of the x and y coordinates).
*/
get pinchPanVector() {
@@ -342,7 +439,7 @@ class ViewportImpl {
}
/**
- * @return {Object} The coordinates of the center of the current pinch
+ * @return {?Point} The coordinates of the center of the current pinch
* gesture.
*/
get pinchCenter() {
@@ -354,8 +451,7 @@ class ViewportImpl {
* required so that we can notify the plugin that zooming is in progress
* so that while zooming is taking place it can stop reacting to scroll events
* from the viewport. This is to avoid flickering.
- *
- * @param {Function} f Function to wrap
+ * @param {function():void} f Function to wrap
* @private
*/
mightZoom_(f) {
@@ -364,12 +460,11 @@ class ViewportImpl {
f();
this.allowedToChangeZoom_ = false;
this.afterZoomCallback_();
+ this.zoomManager_.onPdfZoomChange();
}
/**
- * Sets the zoom of the viewport.
- *
- * @param {number} newZoom the zoom level to zoom to.
+ * @param {number} newZoom The zoom level to set.
* @private
*/
setZoomInternal_(newZoom) {
@@ -378,26 +473,27 @@ class ViewportImpl {
'Called Viewport.setZoomInternal_ without calling ' +
'Viewport.mightZoom_.');
// Record the scroll position (relative to the top-left of the window).
+ let zoom = this.getZoom();
const currentScrollPos = {
- x: this.position.x / this.zoom,
- y: this.position.y / this.zoom
+ x: this.position.x / zoom,
+ y: this.position.y / zoom
};
this.internalZoom_ = newZoom;
this.contentSizeChanged_();
// Scroll to the scaled scroll position.
+ zoom = this.getZoom();
this.position = {
- x: currentScrollPos.x * this.zoom,
- y: currentScrollPos.y * this.zoom
+ x: currentScrollPos.x * zoom,
+ y: currentScrollPos.y * zoom
};
}
/**
* Sets the zoom of the viewport.
* Same as setZoomInternal_ but for pinch zoom we have some more operations.
- *
* @param {number} scaleDelta The zoom delta.
- * @param {!Object} center The pinch center in content coordinates.
+ * @param {!Point} center The pinch center in content coordinates.
* @private
*/
setPinchZoomInternal_(scaleDelta, center) {
@@ -407,16 +503,17 @@ class ViewportImpl {
'Viewport.mightZoom_.');
this.internalZoom_ = clampZoom(this.internalZoom_ * scaleDelta);
- const newCenterInContent = this.frameToContent(center);
+ const newCenterInContent = this.frameToContent_(center);
const delta = {
- x: (newCenterInContent.x - this.oldCenterInContent.x),
- y: (newCenterInContent.y - this.oldCenterInContent.y)
+ x: (newCenterInContent.x - this.oldCenterInContent_.x),
+ y: (newCenterInContent.y - this.oldCenterInContent_.y)
};
// Record the scroll position (relative to the pinch center).
+ const zoom = this.getZoom();
const currentScrollPos = {
- x: this.position.x - delta.x * this.zoom,
- y: this.position.y - delta.y * this.zoom
+ x: this.position.x - delta.x * zoom,
+ y: this.position.y - delta.y * zoom
};
this.contentSizeChanged_();
@@ -426,24 +523,22 @@ class ViewportImpl {
/**
* Converts a point from frame to content coordinates.
- *
- * @param {!Object} framePoint The frame coordinates.
- * @return {!Object} The content coordinates.
+ * @param {!Point} framePoint The frame coordinates.
+ * @return {!Point} The content coordinates.
* @private
*/
- frameToContent(framePoint) {
+ frameToContent_(framePoint) {
// TODO(mcnee) Add a helper Point class to avoid duplicating operations
// on plain {x,y} objects.
+ const zoom = this.getZoom();
return {
- x: (framePoint.x + this.position.x) / this.zoom,
- y: (framePoint.y + this.position.y) / this.zoom
+ x: (framePoint.x + this.position.x) / zoom,
+ y: (framePoint.y + this.position.y) / zoom
};
}
/**
- * Sets the zoom to the given zoom level.
- *
- * @param {number} newZoom the zoom level to zoom to.
+ * @param {number} newZoom The zoom level to zoom to.
*/
setZoom(newZoom) {
this.fittingType_ = FittingType.NONE;
@@ -453,8 +548,12 @@ class ViewportImpl {
});
}
- /** @override */
- updateZoomFromBrowserChange(oldBrowserZoom) {
+ /**
+ * @param {!CustomEvent<number>} e Event containing the old browser zoom.
+ * @private
+ */
+ updateZoomFromBrowserChange_(e) {
+ const oldBrowserZoom = e.detail;
this.mightZoom_(() => {
// Record the scroll position (relative to the top-left of the window).
const oldZoom = oldBrowserZoom * this.internalZoom_;
@@ -463,34 +562,32 @@ class ViewportImpl {
y: this.position.y / oldZoom
};
this.contentSizeChanged_();
+ const newZoom = this.getZoom();
// Scroll to the scaled scroll position.
this.position = {
- x: currentScrollPos.x * this.zoom,
- y: currentScrollPos.y * this.zoom
+ x: currentScrollPos.x * newZoom,
+ y: currentScrollPos.y * newZoom
};
this.updateViewport_();
});
}
- /**
- * @return {number} the width of scrollbars in the viewport in pixels.
- */
+ /** @return {number} The width of scrollbars in the viewport in pixels. */
get scrollbarWidth() {
return this.scrollbarWidth_;
}
- /**
- * @return {FittingType} the fitting type the viewport is currently in.
- */
+ /** @return {FittingType} The fitting type the viewport is currently in. */
get fittingType() {
return this.fittingType_;
}
/**
- * Get the which page is at a given y position.
- *
- * @param {number} y the y-coordinate to get the page at.
- * @return {number} the index of a page overlapping the given y-coordinate.
+ * Get the page at a given y position. If there are multiple pages
+ * overlapping the given y-coordinate, return the page with the smallest
+ * index.
+ * @param {number} y The y-coordinate to get the page at.
+ * @return {number} The index of a page overlapping the given y-coordinate.
* @private
*/
getPageAtY_(y) {
@@ -521,9 +618,32 @@ class ViewportImpl {
return 0;
}
- /** @override */
+ /**
+ * Return the last page visible in the viewport. Returns the last index of the
+ * document if the viewport is below the document.
+ * @param {!ViewportRect} viewportRect
+ * @return {number} The highest index of the pages visible in the viewport.
+ * @private
+ */
+ getLastPageInViewport_(viewportRect) {
+ const pageAtY = this.getPageAtY_(viewportRect.y + viewportRect.height);
+
+ if (!this.twoUpView_ || pageAtY % 2 == 1 ||
+ pageAtY + 1 >= this.pageDimensions_.length) {
+ return pageAtY;
+ }
+
+ const nextPage = this.pageDimensions_[pageAtY + 1];
+ return getIntersectionArea(viewportRect, nextPage) > 0 ? pageAtY + 1 :
+ pageAtY;
+ }
+
+ /**
+ * @param {!Point} point
+ * @return {boolean} Whether |point| (in screen coordinates) is inside a page
+ */
isPointInsidePage(point) {
- const zoom = this.zoom;
+ const zoom = this.getZoom();
const size = this.size;
const position = this.position;
const page = this.getPageAtY_((position.y + point.y) / zoom);
@@ -544,48 +664,51 @@ class ViewportImpl {
}
/**
- * Returns the page with the greatest proportion of its height in the current
- * viewport.
- *
- * @return {number} the index of the most visible page.
+ * @return {number} The index of the page with the greatest proportion of its
+ * area in the current viewport.
*/
getMostVisiblePage() {
- const firstVisiblePage = this.getPageAtY_(this.position.y / this.zoom);
- if (firstVisiblePage == this.pageDimensions_.length - 1) {
+ const viewportRect = this.getViewportRect_();
+
+ const firstVisiblePage = this.getPageAtY_(viewportRect.y);
+ const lastPossibleVisiblePage = this.getLastPageInViewport_(viewportRect);
+ if (firstVisiblePage === lastPossibleVisiblePage) {
return firstVisiblePage;
}
- const viewportRect = {
- x: this.position.x / this.zoom,
- y: this.position.y / this.zoom,
- width: this.size.width / this.zoom,
- height: this.size.height / this.zoom
- };
- const firstVisiblePageVisibility =
- getIntersectionHeight(
- this.pageDimensions_[firstVisiblePage], viewportRect) /
- this.pageDimensions_[firstVisiblePage].height;
- const nextPageVisibility =
- getIntersectionHeight(
- this.pageDimensions_[firstVisiblePage + 1], viewportRect) /
- this.pageDimensions_[firstVisiblePage + 1].height;
- if (nextPageVisibility > firstVisiblePageVisibility) {
- return firstVisiblePage + 1;
+ let mostVisiblePage = firstVisiblePage;
+ let largestIntersection = 0;
+
+ for (let i = firstVisiblePage; i < lastPossibleVisiblePage + 1; i++) {
+ const pageArea =
+ this.pageDimensions_[i].width * this.pageDimensions_[i].height;
+
+ // TODO(thestig): check whether we can remove this check.
+ if (pageArea <= 0) {
+ continue;
+ }
+
+ const pageIntersectionArea =
+ getIntersectionArea(this.pageDimensions_[i], viewportRect) / pageArea;
+
+ if (pageIntersectionArea > largestIntersection) {
+ mostVisiblePage = i;
+ largestIntersection = pageIntersectionArea;
+ }
}
- return firstVisiblePage;
+
+ return mostVisiblePage;
}
/**
* Compute the zoom level for fit-to-page, fit-to-width or fit-to-height.
- *
* At least one of {fitWidth, fitHeight} must be true.
- *
- * @param {Object} pageDimensions the dimensions of a given page in px.
- * @param {boolean} fitWidth a bool indicating whether the whole width of the
- * page needs to be in the viewport.
- * @param {boolean} fitHeight a bool indicating whether the whole height of
- * the page needs to be in the viewport.
- * @return {number} the internal zoom to set
+ * @param {!Size} pageDimensions The dimensions of a given page in px.
+ * @param {boolean} fitWidth Whether the whole width of the page needs to be
+ * in the viewport.
+ * @param {boolean} fitHeight Whether the whole height of the page needs to be
+ * in the viewport.
+ * @return {number} The internal zoom to set
* @private
*/
computeFittingZoom_(pageDimensions, fitWidth, fitHeight) {
@@ -644,16 +767,15 @@ class ViewportImpl {
/**
* Compute a zoom level given the dimensions to fit and the actual numbers
* in those dimensions.
- *
- * @param {boolean} fitWidth make sure the page width is totally contained in
- * the window.
- * @param {boolean} fitHeight make sure the page height is totally contained
- * in the window.
- * @param {number} windowWidth the width of the window in px.
- * @param {number} windowHeight the height of the window in px.
- * @param {number} pageWidth the width of the page in px.
- * @param {number} pageHeight the height of the page in px.
- * @return {number} the internal zoom to set
+ * @param {boolean} fitWidth Whether to constrain the page width to the
+ * window.
+ * @param {boolean} fitHeight Whether to constrain the page height to the
+ * window.
+ * @param {number} windowWidth Width of the window in px.
+ * @param {number} windowHeight Height of the window in px.
+ * @param {number} pageWidth Width of the page in px.
+ * @param {number} pageHeight Height of the page in px.
+ * @return {number} The internal zoom to set
* @private
*/
computeFittingZoomGivenDimensions_(
@@ -683,9 +805,7 @@ class ViewportImpl {
return Math.max(zoom, 0);
}
- /**
- * Zoom the viewport so that the page width consumes the entire viewport.
- */
+ /** Zoom the viewport so that the page width consumes the entire viewport. */
fitToWidth() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.FIT_TO_WIDTH;
@@ -702,7 +822,6 @@ class ViewportImpl {
/**
* Zoom the viewport so that the page height consumes the entire viewport.
- *
* @param {boolean} scrollToTopOfPage Set to true if the viewport should be
* scrolled to the top of the current page. Set to false if the viewport
* should remain at the current scroll position.
@@ -723,25 +842,25 @@ class ViewportImpl {
};
this.setZoomInternal_(this.computeFittingZoom_(dimensions, false, true));
if (scrollToTopOfPage) {
- this.position = {x: 0, y: this.pageDimensions_[page].y * this.zoom};
+ this.position = {
+ x: 0,
+ y: this.pageDimensions_[page].y * this.getZoom()
+ };
}
this.updateViewport_();
});
}
- /**
- * Zoom the viewport so that the page height consumes the entire viewport.
- */
+ /** Zoom the viewport so that the page height consumes the entire viewport. */
fitToHeight() {
this.fitToHeightInternal_(true);
}
/**
* Zoom the viewport so that a page consumes as much as possible of the it.
- *
- * @param {boolean} scrollToTopOfPage Set to true if the viewport should be
- * scrolled to the top of the current page. Set to false if the viewport
- * should remain at the current scroll position.
+ * @param {boolean} scrollToTopOfPage Whether the viewport should be scrolled
+ * to the top of the current page. If false, the viewport will remain at
+ * the current scroll position.
* @private
*/
fitToPageInternal_(scrollToTopOfPage) {
@@ -758,7 +877,10 @@ class ViewportImpl {
};
this.setZoomInternal_(this.computeFittingZoom_(dimensions, true, true));
if (scrollToTopOfPage) {
- this.position = {x: 0, y: this.pageDimensions_[page].y * this.zoom};
+ this.position = {
+ x: 0,
+ y: this.pageDimensions_[page].y * this.getZoom()
+ };
}
this.updateViewport_();
});
@@ -772,9 +894,7 @@ class ViewportImpl {
this.fitToPageInternal_(true);
}
- /**
- * Zoom the viewport to the default zoom policy.
- */
+ /** Zoom the viewport to the default zoom. */
fitToNone() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.NONE;
@@ -788,9 +908,7 @@ class ViewportImpl {
});
}
- /**
- * Zoom out to the next predefined zoom level.
- */
+ /** Zoom out to the next predefined zoom level. */
zoomOut() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.NONE;
@@ -805,9 +923,7 @@ class ViewportImpl {
});
}
- /**
- * Zoom in to the next predefined zoom level.
- */
+ /** Zoom in to the next predefined zoom level. */
zoomIn() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.NONE;
@@ -824,7 +940,6 @@ class ViewportImpl {
/**
* Pinch zoom event handler.
- *
* @param {!Object} e The pinch event.
*/
pinchZoom(e) {
@@ -857,8 +972,8 @@ class ViewportImpl {
y: this.window_.innerHeight / 2
};
} else if (this.keepContentCentered_) {
- this.oldCenterInContent =
- this.frameToContent(frameToPluginCoordinate(e.center));
+ this.oldCenterInContent_ =
+ this.frameToContent_(frameToPluginCoordinate(e.center));
this.keepContentCentered_ = false;
}
@@ -872,10 +987,10 @@ class ViewportImpl {
pinchZoomStart(e) {
this.pinchPhase_ = Viewport.PinchPhase.PINCH_START;
this.prevScale_ = 1;
- this.oldCenterInContent =
- this.frameToContent(frameToPluginCoordinate(e.center));
+ this.oldCenterInContent_ =
+ this.frameToContent_(frameToPluginCoordinate(e.center));
- const needsScrollbars = this.documentNeedsScrollbars_(this.zoom);
+ const needsScrollbars = this.documentNeedsScrollbars_(this.getZoom());
this.keepContentCentered_ = !needsScrollbars.horizontal;
// We keep track of begining of the pinch.
// By doing so we will be able to compute the pan distance.
@@ -887,7 +1002,7 @@ class ViewportImpl {
this.mightZoom_(() => {
this.pinchPhase_ = Viewport.PinchPhase.PINCH_END;
const scaleDelta = e.startScaleRatio / this.prevScale_;
- this.pinchCenter_ = e.center;
+ this.pinchCenter_ = /** @type {!Point} */ (e.center);
this.setPinchZoomInternal_(scaleDelta, frameToPluginCoordinate(e.center));
this.updateViewport_();
@@ -900,8 +1015,32 @@ class ViewportImpl {
}
/**
+ * Go to the next page. If the document is in two-up view, go to the left page
+ * of the next row.
+ */
+ goToNextPage() {
+ const currentPage = this.getMostVisiblePage();
+ const nextPageOffset = (this.twoUpView_ && currentPage % 2 == 0) ? 2 : 1;
+ this.goToPage(currentPage + nextPageOffset);
+ }
+
+ /**
+ * Go to the previous page. If the document is in two-up view, go to the left
+ * page of the previous row.
+ */
+ goToPreviousPage() {
+ const currentPage = this.getMostVisiblePage();
+ let previousPageOffset = -1;
+
+ if (this.twoUpView_) {
+ previousPageOffset = (currentPage % 2 == 0) ? -2 : -3;
+ }
+
+ this.goToPage(currentPage + previousPageOffset);
+ }
+
+ /**
* Go to the given page index.
- *
* @param {number} page the index of the page to go to. zero-based.
*/
goToPage(page) {
@@ -910,7 +1049,6 @@ class ViewportImpl {
/**
* Go to the given y position in the given page index.
- *
* @param {number} page the index of the page to go to. zero-based.
* @param {number} x the x position in the page to go to.
* @param {number} y the y position in the page to go to.
@@ -935,17 +1073,15 @@ class ViewportImpl {
toolbarOffset = this.topToolbarHeight_;
}
this.position = {
- x: (dimensions.x + x) * this.zoom,
- y: (dimensions.y + y) * this.zoom - toolbarOffset
+ x: (dimensions.x + x) * this.getZoom(),
+ y: (dimensions.y + y) * this.getZoom() - toolbarOffset
};
this.updateViewport_();
});
}
/**
- * Set the dimensions of the document.
- *
- * @param {DocumentDimensions} documentDimensions the dimensions of the
+ * @param {DocumentDimensions} documentDimensions The dimensions of the
* document
*/
setDocumentDimensions(documentDimensions) {
@@ -982,9 +1118,8 @@ class ViewportImpl {
/**
* Get the coordinates of the page contents (excluding the page shadow)
* relative to the screen.
- *
- * @param {number} page the index of the page to get the rect for.
- * @return {Object} a rect representing the page in screen coordinates.
+ * @param {number} page The index of the page to get the rect for.
+ * @return {!ViewportRect} A rect representing the page in screen coordinates.
*/
getPageScreenRect(page) {
if (!this.documentDimensions_) {
@@ -1006,24 +1141,23 @@ class ViewportImpl {
Viewport.PAGE_SHADOW.left;
// Compute the space on the left of the document if the document fits
// completely in the screen.
+ const zoom = this.getZoom();
let spaceOnLeft =
- (this.size.width - this.documentDimensions_.width * this.zoom) / 2;
+ (this.size.width - this.documentDimensions_.width * zoom) / 2;
spaceOnLeft = Math.max(spaceOnLeft, 0);
return {
- x: x * this.zoom + spaceOnLeft - this.window_.pageXOffset,
- y: insetDimensions.y * this.zoom - this.window_.pageYOffset,
- width: insetDimensions.width * this.zoom,
- height: insetDimensions.height * this.zoom
+ x: x * zoom + spaceOnLeft - this.window_.pageXOffset,
+ y: insetDimensions.y * zoom - this.window_.pageYOffset,
+ width: insetDimensions.width * zoom,
+ height: insetDimensions.height * zoom
};
}
/**
* Check if the current fitting type is a paged mode.
- *
* In a paged mode, page up and page down scroll to the top of the
* previous/next page and part of the page is under the toolbar.
- *
* @return {boolean} Whether the current fitting type is a paged mode.
*/
isPagedMode() {
@@ -1032,11 +1166,7 @@ class ViewportImpl {
this.fittingType_ == FittingType.FIT_TO_HEIGHT);
}
- /**
- * Scroll the viewport to the specified position.
- *
- * @param {!Point} point The position to which to move the viewport.
- */
+ /** @param {!Point} point The position to which to scroll the viewport. */
scrollTo(point) {
let changed = false;
const newPosition = this.position;
@@ -1054,15 +1184,64 @@ class ViewportImpl {
}
}
- /**
- * Scroll the viewport by the specified delta.
- *
- * @param {!Point} delta The delta by which to move the viewport.
- */
+ /** @param {!Point} delta The delta by which to scroll the viewport. */
scrollBy(delta) {
const newPosition = this.position;
newPosition.x += delta.x;
newPosition.y += delta.y;
this.scrollTo(newPosition);
}
+
+ /** Removes all events being tracked from the tracker. */
+ resetTracker() {
+ if (this.tracker_) {
+ this.tracker_.removeAll();
+ }
+ }
}
+
+/**
+ * Enumeration of pinch states.
+ * This should match PinchPhase enum in pdf/out_of_process_instance.h
+ * @enum {number}
+ */
+Viewport.PinchPhase = {
+ PINCH_NONE: 0,
+ PINCH_START: 1,
+ PINCH_UPDATE_ZOOM_OUT: 2,
+ PINCH_UPDATE_ZOOM_IN: 3,
+ PINCH_END: 4
+};
+
+/**
+ * The increment to scroll a page by in pixels when up/down/left/right arrow
+ * keys are pressed. Usually we just let the browser handle scrolling on the
+ * window when these keys are pressed but in certain cases we need to simulate
+ * these events.
+ */
+Viewport.SCROLL_INCREMENT = 40;
+
+/**
+ * Predefined zoom factors to be used when zooming in/out. These are in
+ * ascending order. This should match the lists in
+ * components/zoom/page_zoom_constants.h and
+ * chrome/browser/resources/settings/appearance_page/appearance_page.js
+ */
+Viewport.ZOOM_FACTORS = [
+ 0.25, 1 / 3, 0.5, 2 / 3, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3,
+ 4, 5
+];
+
+/** The minimum and maximum range to be used to clip zoom factor. */
+Viewport.ZOOM_FACTOR_RANGE = {
+ min: Viewport.ZOOM_FACTORS[0],
+ max: Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1]
+};
+
+/** The width of the page shadow around pages in pixels. */
+Viewport.PAGE_SHADOW = {
+ top: 3,
+ bottom: 7,
+ left: 5,
+ right: 5
+};
diff --git a/chromium/chrome/browser/resources/pdf/viewport_interface.js b/chromium/chrome/browser/resources/pdf/viewport_interface.js
deleted file mode 100644
index c9f99aceb2f..00000000000
--- a/chromium/chrome/browser/resources/pdf/viewport_interface.js
+++ /dev/null
@@ -1,136 +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.
-
-/**
- * @typedef {{
- * width: number,
- * height: number,
- * pageDimensions: Array<ViewportRect>,
- * }}
- */
-let DocumentDimensions;
-
-/**
- * @typedef {{
- * x: number,
- * y: number
- * }}
- */
-let Point;
-
-/**
- * @typedef {{
- * width: number,
- * height: number,
- * }}
- */
-let Size;
-
-/**
- * @typedef {{
- * x: number,
- * y: number,
- * width: number,
- * height: number,
- * }}
- */
-let ViewportRect;
-
-/**
- * @interface
- */
-class Viewport {
- /**
- * Returns the document dimensions.
- *
- * @return {!Size} A dictionary with the 'width'/'height' of the document.
- */
- getDocumentDimensions() {}
-
- /**
- * @return {!Point} the scroll position of the viewport.
- */
- get position() {}
-
- /**
- * @return {!Size} the size of the viewport excluding scrollbars.
- */
- get size() {}
-
- /**
- * @return {number} the zoom level of the viewport.
- */
- get zoom() {}
-
- /**
- * Sets the zoom to the given zoom level.
- *
- * @param {number} newZoom the zoom level to zoom to.
- */
- setZoom(newZoom) {}
-
- /**
- * Gets notified of the browser zoom changing separately from the
- * internal zoom.
- *
- * @param {number} oldBrowserZoom the previous value of the browser zoom.
- */
- updateZoomFromBrowserChange(oldBrowserZoom) {}
-
- /**
- * @param {!Point} point
- * @return {boolean} Whether |point| (in screen coordinates) is inside a page
- */
- isPointInsidePage(point) {}
-}
-
-/**
- * Enumeration of pinch states.
- * This should match PinchPhase enum in pdf/out_of_process_instance.h
- * @enum {number}
- */
-Viewport.PinchPhase = {
- PINCH_NONE: 0,
- PINCH_START: 1,
- PINCH_UPDATE_ZOOM_OUT: 2,
- PINCH_UPDATE_ZOOM_IN: 3,
- PINCH_END: 4
-};
-
-/**
- * The increment to scroll a page by in pixels when up/down/left/right arrow
- * keys are pressed. Usually we just let the browser handle scrolling on the
- * window when these keys are pressed but in certain cases we need to simulate
- * these events.
- */
-Viewport.SCROLL_INCREMENT = 40;
-
-/**
- * Predefined zoom factors to be used when zooming in/out. These are in
- * ascending order. This should match the lists in
- * components/ui/zoom/page_zoom_constants.h and
- * chrome/browser/resources/settings/appearance_page/appearance_page.js
- */
-Viewport.ZOOM_FACTORS = [
- 0.25, 1 / 3, 0.5, 2 / 3, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3,
- 4, 5
-];
-
-/**
- * The minimum and maximum range to be used to clip zoom factor.
- */
-Viewport.ZOOM_FACTOR_RANGE = {
- min: Viewport.ZOOM_FACTORS[0],
- max: Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1]
-};
-
-/**
- * The width of the page shadow around pages in pixels.
- */
-Viewport.PAGE_SHADOW = {
- top: 3,
- bottom: 7,
- left: 5,
- right: 5
-};
diff --git a/chromium/chrome/browser/resources/pdf/zoom_manager.js b/chromium/chrome/browser/resources/pdf/zoom_manager.js
index 6c3182d3fd1..db2878dd3d9 100644
--- a/chromium/chrome/browser/resources/pdf/zoom_manager.js
+++ b/chromium/chrome/browser/resources/pdf/zoom_manager.js
@@ -11,35 +11,50 @@
*/
class ZoomManager {
/**
- * @param {!Viewport} viewport A Viewport for which to manage zoom.
+ * @param {function():number} getViewportZoom Callback to get the viewport's
+ * current zoom level.
* @param {number} initialZoom The initial browser zoom level.
*/
- constructor(viewport, initialZoom) {
+ constructor(getViewportZoom, initialZoom) {
if (this.constructor === ZoomManager) {
throw new TypeError('Instantiated abstract class: ZoomManager');
}
- this.viewport_ = viewport;
+
+ /** @private {number} */
this.browserZoom_ = initialZoom;
+
+ /** @private {function():number} */
+ this.getViewportZoom_ = getViewportZoom;
+
+ /** @private {!EventTarget} */
+ this.eventTarget_ = new cr.EventTarget();
+ }
+
+ /** @return {!EventTarget} */
+ getEventTarget() {
+ return this.eventTarget_;
}
/**
* Creates the appropriate kind of zoom manager given the zoom behavior.
*
* @param {BrowserApi.ZoomBehavior} zoomBehavior How to manage zoom.
- * @param {!Viewport} viewport A Viewport for which to manage zoom.
- * @param {Function} setBrowserZoomFunction A function that sets the browser
- * zoom to the provided value.
+ * @param {function():number} getViewportZoom A function that gets the current
+ * viewport zoom.
+ * @param {function(number):Promise} setBrowserZoomFunction A function that
+ * sets the browser zoom to the provided value.
* @param {number} initialZoom The initial browser zoom level.
*/
- static create(zoomBehavior, viewport, setBrowserZoomFunction, initialZoom) {
+ static create(
+ zoomBehavior, getViewportZoom, setBrowserZoomFunction, initialZoom) {
switch (zoomBehavior) {
case BrowserApi.ZoomBehavior.MANAGE:
return new ActiveZoomManager(
- viewport, setBrowserZoomFunction, initialZoom);
+ getViewportZoom, setBrowserZoomFunction, initialZoom);
case BrowserApi.ZoomBehavior.PROPAGATE_PARENT:
- return new EmbeddedZoomManager(viewport, initialZoom);
+ return new EmbeddedZoomManager(getViewportZoom, initialZoom);
default:
- return new InactiveZoomManager(viewport, initialZoom);
+ return new InactiveZoomManager(getViewportZoom, initialZoom);
}
}
@@ -104,15 +119,19 @@ class InactiveZoomManager extends ZoomManager {}
class ActiveZoomManager extends ZoomManager {
/**
* Constructs a ActiveZoomManager.
- *
- * @param {!Viewport} viewport A Viewport for which to manage zoom.
- * @param {Function} setBrowserZoomFunction A function that sets the browser
- * zoom to the provided value.
+ * @param {function():number} getViewportZoom A function that gets the current
+ * viewport zoom level
+ * @param {function(number):Promise} setBrowserZoomFunction A function that
+ * sets the browser zoom to the provided value.
* @param {number} initialZoom The initial browser zoom level.
*/
- constructor(viewport, setBrowserZoomFunction, initialZoom) {
- super(viewport, initialZoom);
+ constructor(getViewportZoom, setBrowserZoomFunction, initialZoom) {
+ super(getViewportZoom, initialZoom);
+
+ /** @private {function(number):Promise} */
this.setBrowserZoomFunction_ = setBrowserZoomFunction;
+
+ /** @private {?Promise} */
this.changingBrowserZoom_ = null;
}
@@ -135,11 +154,13 @@ class ActiveZoomManager extends ZoomManager {
}
this.browserZoom_ = newZoom;
- this.viewport_.setZoom(newZoom);
+ this.eventTarget_.dispatchEvent(
+ new CustomEvent('set-zoom', {detail: newZoom}));
}
/**
* Invoked when an extension-initiated zoom-level change occurs.
+ * @override
*/
onPdfZoomChange() {
// If we are already changing the browser zoom level in response to a
@@ -150,20 +171,21 @@ class ActiveZoomManager extends ZoomManager {
return;
}
- const zoom = this.viewport_.zoom;
- if (this.floatingPointEquals(this.browserZoom_, zoom)) {
+ const viewportZoom = this.getViewportZoom_();
+ if (this.floatingPointEquals(this.browserZoom_, viewportZoom)) {
return;
}
- this.changingBrowserZoom_ = this.setBrowserZoomFunction_(zoom).then(() => {
- this.browserZoom_ = zoom;
- this.changingBrowserZoom_ = null;
+ this.changingBrowserZoom_ =
+ this.setBrowserZoomFunction_(viewportZoom).then(() => {
+ this.browserZoom_ = viewportZoom;
+ this.changingBrowserZoom_ = null;
- // The extension's zoom level may have changed while the browser zoom
- // change was in progress. We call back into onPdfZoomChange to ensure
- // the browser zoom is up to date.
- this.onPdfZoomChange();
- });
+ // The extension's zoom level may have changed while the browser zoom
+ // change was in progress. We call back into onPdfZoomChange to ensure
+ // the browser zoom is up to date.
+ this.onPdfZoomChange();
+ });
}
/**
@@ -206,6 +228,7 @@ class EmbeddedZoomManager extends ZoomManager {
onBrowserZoomChange(newZoom) {
const oldZoom = this.browserZoom_;
this.browserZoom_ = newZoom;
- this.viewport_.updateZoomFromBrowserChange(oldZoom);
+ this.eventTarget_.dispatchEvent(
+ new CustomEvent('update-zoom-from-browser', {detail: oldZoom}));
}
}