Commit 65033f1b authored by jaepark's avatar jaepark Committed by Commit bot

Links in PDF should open in a new window when shift + left clicked.

BUG=628057
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2300243004
Cr-Commit-Position: refs/heads/master@{#417094}
parent 535dfe7e
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "chrome/browser/plugins/plugin_prefs.h" #include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
...@@ -857,3 +858,36 @@ IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkShiftMiddleClick) { ...@@ -857,3 +858,36 @@ IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkShiftMiddleClick) {
const GURL& url = active_web_contents->GetURL(); const GURL& url = active_web_contents->GetURL();
ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); ASSERT_EQ(std::string("http://www.example.com/"), url.spec());
} }
IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkShiftLeftClick) {
host_resolver()->AddRule("www.example.com", "127.0.0.1");
GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf"));
content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url);
ASSERT_TRUE(guest_contents);
ASSERT_EQ(1U, chrome::GetTotalBrowserCount());
// The link position of the test-link.pdf in page coordinates is (110, 110).
// Convert the link position from page coordinates to screen coordinates.
gfx::Point link_position(110, 110);
ConvertPageCoordToScreenCoord(guest_contents, &link_position);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::WindowedNotificationObserver observer(
chrome::NOTIFICATION_BROWSER_WINDOW_READY,
content::NotificationService::AllSources());
content::SimulateMouseClickAt(web_contents, blink::WebInputEvent::ShiftKey,
blink::WebMouseEvent::Button::Left,
link_position);
observer.Wait();
ASSERT_EQ(2U, chrome::GetTotalBrowserCount());
content::WebContents* active_web_contents =
chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents();
ASSERT_NE(web_contents, active_web_contents);
const GURL& url = active_web_contents->GetURL();
ASSERT_EQ(std::string("http://www.example.com/"), url.spec());
}
...@@ -4,28 +4,79 @@ ...@@ -4,28 +4,79 @@
'use strict'; 'use strict';
/**
* Creates a new NavigatorDelegate for calling browser-specific functions to
* do the actual navigating.
* @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.
*/
function NavigatorDelegate(isInTab, isSourceFileUrl) {
this.isInTab_ = isInTab;
this.isSourceFileUrl_ = isSourceFileUrl;
}
/** /**
* Creates a new Navigator for navigating to links inside or outside the PDF. * Creates a new Navigator for navigating to links inside or outside the PDF.
* @param {string} originalUrl The original page URL. * @param {string} originalUrl The original page URL.
* @param {Object} viewport The viewport info of the page. * @param {Object} viewport The viewport info of the page.
* @param {Object} paramsParser The object for URL parsing. * @param {Object} paramsParser The object for URL parsing.
* @param {Function} navigateInCurrentTabCallback The Callback function that * @param {Object} navigatorDelegate The object with callback functions that
* gets called when navigation happens in the current tab. * get called when navigation happens in the current tab, a new tab,
* @param {Function} navigateInNewTabCallback The Callback function * and a new window.
* that gets called when navigation happens in the new tab.
*/ */
function Navigator(originalUrl, function Navigator(originalUrl, viewport, paramsParser, navigatorDelegate) {
viewport,
paramsParser,
navigateInCurrentTabCallback,
navigateInNewTabCallback) {
this.originalUrl_ = originalUrl; this.originalUrl_ = originalUrl;
this.viewport_ = viewport; this.viewport_ = viewport;
this.paramsParser_ = paramsParser; this.paramsParser_ = paramsParser;
this.navigateInCurrentTabCallback_ = navigateInCurrentTabCallback; this.navigatorDelegate_ = navigatorDelegate;
this.navigateInNewTabCallback_ = navigateInNewTabCallback;
} }
NavigatorDelegate.prototype = {
/**
* @public
* Called when navigation should happen in the current tab.
* @param {string} url The url to be opened in the current tab.
*/
navigateInCurrentTab: function(url) {
// When the PDFviewer is inside a browser tab, prefer the tabs API because
// it can navigate from one file:// URL to another.
if (chrome.tabs && this.isInTab_ && this.isSourceFileUrl_)
chrome.tabs.update({url: url});
else
window.location.href = url;
},
/**
* @public
* Called when navigation should happen in the new tab.
* @param {string} url The url to be opened in the new tab.
* @param {boolean} active Indicates if the new tab should be the active tab.
*/
navigateInNewTab: function(url, active) {
// 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, active: active});
else
window.open(url);
},
/**
* @public
* Called when navigation should happen in the new window.
* @param {string} url The url to be opened in the new window.
*/
navigateInNewWindow: function(url) {
// Prefer the windows API because it guarantees we can just open a new
// window. window.open with '_blank' argument doesn't have this guarantee.
if (chrome.windows)
chrome.windows.create({url: url});
else
window.open(url, '_blank');
}
};
/** /**
* Represents options when navigating to a new url. C++ counterpart of * Represents options when navigating to a new url. C++ counterpart of
* the enum is in ui/base/window_open_disposition.h. This enum represents * the enum is in ui/base/window_open_disposition.h. This enum represents
...@@ -78,16 +129,13 @@ Navigator.prototype = { ...@@ -78,16 +129,13 @@ Navigator.prototype = {
url, this.onViewportReceived_.bind(this)); url, this.onViewportReceived_.bind(this));
break; break;
case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB: case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
this.navigateInNewTabCallback_(url, false); this.navigatorDelegate_.navigateInNewTab(url, false);
break; break;
case Navigator.WindowOpenDisposition.NEW_FOREGROUND_TAB: case Navigator.WindowOpenDisposition.NEW_FOREGROUND_TAB:
this.navigateInNewTabCallback_(url, true); this.navigatorDelegate_.navigateInNewTab(url, true);
break; break;
case Navigator.WindowOpenDisposition.NEW_WINDOW: case Navigator.WindowOpenDisposition.NEW_WINDOW:
// TODO(jaepark): Shift + left clicking a link in PDF should open the this.navigatorDelegate_.navigateInNewWindow(url);
// link in a new window. See http://crbug.com/628057.
this.paramsParser_.getViewportFromUrlParams(
url, this.onViewportReceived_.bind(this));
break; break;
case Navigator.WindowOpenDisposition.SAVE_TO_DISK: case Navigator.WindowOpenDisposition.SAVE_TO_DISK:
// TODO(jaepark): Alt + left clicking a link in PDF should // TODO(jaepark): Alt + left clicking a link in PDF should
...@@ -121,7 +169,7 @@ Navigator.prototype = { ...@@ -121,7 +169,7 @@ Navigator.prototype = {
if (pageNumber != undefined && originalUrl == newUrl) if (pageNumber != undefined && originalUrl == newUrl)
this.viewport_.goToPage(pageNumber); this.viewport_.goToPage(pageNumber);
else else
this.navigateInCurrentTabCallback_(viewportPosition.url); this.navigatorDelegate_.navigateInCurrentTab(viewportPosition.url);
}, },
/** /**
......
...@@ -39,36 +39,6 @@ function getFilenameFromURL(url) { ...@@ -39,36 +39,6 @@ function getFilenameFromURL(url) {
} }
} }
/**
* 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(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;
}
/**
* Called when navigation happens in the new tab.
* @param {string} url The url to be opened in the new tab.
* @param {boolean} active Indicates if the new tab should be the active tab.
*/
function onNavigateInNewTab(url, active) {
// Prefer the tabs API because it guarantees we can just open a new tab.
// window.open doesn't have this guarantee.
if (chrome.tabs)
chrome.tabs.create({url: url, active: active});
else
window.open(url);
}
/** /**
* Whether keydown events should currently be ignored. Events are ignored when * Whether keydown events should currently be ignored. Events are ignored when
* an editable element has focus, to allow for proper editing controls. * an editable element has focus, to allow for proper editing controls.
...@@ -260,12 +230,9 @@ function PDFViewer(browserApi) { ...@@ -260,12 +230,9 @@ function PDFViewer(browserApi) {
var isInTab = this.browserApi_.getStreamInfo().tabId != -1; var isInTab = this.browserApi_.getStreamInfo().tabId != -1;
var isSourceFileUrl = this.originalUrl_.indexOf('file://') == 0; var isSourceFileUrl = this.originalUrl_.indexOf('file://') == 0;
this.navigator_ = new Navigator(this.originalUrl_, this.navigator_ = new Navigator(
this.viewport_, this.paramsParser_, this.originalUrl_, this.viewport_, this.paramsParser_,
onNavigateInCurrentTab.bind(undefined, new NavigatorDelegate(isInTab, isSourceFileUrl));
isInTab,
isSourceFileUrl),
onNavigateInNewTab);
this.viewportScroller_ = this.viewportScroller_ =
new ViewportScroller(this.viewport_, this.plugin_, window); new ViewportScroller(this.viewport_, this.plugin_, window);
......
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