1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * Creates a new Navigator for navigating to links inside or outside the PDF.
9 * @param {string} originalUrl The original page URL.
10 * @param {Object} viewport The viewport info of the page.
11 * @param {Object} paramsParser The object for URL parsing.
12 * @param {Function} navigateInCurrentTabCallback The Callback function that
13 * gets called when navigation happens in the current tab.
14 * @param {Function} navigateInNewTabCallback The Callback function that gets
15 * called when navigation happens in the new tab.
17 function Navigator(originalUrl
,
20 navigateInCurrentTabCallback
,
21 navigateInNewTabCallback
) {
22 this.originalUrl_
= originalUrl
;
23 this.viewport_
= viewport
;
24 this.paramsParser_
= paramsParser
;
25 this.navigateInCurrentTabCallback_
= navigateInCurrentTabCallback
;
26 this.navigateInNewTabCallback_
= navigateInNewTabCallback
;
29 Navigator
.prototype = {
32 * Function to navigate to the given URL. This might involve navigating
33 * within the PDF page or opening a new url (in the same tab or a new tab).
34 * @param {string} url The URL to navigate to.
35 * @param {boolean} newTab Whether to perform the navigation in a new tab or
38 navigate: function(url
, newTab
) {
42 // If |urlFragment| starts with '#', then it's for the same URL with a
43 // different URL fragment.
44 if (url
.charAt(0) == '#') {
45 // if '#' is already present in |originalUrl| then remove old fragment
46 // and add new url fragment.
47 var hashIndex
= this.originalUrl_
.search('#');
49 url
= this.originalUrl_
.substring(0, hashIndex
) + url
;
51 url
= this.originalUrl_
+ url
;
54 // If there's no scheme, then take a guess at the scheme.
55 if (url
.indexOf('://') == -1 && url
.indexOf('mailto:') == -1)
56 url
= this.guessUrlWithoutScheme_(url
);
58 if (!this.isValidUrl_(url
))
62 this.navigateInNewTabCallback_(url
);
64 this.paramsParser_
.getViewportFromUrlParams(
65 url
, this.onViewportReceived_
.bind(this));
71 * Called when the viewport position is received.
72 * @param {Object} viewportPosition Dictionary containing the viewport
75 onViewportReceived_: function(viewportPosition
) {
76 var pageNumber
= viewportPosition
.page
;
77 if (pageNumber
!= undefined)
78 this.viewport_
.goToPage(pageNumber
);
80 this.navigateInCurrentTabCallback_(viewportPosition
['url']);
85 * Checks if the URL starts with a scheme and s not just a scheme.
86 * @param {string} The input URL
87 * @return {boolean} Whether the url is valid.
89 isValidUrl_: function(url
) {
90 // Make sure |url| starts with a valid scheme.
91 if (url
.indexOf('http://') != 0 &&
92 url
.indexOf('https://') != 0 &&
93 url
.indexOf('ftp://') != 0 &&
94 url
.indexOf('file://') != 0 &&
95 url
.indexOf('mailto:') != 0) {
99 // Make sure |url| is not only a scheme.
100 if (url
== 'http://' ||
113 * Attempt to figure out what a URL is when there is no scheme.
114 * @param {string} The input URL
115 * @return {string} The URL with a scheme or the original URL if it is not
116 * possible to determine the scheme.
118 guessUrlWithoutScheme_: function(url
) {
119 // If the original URL is mailto:, that does not make sense to start with,
120 // and neither does adding |url| to it.
121 // If the original URL is not a valid URL, this cannot make a valid URL.
122 // In both cases, just bail out.
123 if (this.originalUrl_
.startsWith('mailto:') ||
124 !this.isValidUrl_(this.originalUrl_
)) {
128 // Check for absolute paths.
129 if (url
.startsWith('/')) {
130 var schemeEndIndex
= this.originalUrl_
.indexOf('://');
131 var firstSlash
= this.originalUrl_
.indexOf('/', schemeEndIndex
+ 3);
132 // e.g. http://www.foo.com/bar -> http://www.foo.com
133 var domain
= firstSlash
!= -1 ?
134 this.originalUrl_
.substr(0, firstSlash
) : this.originalUrl_
;
138 // Check for obvious relative paths.
139 var isRelative
= false;
140 if (url
.startsWith('.') || url
.startsWith('\\'))
143 // In Adobe Acrobat Reader XI, it looks as though links with less than
144 // 2 dot separators in the domain are considered relative links, and
145 // those with 2 of more are considered http URLs. e.g.
147 // www.foo.com/bar -> http
148 // foo.com/bar -> relative link
150 var domainSeparatorIndex
= url
.indexOf('/');
151 var domainName
= domainSeparatorIndex
== -1 ?
152 url
: url
.substr(0, domainSeparatorIndex
);
153 var domainDotCount
= (domainName
.match(/\./g) || []).length
;
154 if (domainDotCount
< 2)
159 var slashIndex
= this.originalUrl_
.lastIndexOf('/');
160 var path
= slashIndex
!= -1 ?
161 this.originalUrl_
.substr(0, slashIndex
) : this.originalUrl_
;
162 return path
+ '/' + url
;
165 return 'http://' + url
;