diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-13 13:24:50 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-14 10:57:25 +0000 |
commit | af3d4809763ef308f08ced947a73b624729ac7ea (patch) | |
tree | 4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/chrome/browser/resources/pdf | |
parent | 0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff) |
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking.
Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a
Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/chrome/browser/resources/pdf')
40 files changed, 1218 insertions, 585 deletions
diff --git a/chromium/chrome/browser/resources/pdf/browser_api.js b/chromium/chrome/browser/resources/pdf/browser_api.js index 5ba5c49d491..53f14b5460e 100644 --- a/chromium/chrome/browser/resources/pdf/browser_api.js +++ b/chromium/chrome/browser/resources/pdf/browser_api.js @@ -25,6 +25,26 @@ function lookupDefaultZoom(streamInfo) { } /** + * Returns a promise that will resolve to the initial zoom factor + * upon starting the plugin. This may differ from the default zoom + * if, for example, the page is zoomed before the plugin is run. + * @param {!Object} streamInfo The stream object pointing to the data contained + * in the PDF. + * @return {Promise<number>} A promise that will resolve to the initial zoom + * factor. + */ +function lookupInitialZoom(streamInfo) { + // Webviews don't run in tabs so |streamInfo.tabId| is -1 when running within + // a webview. + if (!chrome.tabs || streamInfo.tabId < 0) + return Promise.resolve(1); + + return new Promise(function(resolve, reject) { + chrome.tabs.getZoom(streamInfo.tabId, resolve); + }); +} + +/** * A class providing an interface to the browser. */ class BrowserApi { @@ -33,11 +53,14 @@ class BrowserApi { * @param {!Object} streamInfo The stream object which points to the data * contained in the PDF. * @param {number} defaultZoom The default browser zoom. + * @param {number} initialZoom The initial browser zoom + * upon starting the plugin. * @param {boolean} manageZoom Whether to manage zoom. */ - constructor(streamInfo, defaultZoom, manageZoom) { + constructor(streamInfo, defaultZoom, initialZoom, manageZoom) { this.streamInfo_ = streamInfo; this.defaultZoom_ = defaultZoom; + this.initialZoom_ = initialZoom; this.manageZoom_ = manageZoom; } @@ -48,8 +71,12 @@ class BrowserApi { * @param {boolean} manageZoom Whether to manage zoom. */ static create(streamInfo, manageZoom) { - return lookupDefaultZoom(streamInfo).then(function(defaultZoom) { - return new BrowserApi(streamInfo, defaultZoom, manageZoom); + return Promise.all([ + lookupDefaultZoom(streamInfo), + lookupInitialZoom(streamInfo) + ]).then(function(zoomFactors) { + return new BrowserApi( + streamInfo, zoomFactors[0], zoomFactors[1], manageZoom); }); } @@ -92,6 +119,14 @@ class BrowserApi { } /** + * Returns the initial browser zoom factor. + * @return {number} The initial browser zoom factor. + */ + getInitialZoom() { + return this.initialZoom_; + } + + /** * Adds an event listener to be notified when the browser zoom changes. * @param {function} listener The listener to be called with the new zoom * factor. diff --git a/chromium/chrome/browser/resources/pdf/elements/shared-icon-style.css b/chromium/chrome/browser/resources/pdf/elements/shared-icon-style.css new file mode 100644 index 00000000000..6611e9e09c7 --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/elements/shared-icon-style.css @@ -0,0 +1,15 @@ +/* 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. */ + +:root { + --iron-icon-height: 20px; + --iron-icon-width: 20px; + --paper-icon-button: { + height: 20px; + padding: 6px; + width: 20px; + }; + --paper-icon-button-ink-color: rgb(189, 189, 189); + --viewer-icon-ink-color: rgb(189, 189, 189); +} diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.css b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.css index ed9c5746609..58b4cde1726 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.css @@ -3,17 +3,41 @@ * found in the LICENSE file. */ #item { - -webkit-user-select: none; + @apply(--layout-center); + @apply(--layout-horizontal); color: rgb(80, 80, 80); cursor: pointer; - min-height: 40px; + font-size: 77.8%; + height: 30px; position: relative; - @apply(--paper-font-subhead); - @apply(--layout-horizontal); - @apply(--layout-center); } #item:hover { background-color: rgb(237, 237, 237); color: rgb(20, 20, 20); } + +#title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#expand { + --iron-icon-height: 16px; + --iron-icon-width: 16px; + --paper-icon-button-ink-color: var(--paper-grey-900); + height: 16px; + min-width: 16px; + padding: 6px; + transition: transform 150ms; + width: 16px; +} + +:host-context([dir=rtl]) #expand { + transform: rotate(180deg); +} + +:host([children-shown]) #expand { + transform: rotate(90deg); +} 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 9328289811e..008eef63037 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 @@ -6,17 +6,20 @@ <link rel="import" type="css" href="viewer-bookmark.css"> <template> <div id="item" on-click="onClick"> - <span>{{bookmark.title}}</span> <paper-ripple></paper-ripple> + <paper-icon-button id="expand" icon="chevron-right" + on-click="toggleChildren"> + </paper-icon-button> + <span id="title" tabindex="0">{{bookmark.title}}</span> </div> - <div class="sub-bookmark"> - <!-- The sub-bookmarks will only be created after the parent bookmark has - finished initializing and childDepth is available. --> + <!-- 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-repeat" items="{{bookmark.children}}"> <viewer-bookmark bookmark="{{item}}" depth="{{childDepth}}"> </viewer-bookmark> </template> - </div> + </template> </template> </dom-module> <script src="viewer-bookmark.js"></script> 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 4f555296490..7905ea4ec34 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 @@ -3,8 +3,8 @@ // found in the LICENSE file. (function() { - // Amount that each level of bookmarks is indented by (px). - var BOOKMARK_INDENT = 16; + /** Amount that each level of bookmarks is indented by (px). */ + var BOOKMARK_INDENT = 20; Polymer({ is: 'viewer-bookmark', @@ -16,24 +16,75 @@ * - page (optional) * - children (an array of bookmarks) */ - bookmark: Object, + bookmark: { + type: Object, + observer: 'bookmarkChanged_' + }, depth: { type: Number, observer: 'depthChanged' }, - childDepth: Number + childDepth: Number, + + childrenShown: { + type: Boolean, + reflectToAttribute: true, + value: false + }, + + keyEventTarget: { + type: Object, + value: function() { + return this.$.item; + } + } + }, + + behaviors: [ + Polymer.IronA11yKeysBehavior + ], + + keyBindings: { + 'enter': 'onEnter_', + 'space': 'onSpace_' + }, + + bookmarkChanged_: function() { + this.$.expand.style.visibility = + this.bookmark.children.length > 0 ? 'visible' : 'hidden'; }, depthChanged: function() { this.childDepth = this.depth + 1; - this.$.item.style.paddingLeft = (this.depth * BOOKMARK_INDENT) + 'px'; + this.$.item.style.webkitPaddingStart = + (this.depth * BOOKMARK_INDENT) + 'px'; }, onClick: function() { if (this.bookmark.hasOwnProperty('page')) this.fire('change-page', {page: this.bookmark.page}); }, + + 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(); + }, + + onSpace_: function(e) { + // paper-icon-button stops propagation of space events, so there's no need + // to check the event source here. + 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. + } }); })(); 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 index 336ca3a1e32..3f9b6847984 100644 --- 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 @@ -4,7 +4,7 @@ <dom-module id="viewer-bookmarks-content"> <template> <template is="dom-repeat" items="{{bookmarks}}"> - <viewer-bookmark bookmark="{{item}}" depth="1"></viewer-bookmark> + <viewer-bookmark bookmark="{{item}}" depth="0"></viewer-bookmark> </template> </template> </dom-module> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen-legacy/viewer-error-screen-legacy.js b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen-legacy/viewer-error-screen-legacy.js index abd56be2b3a..cd09aed83be 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen-legacy/viewer-error-screen-legacy.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen-legacy/viewer-error-screen-legacy.js @@ -6,5 +6,9 @@ Polymer({ is: 'viewer-error-screen-legacy', properties: { text: String + }, + + show: function() { + this.style.visibility = 'visible'; } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.css b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.css index 07ee91dd908..e1e91bd9b39 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.css @@ -2,21 +2,6 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -:host { - background-color: #ccc; - color: #555; - font-family: sans-serif; - font-size: 20px; - height: 100%; - pointer-events: none; - position: fixed; - text-align: center; - width: 100%; +.last-item { + margin-bottom: 24px; } - -#load-failed-message { - line-height: 0; - position: absolute; - top: 50%; - width: 100%; -}
\ No newline at end of file diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html index 24344a23b5c..2795dfbdccd 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html @@ -1,9 +1,21 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html"> <dom-module id="viewer-error-screen"> <link rel="import" type="css" href="viewer-error-screen.css"> <template> - <div id="load-failed-message">{{text}}</div> + <paper-dialog id="dialog" modal no-cancel-on-esc-key + entry-animation="fade-in-animation"> + <div id="load-failed-message" + class="last-item">{{strings.pageLoadFailed}}</div> + <div class="buttons" hidden$="{{!reloadFn}}"> + <paper-button on-click="reload" autofocus> + <span>{{strings.pageReload}}</span> + </paper-button> + </div> + </paper-dialog> </template> </dom-module> <script src="viewer-error-screen.js"></script> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js index 905c8a0d7a4..88d24a6c459 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.js @@ -5,6 +5,31 @@ Polymer({ is: 'viewer-error-screen', properties: { - text: String + strings: Object, + + reloadFn: { + type: Object, + value: null, + observer: 'reloadFnChanged_' + } + }, + + reloadFnChanged_: function() { + // The default margins in paper-dialog don't work well with hiding/showing + // the .buttons div. We need to manually manage the bottom margin to get + // around this. + if (this.reloadFn) + this.$['load-failed-message'].classList.remove('last-item'); + else + this.$['load-failed-message'].classList.add('last-item'); + }, + + show: function() { + this.$.dialog.open(); + }, + + reload: function() { + if (this.reloadFn) + this.reloadFn(); } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.css b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.css index 1f858bc2b64..ab14b2587dc 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.css @@ -2,29 +2,29 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#pageselector { - display: inline-block; - width: 0.6em; -} - -paper-input-container /deep/ .focused-line { - visibility: hidden; -} - -paper-input-container /deep/ .unfocused-line { - visibility: hidden; +:host { + color: #fff; + font-size: 88.8%; } -paper-input-container { +#pageselector { + --paper-input-container-underline: { + visibility: hidden; + }; + --paper-input-container-underline-focus: { + visibility: hidden; + }; + display: inline-block; padding: 0; + width: 1ch; } input#input { + -webkit-margin-start: -3px; color: #fff; - font-size: 1em; - line-height: 20px; + line-height: 18px; padding: 3px; - text-align: right; + text-align: end; } input#input:focus, @@ -33,9 +33,16 @@ input#input:hover { border-radius: 2px; } +#slash { + padding: 0 3px; +} + +#pagelength-spacer { + display: inline-block; + text-align: start; +} + +#slash, #pagelength { - color: #fff; - font-size: 0.7em; - font-weight: 400; - padding-left: 3px; + font-size: 81.25%; } diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html index 82fc8975526..c686c3ef63b 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html @@ -6,10 +6,14 @@ <link rel="import" type="css" href="viewer-page-selector.css"> <template> <paper-input-container id="pageselector" no-label-float> - <input id="input" is="iron-input" bind-value="{{pageNo}}" on-mouseup="select" - on-change="pageNoCommitted"> + <input id="input" is="iron-input" value="{{pageNo}}" + prevent-invalid-input allowed-pattern="\d" on-mouseup="select" + on-change="pageNoCommitted" aria-label$="{{strings.labelPageNumber}}"> </paper-input-container> - <span id="pagelength">/ <span>{{docLength}}</span></span> + <span id="slash"> / </span> + <span id="pagelength-spacer"> + <span id="pagelength">{{docLength}}</span> + </span> </template> </dom-module> <script src="viewer-page-selector.js"></script> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js index 5086219364e..014362ab962 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var DIGIT_LENGTH = 0.6; - Polymer({ is: 'viewer-page-selector', @@ -18,27 +16,44 @@ Polymer({ }, /** - * The current page being viewed (1-based). + * The current page being viewed (1-based). A change to pageNo is mirrored + * immediately to the input field. A change to the input field is not + * mirrored back until pageNoCommitted() is called and change-page is fired. */ pageNo: { - type: String, - value: '1' - } + type: Number, + value: 1 + }, + + strings: Object }, pageNoCommitted: function() { - var page = parseInt(this.pageNo); - if (!isNaN(page)) { + var page = parseInt(this.$.input.value); + + if (!isNaN(page) && page <= this.docLength && page > 0) this.fire('change-page', {page: page - 1}); - } + else + this.$.input.value = this.pageNo; + this.$.input.blur(); }, docLengthChanged: function() { var numDigits = this.docLength.toString().length; - this.$.pageselector.style.width = (numDigits * DIGIT_LENGTH) + 'em'; + this.$.pageselector.style.width = numDigits + 'ch'; + // Set both sides of the slash to the same width, so that the layout is + // exactly centered. + this.$['pagelength-spacer'].style.width = numDigits + 'ch'; }, select: function() { this.$.input.select(); + }, + + /** + * @return {boolean} True if the selector input field is currently focused. + */ + isActive: function() { + return this.shadowRoot.activeElement == this.$.input; } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.css b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.css deleted file mode 100644 index 83c3fc47961..00000000000 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.css +++ /dev/null @@ -1,39 +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. */ - -:host { - -webkit-transition: opacity 400ms ease-in-out; - background-color: #ccc; - color: #555; - display: table; - font-family: sans-serif; - font-size: 15px; - height: 100%; - pointer-events: none; - position: fixed; - text-align: center; - width: 100%; -} - -#message { - padding-bottom: 10px; -} - -.center { - display: table-cell; - vertical-align: middle; -} - -.form { - border: 1px solid #777; - box-shadow: 1px 1px 1px; - display: inline-block; - padding: 10px; - width: 300px; -} - -input { - color: #333; - pointer-events: all; -}
\ No newline at end of file diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html index 3506405441e..18065022df7 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html @@ -1,15 +1,30 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <dom-module id="viewer-password-screen"> - <link rel="import" type="css" href="viewer-password-screen.css"> <template> - <div class="center"> - <form class="form"> - <div id="message">{{text}}</div> - <input id="password" type="password" size="20"></input> - <input id="submit" type="submit" on-click="submit"></input> - </form> - </div> + <paper-dialog id="dialog" modal no-cancel-on-esc-key + entry-animation="fade-in-animation" exit-animation="fade-out-animation"> + <div id="message">[[strings.passwordPrompt]]</div> + <div class="horizontal layout start"> + <paper-input-container id="password-container" class="flex" + no-label-float invalid="[[invalid]]"> + <input is="iron-input" id="password" type="password" size="20" + on-keypress="handleKey" autofocus> + </input> + <template is="dom-if" if="[[invalid]]"> + <paper-input-error>[[strings.passwordInvalid]]</paper-input-error> + </template> + </paper-input-container> + <paper-button id="submit" + on-click="submit">{{strings.passwordSubmit}}</paper-button> + </div> + </paper-dialog> </template> </dom-module> <script src="viewer-password-screen.js"></script> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js index 491c0a8e4c6..6f5cd6ebfa6 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.js @@ -6,10 +6,9 @@ Polymer({ is: 'viewer-password-screen', properties: { - text: { - type: String, - value: 'This document is password protected. Please enter a password.', - }, + strings: Object, + + invalid: Boolean, active: { type: Boolean, @@ -18,8 +17,6 @@ Polymer({ } }, - timerId: undefined, - ready: function() { this.activeChanged(); }, @@ -31,13 +28,17 @@ Polymer({ deny: function() { this.$.password.disabled = false; this.$.submit.disabled = false; + this.invalid = true; this.$.password.focus(); this.$.password.select(); }, - submit: function(e) { - // Prevent the default form submission behavior. - e.preventDefault(); + handleKey: function(e) { + if (e.keyCode == 13) + this.submit(); + }, + + submit: function() { if (this.$.password.value.length == 0) return; this.$.password.disabled = true; @@ -46,17 +47,11 @@ Polymer({ }, activeChanged: function() { - clearTimeout(this.timerId); - this.timerId = undefined; if (this.active) { - this.style.visibility = 'visible'; - this.style.opacity = 1; + this.$.dialog.open(); this.$.password.focus(); } else { - this.style.opacity = 0; - this.timerId = setTimeout(function() { - this.style.visibility = 'hidden'; - }.bind(this), 400); + this.$.dialog.close(); } } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css index 436090c063a..b96c7b278a8 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css @@ -5,10 +5,13 @@ /* We introduce a wrapper aligner element as setting the relevant attributes * (horizontal justified layout center) have no effect on the core-toolbar. */ #aligner { + padding: 0 16px; width: 100%; } #title { + font-size: 77.8%; + font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -23,37 +26,32 @@ } #buttons { - text-align: right; + -webkit-user-select: none; + text-align: end; } -#buttons > paper-icon-button { - margin-right: 8px; +paper-icon-button { + -webkit-margin-end: 12px; } viewer-toolbar-dropdown { - margin-right: 4px; + -webkit-margin-end: 4px; } paper-progress { - height: 56px; - position: absolute; + --paper-progress-active-color: var(--google-blue-300); + --paper-progress-container-color: transparent; + --paper-progress-height: 3px; + transition: opacity 150ms; width: 100%; - z-index: 3; -} - -paper-progress { - --paper-progress-active-color: rgb(50, 54, 57); - --paper-progress-container-color: rgb(34, 36, 38); } paper-toolbar { - background-color: transparent; + --paper-toolbar-background: rgb(50, 54, 57); + @apply(--shadow-elevation-2dp); color: rgb(241, 241, 241); font-size: 1.5em; - height: 56px; - padding-left: 1em; - padding-right: 1em; - z-index: 3; + height: 48px; } paper-toolbar /deep/ ::selection { @@ -61,9 +59,33 @@ paper-toolbar /deep/ ::selection { } paper-toolbar /deep/ .toolbar-tools { - height: 56px; + height: 48px; } .invisible { visibility: hidden; } + +@media(max-width: 675px) { + #bookmarks, + #rotate-left { + display: none; + } + + #pageselector-container { + flex: 2; + } +} + +@media(max-width: 450px) { + #rotate-right { + display: none; + } +} + +@media(max-width: 400px) { + #buttons, + #pageselector-container { + display: none; + } +} 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 8cba44f130e..feec286f274 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 @@ -6,7 +6,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-up-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-material/paper-material.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html"> <link rel="import" href="../viewer-bookmarks-content/viewer-bookmarks-content.html"> @@ -14,46 +13,57 @@ <link rel="import" href="../viewer-toolbar-dropdown/viewer-toolbar-dropdown.html"> <dom-module id="viewer-pdf-toolbar"> + <link rel="import" type="css" href="../shared-icon-style.css"> <link rel="import" type="css" href="viewer-pdf-toolbar.css"> <template> - <paper-material class="fit"></paper-material> - - <paper-progress value="{{loadProgress}}"></paper-progress> <paper-toolbar> - <div id="aligner" class="horizontal layout center"> - <span id="title" class="invisible flex-5" title="{{docTitle}}"> + <div id="aligner" class="middle horizontal layout center"> + <span id="title" class="flex-5" title="{{docTitle}}"> <span>{{docTitle}}</span> </span> <div class="flex-1" id="pageselector-container"> <viewer-page-selector id="pageselector" class="invisible" - doc-length="{{docLength}}" page-no="{{pageNo}}"> + doc-length="{{docLength}}" page-no="{{pageNo}}" + strings="{{strings}}"> </viewer-page-selector> </div> <div id="buttons" class="invisible flex-5"> - <!-- TODO(tsergeant): "Bookmarks" should be localized. --> <viewer-toolbar-dropdown id="bookmarks" - hidden$="[[!bookmarks]]" - header="Bookmarks" + hidden$="[[!bookmarks.length]]" + header="{{strings.bookmarks}}" open-icon="bookmark" closed-icon="bookmark-border"> <viewer-bookmarks-content bookmarks="{{bookmarks}}"> </viewer-bookmarks-content> </viewer-toolbar-dropdown> - <paper-icon-button icon="image:rotate-right" - on-click="rotateRight"></paper-icon-button> - <!-- TODO(tsergeant): Replace this placeholder with a more useful - button. --> - <paper-icon-button icon="image:rotate-left" - on-click="rotateLeft"></paper-icon-button> - <paper-icon-button icon="save" - on-click="save"></paper-icon-button> - <paper-icon-button icon="print" - on-click="print"></paper-icon-button> + + <paper-icon-button id="rotate-right" icon="image:rotate-right" + on-click="rotateRight" alt="{{strings.tooltipRotateCW}}" + title="{{strings.tooltipRotateCW}}"> + </paper-icon-button> + + <paper-icon-button id="rotate-left" icon="image:rotate-left" + on-click="rotateLeft" alt="{{strings.tooltipRotateCCW}}" + title="{{strings.tooltipRotateCCW}}"> + </paper-icon-button> + + <paper-icon-button id="save" icon="save" + on-click="save" alt="{{strings.tooltipSave}}" + title="{{strings.tooltipSave}}"> + </paper-icon-button> + + <paper-icon-button id="print" icon="print" + on-click="print" alt="{{strings.tooltipPrint}}" + title="{{strings.tooltipPrint}}"> + </paper-icon-button> </div> </div> + <div class="bottom fit"> + <paper-progress id="progress" value="{{loadProgress}}"></paper-progress> + </div> </paper-toolbar> </template> </dom-module> 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 62e5cf9a5ec..338d9eaaeb0 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 @@ -10,6 +10,7 @@ ], properties: { + strings: Object, /** * The current loading progress of the PDF document (0 - 100). */ @@ -78,15 +79,14 @@ }, _onAnimationFinished: function() { - if (!this.opened) - this.style.visibility = 'hidden'; + this.style.transform = this.opened ? 'none' : 'translateY(-100%)'; }, loadProgressChanged: function() { if (this.loadProgress >= 100) { - this.$.title.classList.toggle('invisible', false); this.$.pageselector.classList.toggle('invisible', false); this.$.buttons.classList.toggle('invisible', false); + this.$.progress.style.opacity = 0; } }, @@ -98,7 +98,6 @@ show: function() { if (!this.opened) { this.toggleVisibility(); - this.style.visibility = 'initial'; } }, @@ -113,7 +112,16 @@ }, shouldKeepOpen: function() { - return this.$.bookmarks.dropdownOpen || this.loadProgress < 100; + return this.$.bookmarks.dropdownOpen || this.loadProgress < 100 || + this.$.pageselector.isActive(); + }, + + hideDropdowns: function() { + if (this.$.bookmarks.dropdownOpen) { + this.$.bookmarks.toggleDropdown(); + return true; + } + return false; }, setDropdownLowerBound: function(lowerBound) { diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css index 066c4a52de2..30b9f42abdf 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css @@ -4,7 +4,7 @@ :host { display: inline-block; - text-align: left; + text-align: start; } #container { @@ -30,20 +30,21 @@ paper-material { display: inline-block; } -#icon.open { +:host([dropdown-open]) #icon { background-color: rgb(25, 27, 29); border-radius: 4px; } #arrow { - margin-left: -18px; - padding-right: 4px; + -webkit-margin-start: -12px; + -webkit-padding-end: 4px; } h1 { border-bottom: 1px solid rgb(219, 219, 219); color: rgb(33, 33, 33); + font-size: 77.8%; + font-weight: 500; margin: 0; - padding: 16px; - @apply(--paper-font-title); + padding: 14px 28px; } 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 9b6ec5ec41e..25b44c296e1 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 @@ -4,10 +4,13 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <dom-module id="viewer-toolbar-dropdown"> + <link rel="import" type="css" href="../shared-icon-style.css"> <link rel="import" type="css" href="viewer-toolbar-dropdown.css"> <template> <div on-click="toggleDropdown" id="icon"> - <paper-icon-button icon="[[dropdownIcon]]"></paper-icon-button> + <paper-icon-button id="main-icon" icon="[[dropdownIcon]]" + alt="{{header}}" title="{{header}}"> + </paper-icon-button> <iron-icon icon="arrow-drop-down" id="arrow"></iron-icon> </div> 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 8586d829457..17a04c04d7b 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 @@ -12,7 +12,7 @@ var DROPDOWN_OUTER_PADDING = 2; /** Minimum height of toolbar dropdowns (px). */ - var MIN_DROPDOWN_HEIGHT = 300; + var MIN_DROPDOWN_HEIGHT = 200; Polymer({ is: 'viewer-toolbar-dropdown', @@ -30,6 +30,7 @@ /** True if the dropdown is currently open. */ dropdownOpen: { type: Boolean, + reflectToAttribute: true, value: false }, @@ -69,12 +70,9 @@ toggleDropdown: function() { this.dropdownOpen = !this.dropdownOpen; if (this.dropdownOpen) { - this.$.icon.classList.add('open'); this.$.dropdown.style.display = 'block'; if (!this.maxHeightValid_) this.updateMaxHeight(); - } else { - this.$.icon.classList.remove('open'); } this.cancelAnimation_(); this.playAnimation_(this.dropdownOpen); @@ -102,9 +100,9 @@ * @private */ playAnimation_: function(isEntry) { - this._animation = isEntry ? this.animateEntry_() : this.animateExit_(); - this._animation.onfinish = function() { - this._animation = null; + this.animation_ = isEntry ? this.animateEntry_() : this.animateExit_(); + this.animation_.onfinish = function() { + this.animation_ = null; if (!this.dropdownOpen) this.$.dropdown.style.display = 'none'; }.bind(this); @@ -114,6 +112,9 @@ var maxHeight = this.$.dropdown.getBoundingClientRect().height - DROPDOWN_OUTER_PADDING; + if (maxHeight < 0) + maxHeight = 0; + var fade = new KeyframeEffect(this.$.dropdown, [ {opacity: 0}, {opacity: 1} diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.css b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.css index 6c77cbe13dc..c9bb1896f96 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.css @@ -2,7 +2,28 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#wrapper { + transition: transform 250ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +:host([closed]) #wrapper { + transform: translateX(100%); + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +:host-context([dir=rtl]):host([closed]) #wrapper { + transform: translateX(-100%); +} + paper-fab { + --paper-fab-keyboard-focus-background: var(--viewer-icon-ink-color); + --paper-fab-mini: { + height: 36px; + padding: 8px; + width: 36px; + }; + @apply(--shadow-elevation-4dp); background-color: rgb(242, 242, 242); color: rgb(96, 96, 96); margin: 0 48px; 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 84e5da1bf99..fbc51b550d6 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 @@ -1,13 +1,16 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/transform-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-fab/paper-fab.html"> <dom-module id="viewer-zoom-button"> + <link rel="import" type="css" href="../shared-icon-style.css"> <link rel="import" type="css" href="viewer-zoom-button.css"> <template> - <paper-fab id="button" mini icon="[[icon]]"></paper-fab> + <div id="wrapper"> + <paper-fab id="button" mini icon="[[visibleIcon_]]" on-click="fireClick" + aria-label$="[[visibleTooltip_]]" title="[[visibleTooltip_]]"> + </paper-fab> + </div> </template> </dom-module> <script src="viewer-zoom-button.js"></script> 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 754badb3fcb..df556aced28 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 @@ -5,77 +5,91 @@ Polymer({ is: 'viewer-zoom-button', - behaviors: [ - Polymer.NeonAnimationRunnerBehavior - ], - properties: { - icon: String, + /** + * 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. + */ + 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)' + }, + + tooltips: Array, - opened: { + closed: { type: Boolean, - value: true + reflectToAttribute: true, + value: false + }, + + delay: { + type: Number, + observer: 'delayChanged_' + }, + + /** + * Index of the icon currently being displayed. + */ + activeIndex: { + type: Number, + value: 0 }, - delay: Number, + /** + * Icon currently being displayed on the FAB. + * @private + */ + visibleIcon_: { + type: String, + computed: 'computeVisibleIcon_(icons_, activeIndex)' + }, - animationConfig: { - type: Object, - computed: 'computeAnimationConfig(delay)' + visibleTooltip_: { + type: String, + computed: 'computeVisibleTooltip_(tooltips, activeIndex)' } }, - computeAnimationConfig: function(delay) { - return { - 'entry': { - name: 'transform-animation', - node: this, - timing: { - easing: 'cubic-bezier(0, 0, 0.2, 1)', - duration: 250, - delay: delay - }, - transformFrom: 'translateX(100%)' - }, - 'exit': { - name: 'transform-animation', - node: this, - timing: { - easing: 'cubic-bezier(0.4, 0, 1, 1)', - duration: 250, - delay: delay - }, - transformTo: 'translateX(100%)' - } - }; + computeIconsArray_: function(icons) { + return icons.split(' '); + }, + + computeVisibleIcon_: function(icons, activeIndex) { + return icons[activeIndex]; }, - listeners: { - 'neon-animation-finish': '_onAnimationFinished' + computeVisibleTooltip_: function(tooltips, activeIndex) { + return tooltips[activeIndex]; }, - _onAnimationFinished: function() { - // Must use visibility: hidden so that the buttons do not change layout as - // they are hidden. - if (!this.opened) - this.style.visibility = 'hidden'; + delayChanged_: function() { + this.$.wrapper.style.transitionDelay = this.delay + 'ms'; }, show: function() { - if (!this.opened) { - this.toggle_(); - this.style.visibility = 'initial'; - } + this.closed = false; }, hide: function() { - if (this.opened) - this.toggle_(); + this.closed = true; }, - toggle_: function() { - this.opened = !this.opened; - this.cancelAnimation(); - this.playAnimation(this.opened ? 'entry' : 'exit'); - }, + 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. + this.fire('fabclick'); + + this.activeIndex = (this.activeIndex + 1) % this.icons_.length; + } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css index 808cd91f8fd..4756c8b3ebe 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css @@ -3,6 +3,7 @@ * found in the LICENSE file. */ :host { + -webkit-user-select: none; bottom: 0; padding: 48px 0; position: fixed; @@ -10,18 +11,21 @@ z-index: 3; } +:host-context([dir=rtl]) { + left: 0; + right: auto; +} + viewer-zoom-button { display: block; } -/* A small gap between the fit to page/fit to width buttons and the zoom in/zoom - * out buttons. */ -#fit-to-page-button, +/* A small gap between the zoom in/zoom out buttons. */ #zoom-out-button { - margin-top: 1em; + margin-top: 10px; } -/* A larger gap between the top two and bottom two buttons. */ +/* A larger gap between the fit button and bottom two buttons. */ #zoom-in-button { - margin-top: 2em; + margin-top: 24px; } diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html index 88649f4c52e..a2e3b372014 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html @@ -8,15 +8,13 @@ <div id="zoom-buttons"> <div id="buttons"> - <!-- TODO(alexandrec): Replace with custom icons. --> - <viewer-zoom-button id="fit-to-width-button" icon="fullscreen" - on-click="fitToWidth" delay="0"></viewer-zoom-button> - <viewer-zoom-button id="fit-to-page-button" icon="fullscreen-exit" - on-click="fitToPage" delay="50"></viewer-zoom-button> - <viewer-zoom-button id="zoom-in-button" icon="add" - on-click="zoomIn" delay="100"></viewer-zoom-button> - <viewer-zoom-button id="zoom-out-button" icon="remove" - on-click="zoomOut" delay="150"></viewer-zoom-button> + <viewer-zoom-button id="fit-button" icons="fullscreen-exit fullscreen" + on-fabclick="fitToggle" delay="100"> + </viewer-zoom-button> + <viewer-zoom-button id="zoom-in-button" icons="add" + on-fabclick="zoomIn" delay="50"></viewer-zoom-button> + <viewer-zoom-button id="zoom-out-button" icons="remove" + on-fabclick="zoomOut" delay="0"></viewer-zoom-button> </div> </div> </template> 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 515b49df1cc..c65365c93bb 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 @@ -2,62 +2,69 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -ANIMATION_INTERVAL = 50; - -Polymer({ - is: 'viewer-zoom-toolbar', - - properties: { - /** - * The default zoom percentage. - */ - zoomValue: { - type: Number, - value: 100 - } - }, - - get visible() { - return this.visible_; - }, - - ready: function() { - this.visible_ = true; - }, - - fitToPage: function() { - this.fire('fit-to-page'); - }, - - fitToWidth: function() { - this.fire('fit-to-width'); - }, - - zoomIn: function() { - this.fire('zoom-in'); - }, - - zoomOut: function() { - this.fire('zoom-out'); - }, - - show: function() { - if (!this.visible) { - this.visible_ = true; - this.$['fit-to-width-button'].show(); - this.$['fit-to-page-button'].show(); - this.$['zoom-in-button'].show(); - this.$['zoom-out-button'].show(); - } - }, - - hide: function() { - if (this.visible) { - this.visible_ = false; - this.$['fit-to-page-button'].hide(); - this.$['fit-to-width-button'].hide(); - this.$['zoom-in-button'].hide(); - this.$['zoom-out-button'].hide(); - } - }, -}); +(function() { + + var FIT_TO_PAGE = 0; + var FIT_TO_WIDTH = 1; + + Polymer({ + is: 'viewer-zoom-toolbar', + + properties: { + strings: { + type: Object, + observer: 'setTooltips_' + }, + + visible_: { + type: Boolean, + value: true + } + }, + + isVisible: function() { + return this.visible_; + }, + + setTooltips_: function() { + this.$['fit-button'].tooltips = + [this.strings.tooltipFitToPage, this.strings.tooltipFitToWidth]; + this.$['zoom-in-button'].tooltips = [this.strings.tooltipZoomIn]; + this.$['zoom-out-button'].tooltips = [this.strings.tooltipZoomOut]; + }, + + fitToggle: function() { + if (this.$['fit-button'].activeIndex == FIT_TO_WIDTH) + this.fire('fit-to-width'); + else + this.fire('fit-to-page'); + }, + + zoomIn: function() { + this.fire('zoom-in'); + }, + + zoomOut: function() { + this.fire('zoom-out'); + }, + + show: function() { + if (!this.visible_) { + this.visible_ = true; + this.$['fit-button'].show(); + this.$['zoom-in-button'].show(); + this.$['zoom-out-button'].show(); + } + }, + + hide: function() { + if (this.visible_) { + this.visible_ = false; + this.$['fit-button'].hide(); + this.$['zoom-in-button'].hide(); + this.$['zoom-out-button'].hide(); + } + }, + }); + +})(); diff --git a/chromium/chrome/browser/resources/pdf/index-material.css b/chromium/chrome/browser/resources/pdf/index-material.css index ff62d3f99ec..a443bac50ec 100644 --- a/chromium/chrome/browser/resources/pdf/index-material.css +++ b/chromium/chrome/browser/resources/pdf/index-material.css @@ -4,16 +4,19 @@ body { background-color: rgb(82, 86, 89); - font-family: Roboto, 'Helvetica Neue', Helvetica, Arial; + font-family: 'Roboto', 'Noto', sans-serif; margin: 0; } +viewer-page-indicator { + visibility: hidden; + z-index: 2; +} + viewer-pdf-toolbar { position: fixed; width: 100%; - /* TODO(alexandrec): the viewer-pane's paper-dialog is set to z-index: 12 - * internally by the polymer element. Figure out why that is happening. */ - z-index: 1000; + z-index: 4; } #plugin { @@ -28,27 +31,20 @@ viewer-pdf-toolbar { z-index: 0; } -bookmarks-pane { - z-index: 2; +@media(max-height: 250px) { + viewer-pdf-toolbar { + display: none; + } } -viewer-toolbar { - visibility: hidden; - white-space: nowrap; - z-index: 3; +@media(max-height: 200px) { + viewer-zoom-toolbar { + display: none; + } } -viewer-page-indicator { - visibility: hidden; - z-index: 3; -} - -viewer-error-screen { - visibility: hidden; - z-index: 2; -} - -viewer-password-screen { - visibility: hidden; - z-index: 2; +@media(max-width: 300px) { + viewer-zoom-toolbar { + display: none; + } } diff --git a/chromium/chrome/browser/resources/pdf/index-material.html b/chromium/chrome/browser/resources/pdf/index-material.html index 984d7bcb2c7..5c2c1c4e069 100644 --- a/chromium/chrome/browser/resources/pdf/index-material.html +++ b/chromium/chrome/browser/resources/pdf/index-material.html @@ -1,10 +1,11 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language"> +<html> <head> <meta charset="utf-8"> <!-- Must be before any other scripts or Polymer imports. --> - <script src="settings.js"></script> + <script src="chrome://resources/js/polymer_config.js"></script> <link rel="import" href="elements/viewer-error-screen/viewer-error-screen.html"> + <link rel="import" href="elements/viewer-page-indicator/viewer-page-indicator.html"> <link rel="import" href="elements/viewer-page-selector/viewer-page-selector.html"> <link rel="import" href="elements/viewer-password-screen/viewer-password-screen.html"> <link rel="import" href="elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html"> @@ -12,21 +13,23 @@ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://resources/css/roboto.css"> - <link rel="stylesheet" type="text/css" href="index-material.css"> + <link rel="stylesheet" href="index-material.css"> </head> <body> -<viewer-pdf-toolbar id="material-toolbar"></viewer-pdf-toolbar> +<viewer-pdf-toolbar id="material-toolbar" hidden></viewer-pdf-toolbar> <div id="sizer"></div> <viewer-password-screen id="password-screen"></viewer-password-screen> <viewer-zoom-toolbar id="zoom-toolbar"></viewer-zoom-toolbar> +<viewer-page-indicator id="page-indicator"></viewer-page-indicator> + <viewer-error-screen id="error-screen"></viewer-error-screen> </body> -<script src="ui_manager.js"></script> +<script src="toolbar_manager.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/index.html b/chromium/chrome/browser/resources/pdf/index.html index d35a6538f21..cfb3551660b 100644 --- a/chromium/chrome/browser/resources/pdf/index.html +++ b/chromium/chrome/browser/resources/pdf/index.html @@ -2,7 +2,7 @@ <html i18n-values="dir:textdirection;lang:language"> <head> <meta charset="utf-8"> - <script src="settings.js"></script> + <script src="chrome://resources/js/polymer_config.js"></script> <link rel="import" href="elements/viewer-button/viewer-button.html"> <link rel="import" href="elements/viewer-error-screen-legacy/viewer-error-screen-legacy.html"> <link rel="import" href="elements/viewer-page-indicator/viewer-page-indicator.html"> diff --git a/chromium/chrome/browser/resources/pdf/manifest.json b/chromium/chrome/browser/resources/pdf/manifest.json index 8c44ec21b43..b3c4e943521 100644 --- a/chromium/chrome/browser/resources/pdf/manifest.json +++ b/chromium/chrome/browser/resources/pdf/manifest.json @@ -8,12 +8,13 @@ "offline_enabled": true, "incognito": "split", "permissions": [ - "<all_urls>" + "<all_urls>", + "resourcesPrivate" ], "mime_types": [ "application/pdf" ], - "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src *; plugin-types application/x-google-chrome-pdf", + "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: filesystem: data:; plugin-types application/x-google-chrome-pdf", // This is to work-around an issue where this extension is not granted // permission to access chrome://resources when iframed for print preview. // See https://crbug.com/444752. @@ -25,7 +26,6 @@ ], "mime_types_handler": "<INDEX>", "web_accessible_resources": [ - "index.html", "<INDEX>" ] } diff --git a/chromium/chrome/browser/resources/pdf/navigator.js b/chromium/chrome/browser/resources/pdf/navigator.js index bf86d5d371f..e6bd7ad28c4 100644 --- a/chromium/chrome/browser/resources/pdf/navigator.js +++ b/chromium/chrome/browser/resources/pdf/navigator.js @@ -27,7 +27,7 @@ function Navigator(originalUrl, } Navigator.prototype = { - /** + /** * @private * 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). @@ -38,6 +38,7 @@ Navigator.prototype = { navigate: function(url, newTab) { if (url.length == 0) return; + // If |urlFragment| starts with '#', then it's for the same URL with a // different URL fragment. if (url.charAt(0) == '#') { @@ -50,26 +51,12 @@ Navigator.prototype = { url = this.originalUrl_ + url; } - // If there's no scheme, add http. + // If there's no scheme, then take a guess at the scheme. if (url.indexOf('://') == -1 && url.indexOf('mailto:') == -1) - url = 'http://' + url; + url = this.guessUrlWithoutScheme_(url); - // Make sure inputURL starts with a valid scheme. - if (url.indexOf('http://') != 0 && - url.indexOf('https://') != 0 && - url.indexOf('ftp://') != 0 && - url.indexOf('file://') != 0 && - url.indexOf('mailto:') != 0) { + if (!this.isValidUrl_(url)) return; - } - // Make sure inputURL is not only a scheme. - if (url == 'http://' || - url == 'https://' || - url == 'ftp://' || - url == 'file://' || - url == 'mailto:') { - return; - } if (newTab) { this.navigateInNewTabCallback_(url); @@ -79,7 +66,7 @@ Navigator.prototype = { } }, - /** + /** * @private * Called when the viewport position is received. * @param {Object} viewportPosition Dictionary containing the viewport @@ -91,5 +78,90 @@ Navigator.prototype = { this.viewport_.goToPage(pageNumber); else this.navigateInCurrentTabCallback_(viewportPosition['url']); + }, + + /** + * @private + * Checks if the URL starts with a scheme and s not just a scheme. + * @param {string} The input URL + * @return {boolean} Whether the url is valid. + */ + isValidUrl_: function(url) { + // Make sure |url| starts with a valid scheme. + if (url.indexOf('http://') != 0 && + url.indexOf('https://') != 0 && + url.indexOf('ftp://') != 0 && + url.indexOf('file://') != 0 && + url.indexOf('mailto:') != 0) { + return false; + } + + // Make sure |url| is not only a scheme. + if (url == 'http://' || + url == 'https://' || + url == 'ftp://' || + url == 'file://' || + url == 'mailto:') { + return false; + } + + return true; + }, + + /** + * @private + * Attempt to figure out what a URL is when there is no scheme. + * @param {string} The input URL + * @return {string} The URL with a scheme or the original URL if it is not + * possible to determine the scheme. + */ + guessUrlWithoutScheme_: function(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:') || + !this.isValidUrl_(this.originalUrl_)) { + return url; + } + + // Check for absolute paths. + if (url.startsWith('/')) { + var schemeEndIndex = this.originalUrl_.indexOf('://'); + var firstSlash = this.originalUrl_.indexOf('/', schemeEndIndex + 3); + // e.g. http://www.foo.com/bar -> http://www.foo.com + var domain = firstSlash != -1 ? + this.originalUrl_.substr(0, firstSlash) : this.originalUrl_; + return domain + url; + } + + // Check for obvious relative paths. + var isRelative = false; + if (url.startsWith('.') || url.startsWith('\\')) + isRelative = true; + + // 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. + // + // www.foo.com/bar -> http + // foo.com/bar -> relative link + if (!isRelative) { + var domainSeparatorIndex = url.indexOf('/'); + var domainName = domainSeparatorIndex == -1 ? + url : url.substr(0, domainSeparatorIndex); + var domainDotCount = (domainName.match(/\./g) || []).length; + if (domainDotCount < 2) + isRelative = true; + } + + if (isRelative) { + var slashIndex = this.originalUrl_.lastIndexOf('/'); + var path = slashIndex != -1 ? + this.originalUrl_.substr(0, slashIndex) : this.originalUrl_; + return path + '/' + url; + } + + return 'http://' + url; } }; diff --git a/chromium/chrome/browser/resources/pdf/pdf.js b/chromium/chrome/browser/resources/pdf/pdf.js index c4975746d57..d667247abda 100644 --- a/chromium/chrome/browser/resources/pdf/pdf.js +++ b/chromium/chrome/browser/resources/pdf/pdf.js @@ -21,21 +21,38 @@ function getScrollbarWidth() { } /** - * Return the filename component of a URL. + * Return the filename component of a URL, percent decoded if possible. * @param {string} url The URL to get the filename from. * @return {string} The filename component. */ function getFilenameFromURL(url) { - var components = url.split(/\/|\\/); - return components[components.length - 1]; + // Ignore the query and fragment. + var mainUrl = url.split(/#|\?/)[0]; + var components = mainUrl.split(/\/|\\/); + var filename = components[components.length - 1]; + try { + return decodeURIComponent(filename); + } catch (e) { + if (e instanceof URIError) + return filename; + throw e; + } } /** * Called when navigation happens in the current tab. + * @param {boolean} isInTab Indicates if the PDF viewer is displayed in a tab. + * @param {boolean} isSourceFileUrl Indicates if the navigation source is a + * file:// URL. * @param {string} url The url to be opened in the current tab. */ -function onNavigateInCurrentTab(url) { - window.location.href = url; +function onNavigateInCurrentTab(isInTab, isSourceFileUrl, 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 && isInTab && isSourceFileUrl) + chrome.tabs.update({url: url}); + else + window.location.href = url; } /** @@ -46,7 +63,7 @@ function onNavigateInNewTab(url) { // Prefer the tabs API because it guarantees we can just open a new tab. // window.open doesn't have this guarantee. if (chrome.tabs) - chrome.tabs.create({ url: url}); + chrome.tabs.create({url: url}); else window.open(url); } @@ -75,6 +92,29 @@ function shouldIgnoreKeyEvents(activeElement) { PDFViewer.MIN_TOOLBAR_OFFSET = 15; /** + * The height of the toolbar along the top of the page. The document will be + * shifted down by this much in the viewport. + */ +PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56; + +/** + * Minimum height for the material toolbar to show (px). Should match the media + * query in index-material.css. If the window is smaller than this at load, + * leave no space for the toolbar. + */ +PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT = 250; + +/** + * The light-gray background color used for print preview. + */ +PDFViewer.LIGHT_BACKGROUND_COLOR = '0xFFCCCCCC'; + +/** + * The dark-gray background color used for the regular viewer. + */ +PDFViewer.DARK_BACKGROUND_COLOR = '0xFF525659'; + +/** * Creates a new PDFViewer. There should only be one of these objects per * document. * @constructor @@ -85,6 +125,7 @@ function PDFViewer(browserApi) { this.loadState_ = LoadState.LOADING; this.parentWindow_ = null; this.parentOrigin_ = null; + this.isFormFieldFocused_ = false; this.delayedScriptingMessages_ = []; @@ -97,21 +138,33 @@ function PDFViewer(browserApi) { // of the pdf and zoom level. this.sizer_ = $('sizer'); this.toolbar_ = $('toolbar'); - this.pageIndicator_ = $('page-indicator'); + if (!this.isMaterial_ || this.isPrintPreview_) + this.pageIndicator_ = $('page-indicator'); this.progressBar_ = $('progress-bar'); this.passwordScreen_ = $('password-screen'); this.passwordScreen_.addEventListener('password-submitted', this.onPasswordSubmitted_.bind(this)); this.errorScreen_ = $('error-screen'); + // Can only reload if we are in a normal tab. + if (chrome.tabs && this.browserApi_.getStreamInfo().tabId != -1) { + this.errorScreen_.reloadFn = function() { + chrome.tabs.reload(this.browserApi_.getStreamInfo().tabId); + }.bind(this); + } // Create the viewport. + var shortWindow = window.innerHeight < PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT; + var topToolbarHeight = + (this.isMaterial_ && !this.isPrintPreview_ && !shortWindow) ? + PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0; this.viewport_ = new Viewport(window, this.sizer_, this.viewportChanged_.bind(this), this.beforeZoom_.bind(this), this.afterZoom_.bind(this), getScrollbarWidth(), - this.browserApi_.getDefaultZoom()); + this.browserApi_.getDefaultZoom(), + topToolbarHeight); // 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 @@ -131,8 +184,6 @@ function PDFViewer(browserApi) { window.addEventListener('message', this.handleScriptingMessage.bind(this), false); - document.title = decodeURIComponent( - getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl)); this.plugin_.setAttribute('src', this.browserApi_.getStreamInfo().originalUrl); this.plugin_.setAttribute('stream-url', @@ -144,8 +195,11 @@ function PDFViewer(browserApi) { } this.plugin_.setAttribute('headers', headers); - if (this.isMaterial_) - this.plugin_.setAttribute('is-material', ''); + var backgroundColor = PDFViewer.DARK_BACKGROUND_COLOR; + if (!this.isMaterial_) + backgroundColor = PDFViewer.LIGHT_BACKGROUND_COLOR; + this.plugin_.setAttribute('background-color', backgroundColor); + this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight); if (!this.browserApi_.getStreamInfo().embedded) this.plugin_.setAttribute('full-frame', ''); @@ -170,47 +224,68 @@ function PDFViewer(browserApi) { this.zoomToolbar_.addEventListener('fit-to-width', this.viewport_.fitToWidth.bind(this.viewport_)); this.zoomToolbar_.addEventListener('fit-to-page', - this.viewport_.fitToPage.bind(this.viewport_)); + this.fitToPage_.bind(this)); this.zoomToolbar_.addEventListener('zoom-in', this.viewport_.zoomIn.bind(this.viewport_)); this.zoomToolbar_.addEventListener('zoom-out', this.viewport_.zoomOut.bind(this.viewport_)); - this.materialToolbar_ = $('material-toolbar'); - this.materialToolbar_.docTitle = document.title; - this.materialToolbar_.addEventListener('save', this.save_.bind(this)); - this.materialToolbar_.addEventListener('print', this.print_.bind(this)); - this.materialToolbar_.addEventListener('rotate-right', - this.rotateClockwise_.bind(this)); - this.materialToolbar_.addEventListener('rotate-left', - this.rotateCounterClockwise_.bind(this)); + if (!this.isPrintPreview_) { + this.materialToolbar_ = $('material-toolbar'); + this.materialToolbar_.hidden = false; + this.materialToolbar_.addEventListener('save', this.save_.bind(this)); + this.materialToolbar_.addEventListener('print', this.print_.bind(this)); + this.materialToolbar_.addEventListener('rotate-right', + this.rotateClockwise_.bind(this)); + this.materialToolbar_.addEventListener('rotate-left', + this.rotateCounterClockwise_.bind(this)); + // Must attach to mouseup on the plugin element, since it eats mousedown + // and click events. + this.plugin_.addEventListener('mouseup', + this.materialToolbar_.hideDropdowns.bind(this.materialToolbar_)); + + this.materialToolbar_.docTitle = + getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl); + } document.body.addEventListener('change-page', function(e) { this.viewport_.goToPage(e.detail.page); }.bind(this)); - this.uiManager_ = - new UiManager(window, this.materialToolbar_, this.zoomToolbar_); + this.toolbarManager_ = + new ToolbarManager(window, this.materialToolbar_, this.zoomToolbar_); } // Set up the ZoomManager. this.zoomManager_ = new ZoomManager( this.viewport_, this.browserApi_.setZoom.bind(this.browserApi_), - this.browserApi_.getDefaultZoom()); + this.browserApi_.getInitialZoom()); this.browserApi_.addZoomEventListener( this.zoomManager_.onBrowserZoomChange.bind(this.zoomManager_)); // Setup the keyboard event listener. - document.onkeydown = this.handleKeyEvent_.bind(this); + document.addEventListener('keydown', this.handleKeyEvent_.bind(this)); + document.addEventListener('mousemove', this.handleMouseEvent_.bind(this)); + document.addEventListener('mouseout', this.handleMouseEvent_.bind(this)); // Parse open pdf parameters. this.paramsParser_ = new OpenPDFParamsParser(this.getNamedDestination_.bind(this)); + var isInTab = this.browserApi_.getStreamInfo().tabId != -1; + var isSourceFileUrl = + this.browserApi_.getStreamInfo().originalUrl.indexOf('file://') == 0; this.navigator_ = new Navigator(this.browserApi_.getStreamInfo().originalUrl, this.viewport_, this.paramsParser_, - onNavigateInCurrentTab, onNavigateInNewTab); + onNavigateInCurrentTab.bind(undefined, + isInTab, + isSourceFileUrl), + onNavigateInNewTab); this.viewportScroller_ = new ViewportScroller(this.viewport_, this.plugin_, window); + + // Request translated strings. + if (!this.isPrintPreview_) + chrome.resourcesPrivate.getStrings('pdf', this.handleStrings_.bind(this)); } PDFViewer.prototype = { @@ -228,6 +303,9 @@ PDFViewer.prototype = { if (shouldIgnoreKeyEvents(document.activeElement) || e.defaultPrevented) return; + if (this.isMaterial_) + this.toolbarManager_.hideToolbarsAfterTimeout(e); + var pageUpHandler = function() { // Go to the previous page if we are fit-to-page. if (this.viewport_.fittingType == Viewport.FittingType.FIT_TO_PAGE) { @@ -252,6 +330,15 @@ PDFViewer.prototype = { }.bind(this); switch (e.keyCode) { + case 9: // Tab key. + this.toolbarManager_.showToolbarsForKeyboardNavigation(); + return; + case 27: // Escape key. + if (this.isMaterial_ && !this.isPrintPreview_) { + this.toolbarManager_.hideSingleToolbarLayer(); + return; + } + break; // Ensure escape falls through to the print-preview handler. case 32: // Space key. if (e.shiftKey) pageUpHandler(); @@ -266,8 +353,10 @@ PDFViewer.prototype = { return; case 37: // Left arrow key. if (!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) { - // Go to the previous page if there are no horizontal scrollbars. - if (!this.viewport_.documentHasScrollbars().horizontal) { + // Go to the previous page if there are no horizontal scrollbars and + // no form field is focused. + if (!(this.viewport_.documentHasScrollbars().horizontal || + this.isFormFieldFocused_)) { this.viewport_.goToPage(this.viewport_.getMostVisiblePage() - 1); // Since we do the movement of the page. e.preventDefault(); @@ -285,8 +374,10 @@ PDFViewer.prototype = { return; case 39: // Right arrow key. if (!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) { - // Go to the next page if there are no horizontal scrollbars. - if (!this.viewport_.documentHasScrollbars().horizontal) { + // Go to the next page if there are no horizontal scrollbars and no + // form field is focused. + if (!(this.viewport_.documentHasScrollbars().horizontal || + this.isFormFieldFocused_)) { this.viewport_.goToPage(this.viewport_.getMostVisiblePage() + 1); // Since we do the movement of the page. e.preventDefault(); @@ -312,7 +403,9 @@ PDFViewer.prototype = { } return; case 71: // g key. - if (this.isMaterial_ && (e.ctrlKey || e.metaKey)) { + if (this.isMaterial_ && this.materialToolbar_ && + (e.ctrlKey || e.metaKey)) { + this.toolbarManager_.showToolbars(); this.materialToolbar_.selectPageNumber(); // To prevent the default "find text" behaviour in Chrome. e.preventDefault(); @@ -334,6 +427,19 @@ PDFViewer.prototype = { type: 'sendKeyEvent', keyEvent: SerializeKeyEvent(e) }); + } else if (this.isMaterial_) { + // Show toolbars as a fallback. + if (!(e.shiftKey || e.ctrlKey || e.altKey)) + this.toolbarManager_.showToolbars(); + } + }, + + handleMouseEvent_: function(e) { + if (this.isMaterial_) { + if (e.type == 'mousemove') + this.toolbarManager_.handleMouseMove(e); + else if (e.type == 'mouseout') + this.toolbarManager_.hideToolbarsForMouseOut(); } }, @@ -357,6 +463,11 @@ PDFViewer.prototype = { }); }, + fitToPage_: function() { + this.viewport_.fitToPage(); + this.toolbarManager_.forceHideTopToolbar(); + }, + /** * @private * Notify the plugin to print. @@ -432,14 +543,16 @@ PDFViewer.prototype = { * @param {number} progress the progress as a percentage. */ updateProgress_: function(progress) { - if (this.isMaterial_) - this.materialToolbar_.loadProgress = progress; - else + if (this.isMaterial_) { + if (this.materialToolbar_) + this.materialToolbar_.loadProgress = progress; + } else { this.progressBar_.progress = progress; + } if (progress == -1) { // Document load failed. - this.errorScreen_.style.visibility = 'visible'; + this.errorScreen_.show(); this.sizer_.style.display = 'none'; if (!this.isMaterial_) this.toolbar_.style.visibility = 'hidden'; @@ -462,7 +575,31 @@ PDFViewer.prototype = { this.handleScriptingMessage(this.delayedScriptingMessages_.shift()); if (this.isMaterial_) - this.uiManager_.hideUiAfterTimeout(); + this.toolbarManager_.hideToolbarsAfterTimeout(); + } + }, + + /** + * @private + * Load a dictionary of translated strings into the UI. Used as a callback for + * chrome.resourcesPrivate. + * @param {Object} strings Dictionary of translated strings + */ + handleStrings_: function(strings) { + if (this.isMaterial_) { + this.errorScreen_.strings = strings; + this.passwordScreen_.strings = strings; + if (this.materialToolbar_) + this.materialToolbar_.strings = strings; + this.zoomToolbar_.strings = strings; + document.documentElement.lang = strings['language']; + document.dir = strings['textdirection']; + } else { + this.passwordScreen_.text = strings.passwordPrompt; + this.progressBar_.text = strings.pageLoading; + if (!this.isPrintPreview_) + this.progressBar_.style.visibility = 'visible'; + this.errorScreen_.text = strings.pageLoadFailed; } }, @@ -494,11 +631,15 @@ PDFViewer.prototype = { if (this.passwordScreen_.active) this.passwordScreen_.accept(); + if (this.pageIndicator_) + this.pageIndicator_.initialFadeIn(); + if (this.isMaterial_) { - this.materialToolbar_.docLength = - this.documentDimensions_.pageDimensions.length; + if (this.materialToolbar_) { + this.materialToolbar_.docLength = + this.documentDimensions_.pageDimensions.length; + } } else { - this.pageIndicator_.initialFadeIn(); this.toolbar_.initialFadeIn(); } break; @@ -543,22 +684,21 @@ PDFViewer.prototype = { position.y = message.data.y; this.viewport_.position = position; break; - case 'setTranslatedStrings': - this.passwordScreen_.text = message.data.getPasswordString; - if (!this.isMaterial_) { - this.progressBar_.text = message.data.loadingString; - if (!this.isPrintPreview_) - this.progressBar_.style.visibility = 'visible'; - } - this.errorScreen_.text = message.data.loadFailedString; - break; case 'cancelStreamUrl': chrome.mimeHandlerPrivate.abortStream(); break; - case 'bookmarks': + case 'metadata': + if (message.data.title) { + document.title = message.data.title; + } else { + document.title = + getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl); + } this.bookmarks_ = message.data.bookmarks; - if (this.isMaterial_ && this.bookmarks_.length !== 0) + if (this.isMaterial_ && this.materialToolbar_) { + this.materialToolbar_.docTitle = document.title; this.materialToolbar_.bookmarks = this.bookmarks; + } break; case 'setIsSelecting': this.viewportScroller_.setEnableScrolling(message.data.isSelecting); @@ -567,6 +707,9 @@ PDFViewer.prototype = { this.paramsParser_.onNamedDestinationReceived( message.data.pageNumber); break; + case 'formFocusChange': + this.isFormFieldFocused_ = message.data.focused; + break; } }, @@ -589,8 +732,6 @@ PDFViewer.prototype = { afterZoom_: function() { var position = this.viewport_.position; var zoom = this.viewport_.zoom; - if (this.isMaterial_) - this.zoomToolbar_.zoomValue = 100 * zoom; this.plugin_.postMessage({ type: 'viewport', zoom: zoom, @@ -626,11 +767,28 @@ PDFViewer.prototype = { var verticalScrollbarWidth = hasScrollbars.vertical ? scrollbarWidth : 0; var horizontalScrollbarWidth = hasScrollbars.horizontal ? scrollbarWidth : 0; - var toolbarRight = Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); - var toolbarBottom = Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); - toolbarRight -= verticalScrollbarWidth; - toolbarBottom -= horizontalScrollbarWidth; - if (!this.isMaterial_) { + if (this.isMaterial_) { + // Shift the zoom toolbar to the left by half a scrollbar width. This + // gives a compromise: if there is no scrollbar visible then the toolbar + // will be half a scrollbar width further left than the spec but if there + // is a scrollbar visible it will be half a scrollbar width further right + // than the spec. In RTL layout, the zoom toolbar is on the left side, but + // the scrollbar is still on the left, so this is not necessary. + if (document.dir == 'ltr') { + this.zoomToolbar_.style.right = -verticalScrollbarWidth + + (scrollbarWidth / 2) + 'px'; + } + // Having a horizontal scrollbar is much rarer so we don't offset the + // toolbar from the bottom any more than what the spec says. This means + // that when there is a scrollbar visible, it will be a full scrollbar + // width closer to the bottom of the screen than usual, but this is ok. + this.zoomToolbar_.style.bottom = -horizontalScrollbarWidth + 'px'; + } else { + var toolbarRight = Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); + var toolbarBottom = + Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); + toolbarRight -= verticalScrollbarWidth; + toolbarBottom -= horizontalScrollbarWidth; this.toolbar_.style.right = toolbarRight + 'px'; this.toolbar_.style.bottom = toolbarBottom + 'px'; // Hide the toolbar if it doesn't fit in the viewport. @@ -642,9 +800,12 @@ PDFViewer.prototype = { // Update the page indicator. var visiblePage = this.viewport_.getMostVisiblePage(); - if (this.isMaterial_) { + + if (this.materialToolbar_) this.materialToolbar_.pageNo = visiblePage + 1; - } else { + + // TODO(raymes): Give pageIndicator_ the same API as materialToolbar_. + if (this.pageIndicator_) { this.pageIndicator_.index = visiblePage; if (this.documentDimensions_.pageDimensions.length > 1 && hasScrollbars.vertical) { @@ -734,8 +895,7 @@ PDFViewer.prototype = { if (saveButton) saveButton.parentNode.removeChild(saveButton); - if (!this.isMaterial_) - this.pageIndicator_.pageLabels = message.data.pageNumbers; + this.pageIndicator_.pageLabels = message.data.pageNumbers; this.plugin_.postMessage({ type: 'resetPrintPreviewMode', diff --git a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js index 4a08195c83c..06fc8b546c4 100644 --- a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js +++ b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js @@ -269,16 +269,29 @@ PDFScriptingAPI.prototype = { * @return {HTMLIFrameElement} the iframe element containing the PDF viewer. */ function PDFCreateOutOfProcessPlugin(src) { + var client = new PDFScriptingAPI(window); var iframe = window.document.createElement('iframe'); - iframe.setAttribute( - 'src', - 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html?' + src); // Prevent the frame from being tab-focusable. iframe.setAttribute('tabindex', '-1'); - var client = new PDFScriptingAPI(window); - iframe.onload = function() { - client.setPlugin(iframe.contentWindow); - }; + + // TODO(raymes): This below is a hack to tell if the material design PDF UI + // has been enabled. Remove this as soon as we remove the material design PDF + // flag. + var EXTENSION_URL = 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/'; + var PAGE_NAME = 'index.html'; + var MATERIAL_PAGE_NAME = 'index-material.html'; + fetch(EXTENSION_URL + PAGE_NAME, { + method: 'get' + }).then(function() { + iframe.setAttribute('src', EXTENSION_URL + PAGE_NAME + '?' + src); + }, function() { + iframe.setAttribute('src', EXTENSION_URL + MATERIAL_PAGE_NAME + '?' + src); + }).then(function() { + iframe.onload = function() { + client.setPlugin(iframe.contentWindow); + }; + }); + // Add the functions to the iframe so that they can be called directly. iframe.setViewportChangedCallback = client.setViewportChangedCallback.bind(client); diff --git a/chromium/chrome/browser/resources/pdf/settings.js b/chromium/chrome/browser/resources/pdf/settings.js deleted file mode 100644 index 3b20eae9d9f..00000000000 --- a/chromium/chrome/browser/resources/pdf/settings.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 = {dom: 'shadow'}; diff --git a/chromium/chrome/browser/resources/pdf/toolbar_manager.js b/chromium/chrome/browser/resources/pdf/toolbar_manager.js new file mode 100644 index 00000000000..bef7cf8a41c --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/toolbar_manager.js @@ -0,0 +1,221 @@ +// 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. + +'use strict'; + +/** Idle time in ms before the UI is hidden. */ +var HIDE_TIMEOUT = 2000; +/** Time in ms after force hide before toolbar is shown again. */ +var FORCE_HIDE_TIMEOUT = 1000; +/** Velocity required in a mousemove to reveal the UI (pixels/sample). */ +var SHOW_VELOCITY = 25; +/** Distance from the top of the screen required to reveal the toolbars. */ +var TOP_TOOLBAR_REVEAL_DISTANCE = 100; +/** Distance from the bottom-right of the screen required to reveal toolbars. */ +var SIDE_TOOLBAR_REVEAL_DISTANCE_RIGHT = 150; +var SIDE_TOOLBAR_REVEAL_DISTANCE_BOTTOM = 250; + +/** + * Whether a mousemove event is high enough velocity to reveal the toolbars. + * @param {MouseEvent} e Event to test. + * @return {boolean} true if the event is a high velocity mousemove, false + * otherwise. + */ +function isHighVelocityMouseMove(e) { + return e.type == 'mousemove' && + e.movementX * e.movementX + e.movementY * e.movementY > + SHOW_VELOCITY * SHOW_VELOCITY; +} + +/** + * @param {MouseEvent} e Event to test. + * @return {boolean} True if the mouse is close to the top of the screen. + */ +function isMouseNearTopToolbar(e) { + return e.y < TOP_TOOLBAR_REVEAL_DISTANCE; +} + +/** + * @param {MouseEvent} e Event to test. + * @return {boolean} True if the mouse is close to the bottom-right of the + * screen. + */ +function isMouseNearSideToolbar(e) { + var atSide = e.x > window.innerWidth - SIDE_TOOLBAR_REVEAL_DISTANCE_RIGHT; + if (document.dir == 'rtl') + atSide = e.x < SIDE_TOOLBAR_REVEAL_DISTANCE_RIGHT; + var atBottom = e.y > window.innerHeight - SIDE_TOOLBAR_REVEAL_DISTANCE_BOTTOM; + return atSide && atBottom; +} + +/** + * Constructs a Toolbar Manager, responsible for co-ordinating between multiple + * toolbar elements. + * @constructor + * @param {Object} window The window containing the UI. + * @param {Object} toolbar The top toolbar element. + * @param {Object} zoomToolbar The zoom toolbar element. + */ +function ToolbarManager(window, toolbar, zoomToolbar) { + this.window_ = window; + this.toolbar_ = toolbar; + this.zoomToolbar_ = zoomToolbar; + + this.toolbarTimeout_ = null; + this.isMouseNearTopToolbar_ = false; + this.isMouseNearSideToolbar_ = false; + + this.sideToolbarAllowedOnly_ = false; + this.sideToolbarAllowedOnlyTimer_ = null; + + this.keyboardNavigationActive = false; + + this.window_.addEventListener('resize', this.resizeDropdowns_.bind(this)); + this.resizeDropdowns_(); +} + +ToolbarManager.prototype = { + + handleMouseMove: function(e) { + this.isMouseNearTopToolbar_ = this.toolbar_ && isMouseNearTopToolbar(e); + this.isMouseNearSideToolbar_ = isMouseNearSideToolbar(e); + + this.keyboardNavigationActive = false; + var touchInteractionActive = + (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents); + + // Allow the top toolbar to be shown if the mouse moves away from the side + // toolbar (as long as the timeout has elapsed). + if (!this.isMouseNearSideToolbar_ && !this.sideToolbarAllowedOnlyTimer_) + this.sideToolbarAllowedOnly_ = false; + + // Allow the top toolbar to be shown if the mouse moves to the top edge. + if (this.isMouseNearTopToolbar_) + this.sideToolbarAllowedOnly_ = false; + + // Tapping the screen with toolbars open tries to close them. + if (touchInteractionActive && this.zoomToolbar_.isVisible()) { + this.hideToolbarsIfAllowed(); + return; + } + + // Show the toolbars if the mouse is near the top or bottom-right of the + // screen, if the mouse moved fast, or if the touchscreen was tapped. + if (this.isMouseNearTopToolbar_ || this.isMouseNearSideToolbar_ || + isHighVelocityMouseMove(e) || touchInteractionActive) { + if (this.sideToolbarAllowedOnly_) + this.zoomToolbar_.show(); + else + this.showToolbars(); + } + this.hideToolbarsAfterTimeout(); + }, + + /** + * Display both UI toolbars. + */ + showToolbars: function() { + if (this.toolbar_) + this.toolbar_.show(); + this.zoomToolbar_.show(); + }, + + /** + * Show toolbars and mark that navigation is being performed with + * tab/shift-tab. This disables toolbar hiding until the mouse is moved or + * escape is pressed. + */ + showToolbarsForKeyboardNavigation: function() { + this.keyboardNavigationActive = true; + this.showToolbars(); + }, + + /** + * Hide toolbars after a delay, regardless of the position of the mouse. + * Intended to be called when the mouse has moved out of the parent window. + */ + hideToolbarsForMouseOut: function() { + this.isMouseNearTopToolbar_ = false; + this.isMouseNearSideToolbar_ = false; + this.hideToolbarsAfterTimeout(); + }, + + /** + * Check if the toolbars are able to be closed, and close them if they are. + * Toolbars may be kept open based on mouse/keyboard activity and active + * elements. + */ + hideToolbarsIfAllowed: function() { + if (this.isMouseNearSideToolbar_ || this.isMouseNearTopToolbar_) + return; + + if (this.toolbar_ && this.toolbar_.shouldKeepOpen()) + return; + + if (this.keyboardNavigationActive) + return; + + // Remove focus to make any visible tooltips disappear -- otherwise they'll + // still be visible on screen when the toolbar is off screen. + if ((this.toolbar_ && document.activeElement == this.toolbar_) || + document.activeElement == this.zoomToolbar_) { + document.activeElement.blur(); + } + + if (this.toolbar_) + this.toolbar_.hide(); + this.zoomToolbar_.hide(); + }, + + /** + * Hide the toolbar after the HIDE_TIMEOUT has elapsed. + */ + hideToolbarsAfterTimeout: function() { + if (this.toolbarTimeout_) + this.window_.clearTimeout(this.toolbarTimeout_); + this.toolbarTimeout_ = this.window_.setTimeout( + this.hideToolbarsIfAllowed.bind(this), HIDE_TIMEOUT); + }, + + /** + * Hide the 'topmost' layer of toolbars. Hides any dropdowns that are open, or + * hides the basic toolbars otherwise. + */ + hideSingleToolbarLayer: function() { + if (!this.toolbar_ || !this.toolbar_.hideDropdowns()) { + this.keyboardNavigationActive = false; + this.hideToolbarsIfAllowed(); + } + }, + + /** + * Hide the top toolbar and keep it hidden until both: + * - The mouse is moved away from the right side of the screen + * - 1 second has passed. + * + * The top toolbar can be immediately re-opened by moving the mouse to the top + * of the screen. + */ + forceHideTopToolbar: function() { + if (!this.toolbar_) + return; + this.toolbar_.hide(); + this.sideToolbarAllowedOnly_ = true; + this.sideToolbarAllowedOnlyTimer_ = this.window_.setTimeout(function() { + this.sideToolbarAllowedOnlyTimer_ = null; + }.bind(this), FORCE_HIDE_TIMEOUT); + }, + + /** + * Updates the size of toolbar dropdowns based on the positions of the rest of + * the UI. + * @private + */ + resizeDropdowns_: function() { + if (!this.toolbar_) + return; + var lowerBound = this.window_.innerHeight - this.zoomToolbar_.clientHeight; + this.toolbar_.setDropdownLowerBound(lowerBound); + } +}; diff --git a/chromium/chrome/browser/resources/pdf/ui_manager.js b/chromium/chrome/browser/resources/pdf/ui_manager.js deleted file mode 100644 index baee7bc0d43..00000000000 --- a/chromium/chrome/browser/resources/pdf/ui_manager.js +++ /dev/null @@ -1,106 +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. - -'use strict'; - -/** Idle time in ms before the UI is hidden. */ -var HIDE_TIMEOUT = 2000; -/** Velocity required in a mousemove to reveal the UI (pixels/sample). */ -var SHOW_VELOCITY = 20; -/** Distance from the top or right of the screen required to reveal the UI. */ -var EDGE_REVEAL = 100; - -/** - * Whether a mousemove event is high enough velocity to reveal the toolbars. - * @param {MouseEvent} e Event to test. - * @return {boolean} true if the event is a high velocity mousemove, false - * otherwise. - */ -function isHighVelocityMouseMove(e) { - return e.type == 'mousemove' && - e.movementX * e.movementX + e.movementY * e.movementY > - SHOW_VELOCITY * SHOW_VELOCITY; -} - -/** - * Whether the mouse is close enough to the edge of the screen to keep the - * toolbars open. - * @param {Event} e Event to test. - * @return {boolean} true if the mouse is close to the top or right of the - * screen. - */ -function shouldKeepUiOpen(e) { - return (e.y < EDGE_REVEAL || e.x > window.innerWidth - EDGE_REVEAL); -} - -/** - * Creates a UI Manager to handle transitioning of toolbars. - * @constructor - * @param {Object} window The window containing the UI. - * @param {Object} toolbar The top toolbar element. - * @param {Object} zoomToolbar The zoom toolbar element. - */ -function UiManager(window, toolbar, zoomToolbar) { - this.window_ = window; - this.toolbar_ = toolbar; - this.zoomToolbar_ = zoomToolbar; - - this.uiTimeout_ = null; - this.keepOpen_ = false; - - var userInputs = ['keydown', 'mousemove']; - for (var i = 0; i < userInputs.length; i++) - this.window_.addEventListener(userInputs[i], this.handleEvent.bind(this)); - - this.window_.addEventListener('resize', this.resizeDropdowns_.bind(this)); - this.resizeDropdowns_(); -} - -UiManager.prototype = { - handleEvent: function(e) { - this.keepOpen_ = shouldKeepUiOpen(e); - if (e.type != 'mousemove' || this.keepOpen_ || isHighVelocityMouseMove(e)) - this.showUi_(); - }, - - /** - * @private - * Display the toolbar and any pane that was previously opened. - */ - showUi_: function() { - this.toolbar_.show(); - this.zoomToolbar_.show(); - this.hideUiAfterTimeout(); - }, - - /** - * @private - * Hide the toolbar and any pane that was previously opened. - */ - hideUi_: function() { - if (!(this.keepOpen_ || this.toolbar_.shouldKeepOpen())) { - this.toolbar_.hide(); - this.zoomToolbar_.hide(); - } - }, - - /** - * Hide the toolbar after the HIDE_TIMEOUT has elapsed. - */ - hideUiAfterTimeout: function() { - if (this.uiTimeout_) - clearTimeout(this.uiTimeout_); - this.uiTimeout_ = setTimeout(this.hideUi_.bind(this), HIDE_TIMEOUT); - }, - - /** - * Updates the size of toolbar dropdowns based on the positions of the rest of - * the UI. - * @private - */ - resizeDropdowns_: function() { - var lowerBound = this.window_.innerHeight - this.zoomToolbar_.clientHeight; - this.toolbar_.setDropdownLowerBound(lowerBound); - } -}; diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js index 47c25079faa..4cb8fee0f66 100644 --- a/chromium/chrome/browser/resources/pdf/viewport.js +++ b/chromium/chrome/browser/resources/pdf/viewport.js @@ -25,6 +25,8 @@ function getIntersectionHeight(rect1, rect2) { * @param {Function} afterZoomCallback is run after a change in zoom * @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. */ function Viewport(window, sizer, @@ -32,7 +34,8 @@ function Viewport(window, beforeZoomCallback, afterZoomCallback, scrollbarWidth, - defaultZoom) { + defaultZoom, + topToolbarHeight) { this.window_ = window; this.sizer_ = sizer; this.viewportChangedCallback_ = viewportChangedCallback; @@ -45,6 +48,7 @@ function Viewport(window, this.scrollbarWidth_ = scrollbarWidth; this.fittingType_ = Viewport.FittingType.NONE; this.defaultZoom_ = defaultZoom; + this.topToolbarHeight_ = topToolbarHeight; window.addEventListener('scroll', this.updateViewport_.bind(this)); window.addEventListener('resize', this.resize_.bind(this)); @@ -91,6 +95,24 @@ Viewport.PAGE_SHADOW = {top: 3, bottom: 7, left: 5, right: 5}; Viewport.prototype = { /** + * Returns the zoomed and rounded document dimensions for the given zoom. + * 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. + * @private + */ + getZoomedDocumentDimensions_: function(zoom) { + if (!this.documentDimensions_) + return null; + return { + width: Math.round(this.documentDimensions_.width * zoom), + height: Math.round(this.documentDimensions_.height * zoom) + }; + }, + + /** * @private * Returns true if the document needs scrollbars at the given zoom level. * @param {number} zoom compute whether scrollbars are needed at this zoom @@ -99,25 +121,25 @@ Viewport.prototype = { * respectively. */ documentNeedsScrollbars_: function(zoom) { - if (!this.documentDimensions_) { + var zoomedDimensions = this.getZoomedDocumentDimensions_(zoom); + if (!zoomedDimensions) { return { horizontal: false, vertical: false }; } - var documentWidth = this.documentDimensions_.width * zoom; - var documentHeight = this.documentDimensions_.height * zoom; // If scrollbars are required for one direction, expand the document in the // other direction to take the width of the scrollbars into account when // deciding whether the other direction needs scrollbars. - if (documentWidth > this.window_.innerWidth) - documentHeight += this.scrollbarWidth_; - else if (documentHeight > this.window_.innerHeight) - documentWidth += this.scrollbarWidth_; + if (zoomedDimensions.width > this.window_.innerWidth) + zoomedDimensions.height += this.scrollbarWidth_; + else if (zoomedDimensions.height > this.window_.innerHeight) + zoomedDimensions.width += this.scrollbarWidth_; return { - horizontal: documentWidth > this.window_.innerWidth, - vertical: documentHeight > this.window_.innerHeight + horizontal: zoomedDimensions.width > this.window_.innerWidth, + vertical: zoomedDimensions.height + this.topToolbarHeight_ > + this.window_.innerHeight }; }, @@ -136,11 +158,11 @@ Viewport.prototype = { * Helper function called when the zoomed document size changes. */ contentSizeChanged_: function() { - if (this.documentDimensions_) { - this.sizer_.style.width = - this.documentDimensions_.width * this.zoom_ + 'px'; - this.sizer_.style.height = - this.documentDimensions_.height * this.zoom_ + 'px'; + var zoomedDimensions = this.getZoomedDocumentDimensions_(this.zoom_); + if (zoomedDimensions) { + this.sizer_.style.width = zoomedDimensions.width + 'px'; + this.sizer_.style.height = zoomedDimensions.height + + this.topToolbarHeight_ + 'px'; } }, @@ -171,7 +193,7 @@ Viewport.prototype = { get position() { return { x: this.window_.pageXOffset, - y: this.window_.pageYOffset + y: this.window_.pageYOffset - this.topToolbarHeight_ }; }, @@ -180,7 +202,7 @@ Viewport.prototype = { * @type {Object} position the position to scroll to. */ set position(position) { - this.window_.scrollTo(position.x, position.y); + this.window_.scrollTo(position.x, position.y + this.topToolbarHeight_); }, /** @@ -229,15 +251,17 @@ Viewport.prototype = { 'Viewport.mightZoom_.'; } // Record the scroll position (relative to the top-left of the window). - var currentScrollPos = [ - this.window_.pageXOffset / this.zoom_, - this.window_.pageYOffset / this.zoom_ - ]; + var currentScrollPos = { + x: this.position.x / this.zoom_, + y: this.position.y / this.zoom_ + }; this.zoom_ = newZoom; this.contentSizeChanged_(); // Scroll to the scaled scroll position. - this.window_.scrollTo(currentScrollPos[0] * newZoom, - currentScrollPos[1] * newZoom); + this.position = { + x: currentScrollPos.x * newZoom, + y: currentScrollPos.y * newZoom + }; }, /** @@ -353,10 +377,7 @@ Viewport.prototype = { if (!needsScrollbars.horizontal && !needsScrollbars.vertical) return zoom; - var zoomedDimensions = { - width: this.documentDimensions_.width * zoom, - height: this.documentDimensions_.height * zoom - }; + var zoomedDimensions = this.getZoomedDocumentDimensions_(zoom); // Check if adding a scrollbar will result in needing the other scrollbar. var scrollbarWidth = this.scrollbarWidth_; @@ -426,8 +447,12 @@ Viewport.prototype = { height: this.pageDimensions_[page].height, }; this.setZoomInternal_(this.computeFittingZoom_(dimensions, false)); - if (scrollToTopOfPage) - this.window_.scrollTo(0, this.pageDimensions_[page].y * this.zoom_); + if (scrollToTopOfPage) { + this.position = { + x: 0, + y: this.pageDimensions_[page].y * this.zoom_ + }; + } this.updateViewport_(); }.bind(this)); }, @@ -485,8 +510,16 @@ Viewport.prototype = { if (page >= this.pageDimensions_.length) page = this.pageDimensions_.length - 1; var dimensions = this.pageDimensions_[page]; - this.window_.scrollTo(dimensions.x * this.zoom_, - dimensions.y * this.zoom_); + var toolbarOffset = 0; + // Unless we're in fit to page mode, scroll above the page by + // |this.topToolbarHeight_| so that the toolbar isn't covering it + // initially. + if (this.fittingType_ != Viewport.FittingType.FIT_TO_PAGE) + toolbarOffset = this.topToolbarHeight_; + this.position = { + x: dimensions.x * this.zoom_, + y: dimensions.y * this.zoom_ - toolbarOffset + }; this.updateViewport_(); }.bind(this)); }, @@ -504,7 +537,10 @@ Viewport.prototype = { this.setZoomInternal_( Math.min(this.defaultZoom_, this.computeFittingZoom_(this.documentDimensions_, true))); - this.window_.scrollTo(0, 0); + this.position = { + x: 0, + y: -this.topToolbarHeight_ + }; } this.contentSizeChanged_(); this.resize_(); diff --git a/chromium/chrome/browser/resources/pdf/zoom_manager.js b/chromium/chrome/browser/resources/pdf/zoom_manager.js index 14c57a061d8..2b52c54aba3 100644 --- a/chromium/chrome/browser/resources/pdf/zoom_manager.js +++ b/chromium/chrome/browser/resources/pdf/zoom_manager.js @@ -13,12 +13,12 @@ class ZoomManager { * @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 {number} defaultZoom The default browser zoom level. + * @param {number} initialZoom The initial browser zoom level. */ - constructor(viewport, setBrowserZoomFunction, defaultZoom) { + constructor(viewport, setBrowserZoomFunction, initialZoom) { this.viewport_ = viewport; this.setBrowserZoomFunction_ = setBrowserZoomFunction; - this.browserZoom_ = defaultZoom; + this.browserZoom_ = initialZoom; this.changingBrowserZoom_ = null; } |