Commit bb9c12a3 authored by dpapad's avatar dpapad Committed by Chromium LUCI CQ

PDF Viewer: Return a Promise from getViewportFromUrlParams().

The API was previously callback-based, instead of Promise-based.
Callback-based APIs are more tedious to use. As a concrete example,
the PDFExtensionJSTest.ParamsParser tests were incorrectly not waiting
for any of the callbacks to execute before declaring the test
successful.

In the process also
 - Changed Navigator#navigate() to return a Promise, instead of
   firing a 'navigate-for-testing' event.
 - Fixed incorrect type annotation for OpenPdfParams#viewPosition.

Bug: None
Change-Id: Ib14b6499d3c661bb62c21c1836324ceecf1494ea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2618219
Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
Reviewed-by: default avatarDaniel Hosseinian <dhoss@chromium.org>
Auto-Submit: dpapad <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842168}
parent 77c454fb
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; import {OpenPdfParamsParser} from './open_pdf_params_parser.js';
import {Viewport} from './viewport.js'; import {Viewport} from './viewport.js';
...@@ -104,14 +103,6 @@ export class PdfNavigator { ...@@ -104,14 +103,6 @@ export class PdfNavigator {
/** @private {!NavigatorDelegate} */ /** @private {!NavigatorDelegate} */
this.navigatorDelegate_ = navigatorDelegate; this.navigatorDelegate_ = navigatorDelegate;
/** @private {!EventTarget} */
this.eventTarget_ = new EventTarget();
}
/** @return {!EventTarget} */
getEventTarget() {
return this.eventTarget_;
} }
/** /**
...@@ -120,10 +111,11 @@ export class PdfNavigator { ...@@ -120,10 +111,11 @@ export class PdfNavigator {
* @param {string} urlString The URL to navigate to. * @param {string} urlString The URL to navigate to.
* @param {!WindowOpenDisposition} disposition The window open * @param {!WindowOpenDisposition} disposition The window open
* disposition when navigating to the new URL. * disposition when navigating to the new URL.
* @return {!Promise<void>} When navigation has completed (used for testing).
*/ */
navigate(urlString, disposition) { navigate(urlString, disposition) {
if (urlString.length === 0) { if (urlString.length === 0) {
return; return Promise.resolve();
} }
// If |urlFragment| starts with '#', then it's for the same URL with a // If |urlFragment| starts with '#', then it's for the same URL with a
...@@ -145,17 +137,19 @@ export class PdfNavigator { ...@@ -145,17 +137,19 @@ export class PdfNavigator {
try { try {
url = new URL(urlString); url = new URL(urlString);
} catch (err) { } catch (err) {
return; return Promise.reject(err);
} }
if (!this.isValidUrl_(url)) { if (!this.isValidUrl_(url)) {
return; return Promise.resolve();
} }
let whenDone = Promise.resolve();
switch (disposition) { switch (disposition) {
case WindowOpenDisposition.CURRENT_TAB: case WindowOpenDisposition.CURRENT_TAB:
this.paramsParser_.getViewportFromUrlParams( whenDone = this.paramsParser_.getViewportFromUrlParams(url.href).then(
url.href, this.onViewportReceived_.bind(this)); this.onViewportReceived_.bind(this));
break; break;
case WindowOpenDisposition.NEW_BACKGROUND_TAB: case WindowOpenDisposition.NEW_BACKGROUND_TAB:
this.navigatorDelegate_.navigateInNewTab(url.href, false); this.navigatorDelegate_.navigateInNewTab(url.href, false);
...@@ -169,15 +163,14 @@ export class PdfNavigator { ...@@ -169,15 +163,14 @@ export class PdfNavigator {
case WindowOpenDisposition.SAVE_TO_DISK: case WindowOpenDisposition.SAVE_TO_DISK:
// TODO(jaepark): Alt + left clicking a link in PDF should // TODO(jaepark): Alt + left clicking a link in PDF should
// download the link. // download the link.
this.paramsParser_.getViewportFromUrlParams( whenDone = this.paramsParser_.getViewportFromUrlParams(url.href).then(
url.href, this.onViewportReceived_.bind(this)); this.onViewportReceived_.bind(this));
break; break;
default: default:
break; break;
} }
// Dispatch events for tests. return whenDone;
this.eventTarget_.dispatchEvent(new CustomEvent('navigate-for-testing'));
} }
/** /**
......
...@@ -11,11 +11,11 @@ import {Size} from './viewport.js'; ...@@ -11,11 +11,11 @@ import {Size} from './viewport.js';
* url: (string|undefined), * url: (string|undefined),
* zoom: (number|undefined), * zoom: (number|undefined),
* view: (!FittingType|undefined), * view: (!FittingType|undefined),
* viewPosition: (!Point|undefined), * viewPosition: (number|undefined),
* position: (!Object|undefined), * position: (!Object|undefined),
* }} * }}
*/ */
let OpenPdfParams; export let OpenPdfParams;
// Parses the open pdf parameters passed in the url to set initial viewport // Parses the open pdf parameters passed in the url to set initial viewport
// settings for opening the pdf. // settings for opening the pdf.
...@@ -224,10 +224,9 @@ export class OpenPdfParamsParser { ...@@ -224,10 +224,9 @@ export class OpenPdfParamsParser {
* See http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/ * See http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/
* pdfs/pdf_open_parameters.pdf for details. * pdfs/pdf_open_parameters.pdf for details.
* @param {string} url that needs to be parsed. * @param {string} url that needs to be parsed.
* @param {function(!OpenPdfParams)} callback function to be called with * @return {!Promise<!OpenPdfParams>}
* viewport info.
*/ */
getViewportFromUrlParams(url, callback) { async getViewportFromUrlParams(url) {
const params = {}; const params = {};
params['url'] = url; params['url'] = url;
...@@ -254,22 +253,23 @@ export class OpenPdfParamsParser { ...@@ -254,22 +253,23 @@ export class OpenPdfParamsParser {
} }
if (params.page === undefined && urlParams.has('nameddest')) { if (params.page === undefined && urlParams.has('nameddest')) {
this.getNamedDestinationCallback_( const data = await this.getNamedDestinationCallback_(
/** @type {string} */ (urlParams.get('nameddest'))) /** @type {string} */ (urlParams.get('nameddest')));
.then(data => {
if (data.pageNumber !== -1) { if (data.pageNumber !== -1) {
params.page = data.pageNumber; params.page = data.pageNumber;
} }
if (data.namedDestinationView) {
Object.assign( if (data.namedDestinationView) {
params, Object.assign(
this.parseNameddestViewParam_( params,
/** @type {string} */ (data.namedDestinationView))); this.parseNameddestViewParam_(
} /** @type {string} */ (data.namedDestinationView)));
callback(params); }
});
} else { return params;
callback(params);
} }
return Promise.resolve(params);
} }
} }
...@@ -12,7 +12,7 @@ import {BrowserApi, ZoomBehavior} from './browser_api.js'; ...@@ -12,7 +12,7 @@ import {BrowserApi, ZoomBehavior} from './browser_api.js';
import {FittingType, Point} from './constants.js'; import {FittingType, Point} from './constants.js';
import {ContentController, MessageData, PluginController, PluginControllerEventType} from './controller.js'; import {ContentController, MessageData, PluginController, PluginControllerEventType} from './controller.js';
import {PDFMetrics, UserAction} from './metrics.js'; import {PDFMetrics, UserAction} from './metrics.js';
import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; import {OpenPdfParams, OpenPdfParamsParser} from './open_pdf_params_parser.js';
import {LoadState} from './pdf_scripting_api.js'; import {LoadState} from './pdf_scripting_api.js';
import {DocumentDimensionsMessageData, MessageObject} from './pdf_viewer_utils.js'; import {DocumentDimensionsMessageData, MessageObject} from './pdf_viewer_utils.js';
import {Viewport} from './viewport.js'; import {Viewport} from './viewport.js';
...@@ -318,8 +318,8 @@ export class PDFViewerBaseElement extends PolymerElement { ...@@ -318,8 +318,8 @@ export class PDFViewerBaseElement extends PolymerElement {
if (this.lastViewportPosition) { if (this.lastViewportPosition) {
this.viewport_.position = this.lastViewportPosition; this.viewport_.position = this.lastViewportPosition;
} }
this.paramsParser.getViewportFromUrlParams( this.paramsParser.getViewportFromUrlParams(this.originalUrl)
this.originalUrl, params => this.handleURLParams_(params)); .then(this.handleURLParams_.bind(this));
this.setLoadState(LoadState.SUCCESS); this.setLoadState(LoadState.SUCCESS);
this.sendDocumentLoadedMessage(); this.sendDocumentLoadedMessage();
while (this.delayedScriptingMessages_.length > 0) { while (this.delayedScriptingMessages_.length > 0) {
...@@ -497,7 +497,7 @@ export class PDFViewerBaseElement extends PolymerElement { ...@@ -497,7 +497,7 @@ export class PDFViewerBaseElement extends PolymerElement {
* Handle open pdf parameters. This function updates the viewport as per * Handle open pdf parameters. This function updates the viewport as per
* the parameters mentioned in the url while opening pdf. The order is * the parameters mentioned in the url while opening pdf. The order is
* important as later actions can override the effects of previous actions. * important as later actions can override the effects of previous actions.
* @param {Object} params The open params passed in the URL. * @param {!OpenPdfParams} params The open params passed in the URL.
* @private * @private
*/ */
handleURLParams_(params) { handleURLParams_(params) {
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js';
import {NavigatorDelegate, PdfNavigator, WindowOpenDisposition} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/navigator.js'; import {NavigatorDelegate, PdfNavigator, WindowOpenDisposition} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/navigator.js';
import {OpenPdfParamsParser} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/open_pdf_params_parser.js'; import {OpenPdfParamsParser} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/open_pdf_params_parser.js';
import {PDFScriptingAPI} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_scripting_api.js'; import {PDFScriptingAPI} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_scripting_api.js';
...@@ -56,12 +55,12 @@ class MockNavigatorDelegate { ...@@ -56,12 +55,12 @@ class MockNavigatorDelegate {
* @param {!MockViewportChangedCallback} viewportChangedCallback * @param {!MockViewportChangedCallback} viewportChangedCallback
* @param {!MockNavigatorDelegate} navigatorDelegate * @param {!MockNavigatorDelegate} navigatorDelegate
*/ */
function doNavigationUrlTest( async function doNavigationUrlTest(
navigator, url, disposition, expectedResultUrl, viewportChangedCallback, navigator, url, disposition, expectedResultUrl, viewportChangedCallback,
navigatorDelegate) { navigatorDelegate) {
viewportChangedCallback.reset(); viewportChangedCallback.reset();
navigatorDelegate.reset(); navigatorDelegate.reset();
navigator.navigate(url, disposition); await navigator.navigate(url, disposition);
chrome.test.assertFalse(viewportChangedCallback.wasCalled); chrome.test.assertFalse(viewportChangedCallback.wasCalled);
chrome.test.assertEq(expectedResultUrl, navigatorDelegate.url); chrome.test.assertEq(expectedResultUrl, navigatorDelegate.url);
if (expectedResultUrl === undefined) { if (expectedResultUrl === undefined) {
...@@ -89,7 +88,7 @@ function doNavigationUrlTest( ...@@ -89,7 +88,7 @@ function doNavigationUrlTest(
* @param {string} url * @param {string} url
* @param {(string|undefined)} expectedResultUrl * @param {(string|undefined)} expectedResultUrl
*/ */
function doNavigationUrlTests(originalUrl, url, expectedResultUrl) { async function doNavigationUrlTests(originalUrl, url, expectedResultUrl) {
const mockWindow = new MockElement(100, 100, null); const mockWindow = new MockElement(100, 100, null);
const mockSizer = new MockSizer(); const mockSizer = new MockSizer();
const mockViewportChangedCallback = new MockViewportChangedCallback(); const mockViewportChangedCallback = new MockViewportChangedCallback();
...@@ -105,13 +104,13 @@ function doNavigationUrlTests(originalUrl, url, expectedResultUrl) { ...@@ -105,13 +104,13 @@ function doNavigationUrlTests(originalUrl, url, expectedResultUrl) {
const navigator = const navigator =
new PdfNavigator(originalUrl, viewport, paramsParser, navigatorDelegate); new PdfNavigator(originalUrl, viewport, paramsParser, navigatorDelegate);
doNavigationUrlTest( await doNavigationUrlTest(
navigator, url, WindowOpenDisposition.CURRENT_TAB, expectedResultUrl, navigator, url, WindowOpenDisposition.CURRENT_TAB, expectedResultUrl,
mockViewportChangedCallback, navigatorDelegate); mockViewportChangedCallback, navigatorDelegate);
doNavigationUrlTest( await doNavigationUrlTest(
navigator, url, WindowOpenDisposition.NEW_BACKGROUND_TAB, navigator, url, WindowOpenDisposition.NEW_BACKGROUND_TAB,
expectedResultUrl, mockViewportChangedCallback, navigatorDelegate); expectedResultUrl, mockViewportChangedCallback, navigatorDelegate);
doNavigationUrlTest( await doNavigationUrlTest(
navigator, url, WindowOpenDisposition.NEW_WINDOW, expectedResultUrl, navigator, url, WindowOpenDisposition.NEW_WINDOW, expectedResultUrl,
mockViewportChangedCallback, navigatorDelegate); mockViewportChangedCallback, navigatorDelegate);
} }
...@@ -154,47 +153,36 @@ const tests = [ ...@@ -154,47 +153,36 @@ const tests = [
viewport.setZoom(1); viewport.setZoom(1);
mockCallback.reset(); mockCallback.reset();
let navigatingDone =
eventToPromise('navigate-for-testing', navigator.getEventTarget());
// This should move viewport to page 0. // This should move viewport to page 0.
navigator.navigate(url + '#US', WindowOpenDisposition.CURRENT_TAB); await navigator.navigate(url + '#US', WindowOpenDisposition.CURRENT_TAB);
await navigatingDone;
chrome.test.assertTrue(mockCallback.wasCalled); chrome.test.assertTrue(mockCallback.wasCalled);
chrome.test.assertEq(0, viewport.position.x); chrome.test.assertEq(0, viewport.position.x);
chrome.test.assertEq(0, viewport.position.y); chrome.test.assertEq(0, viewport.position.y);
mockCallback.reset(); mockCallback.reset();
navigatorDelegate.reset(); navigatorDelegate.reset();
navigatingDone =
eventToPromise('navigate-for-testing', navigator.getEventTarget());
// This should open "http://xyz.pdf#US" in a new tab. So current tab // This should open "http://xyz.pdf#US" in a new tab. So current tab
// viewport should not update and viewport position should remain same. // viewport should not update and viewport position should remain same.
navigator.navigate(url + '#US', WindowOpenDisposition.NEW_BACKGROUND_TAB); await navigator.navigate(
await navigatingDone; url + '#US', WindowOpenDisposition.NEW_BACKGROUND_TAB);
chrome.test.assertFalse(mockCallback.wasCalled); chrome.test.assertFalse(mockCallback.wasCalled);
chrome.test.assertTrue(navigatorDelegate.navigateInNewTabCalled); chrome.test.assertTrue(navigatorDelegate.navigateInNewTabCalled);
chrome.test.assertEq(0, viewport.position.x); chrome.test.assertEq(0, viewport.position.x);
chrome.test.assertEq(0, viewport.position.y); chrome.test.assertEq(0, viewport.position.y);
mockCallback.reset(); mockCallback.reset();
navigatingDone =
eventToPromise('navigate-for-testing', navigator.getEventTarget());
// This should move viewport to page 2. // This should move viewport to page 2.
navigator.navigate(url + '#UY', WindowOpenDisposition.CURRENT_TAB); await navigator.navigate(url + '#UY', WindowOpenDisposition.CURRENT_TAB);
await navigatingDone;
chrome.test.assertTrue(mockCallback.wasCalled); chrome.test.assertTrue(mockCallback.wasCalled);
chrome.test.assertEq(0, viewport.position.x); chrome.test.assertEq(0, viewport.position.x);
chrome.test.assertEq(300, viewport.position.y); chrome.test.assertEq(300, viewport.position.y);
mockCallback.reset(); mockCallback.reset();
navigatorDelegate.reset(); navigatorDelegate.reset();
navigatingDone =
eventToPromise('navigate-for-testing', navigator.getEventTarget());
// #ABC is not a named destination in the page so viewport should not // #ABC is not a named destination in the page so viewport should not
// update, and the viewport position should remain same as testNavigate3's // update, and the viewport position should remain same as testNavigate3's
// navigating results, as this link will open in the same tab. // navigating results, as this link will open in the same tab.
navigator.navigate(url + '#ABC', WindowOpenDisposition.CURRENT_TAB); await navigator.navigate(url + '#ABC', WindowOpenDisposition.CURRENT_TAB);
await navigatingDone;
chrome.test.assertFalse(mockCallback.wasCalled); chrome.test.assertFalse(mockCallback.wasCalled);
chrome.test.assertTrue(navigatorDelegate.navigateInCurrentTabCalled); chrome.test.assertTrue(navigatorDelegate.navigateInCurrentTabCalled);
chrome.test.assertEq(0, viewport.position.x); chrome.test.assertEq(0, viewport.position.x);
...@@ -207,44 +195,45 @@ const tests = [ ...@@ -207,44 +195,45 @@ const tests = [
* a valid scheme, so the navigator must determine the url by following * a valid scheme, so the navigator must determine the url by following
* similar heuristics as Adobe Acrobat Reader. * similar heuristics as Adobe Acrobat Reader.
*/ */
function testNavigateForLinksWithoutScheme() { async function testNavigateForLinksWithoutScheme() {
const url = 'http://www.example.com/subdir/xyz.pdf'; const url = 'http://www.example.com/subdir/xyz.pdf';
// Sanity check. // Sanity check.
doNavigationUrlTests( await doNavigationUrlTests(
url, 'https://www.foo.com/bar.pdf', 'https://www.foo.com/bar.pdf'); url, 'https://www.foo.com/bar.pdf', 'https://www.foo.com/bar.pdf');
// Open relative links. // Open relative links.
doNavigationUrlTests( await doNavigationUrlTests(
url, 'foo/bar.pdf', 'http://www.example.com/subdir/foo/bar.pdf'); url, 'foo/bar.pdf', 'http://www.example.com/subdir/foo/bar.pdf');
doNavigationUrlTests( await doNavigationUrlTests(
url, 'foo.com/bar.pdf', url, 'foo.com/bar.pdf',
'http://www.example.com/subdir/foo.com/bar.pdf'); 'http://www.example.com/subdir/foo.com/bar.pdf');
doNavigationUrlTests( await doNavigationUrlTests(
url, '../www.foo.com/bar.pdf', url, '../www.foo.com/bar.pdf',
'http://www.example.com/www.foo.com/bar.pdf'); 'http://www.example.com/www.foo.com/bar.pdf');
// Open an absolute link. // Open an absolute link.
doNavigationUrlTests( await doNavigationUrlTests(
url, '/foodotcom/bar.pdf', 'http://www.example.com/foodotcom/bar.pdf'); url, '/foodotcom/bar.pdf', 'http://www.example.com/foodotcom/bar.pdf');
// Open a http url without a scheme. // Open a http url without a scheme.
doNavigationUrlTests( await doNavigationUrlTests(
url, 'www.foo.com/bar.pdf', 'http://www.foo.com/bar.pdf'); url, 'www.foo.com/bar.pdf', 'http://www.foo.com/bar.pdf');
// Test three dots. // Test three dots.
doNavigationUrlTests( await doNavigationUrlTests(
url, '.../bar.pdf', 'http://www.example.com/subdir/.../bar.pdf'); url, '.../bar.pdf', 'http://www.example.com/subdir/.../bar.pdf');
// Test forward slashes. // Test forward slashes.
doNavigationUrlTests(url, '..\\bar.pdf', 'http://www.example.com/bar.pdf'); await doNavigationUrlTests(
doNavigationUrlTests( url, '..\\bar.pdf', 'http://www.example.com/bar.pdf');
await doNavigationUrlTests(
url, '.\\bar.pdf', 'http://www.example.com/subdir/bar.pdf'); url, '.\\bar.pdf', 'http://www.example.com/subdir/bar.pdf');
doNavigationUrlTests( await doNavigationUrlTests(
url, '\\bar.pdf', 'http://www.example.com/subdir//bar.pdf'); url, '\\bar.pdf', 'http://www.example.com/subdir//bar.pdf');
// Regression test for https://crbug.com/569040 // Regression test for https://crbug.com/569040
doNavigationUrlTests( await doNavigationUrlTests(
url, 'http://something.else/foo#page=5', url, 'http://something.else/foo#page=5',
'http://something.else/foo#page=5'); 'http://something.else/foo#page=5');
...@@ -254,31 +243,31 @@ const tests = [ ...@@ -254,31 +243,31 @@ const tests = [
* Test opening a url in the same tab, in a new tab, and in a new window with * Test opening a url in the same tab, in a new tab, and in a new window with
* a file:/// url as the current location. * a file:/// url as the current location.
*/ */
function testNavigateFromLocalFile() { async function testNavigateFromLocalFile() {
const url = 'file:///some/path/to/myfile.pdf'; const url = 'file:///some/path/to/myfile.pdf';
// Open an absolute link. // Open an absolute link.
doNavigationUrlTests( await doNavigationUrlTests(
url, '/foodotcom/bar.pdf', 'file:///foodotcom/bar.pdf'); url, '/foodotcom/bar.pdf', 'file:///foodotcom/bar.pdf');
chrome.test.succeed(); chrome.test.succeed();
}, },
function testNavigateInvalidUrls() { async function testNavigateInvalidUrls() {
const url = 'https://example.com/some-web-document.pdf'; const url = 'https://example.com/some-web-document.pdf';
// From non-file: to file: // From non-file: to file:
doNavigationUrlTests(url, 'file:///bar.pdf', undefined); await doNavigationUrlTests(url, 'file:///bar.pdf', undefined);
doNavigationUrlTests(url, 'chrome://version', undefined); await doNavigationUrlTests(url, 'chrome://version', undefined);
doNavigationUrlTests( await doNavigationUrlTests(
url, 'javascript:// this is not a document.pdf', undefined); url, 'javascript:// this is not a document.pdf', undefined);
doNavigationUrlTests( await doNavigationUrlTests(
url, 'this-is-not-a-valid-scheme://path.pdf', undefined); url, 'this-is-not-a-valid-scheme://path.pdf', undefined);
doNavigationUrlTests(url, '', undefined); await doNavigationUrlTests(url, '', undefined);
chrome.test.succeed(); chrome.test.succeed();
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment