diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 19:25:58 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 19:25:58 +0000 |
commit | ae5184d682c302981920f45b580b5a306fc957f9 (patch) | |
tree | 5374e7d63121d44649ab87f3a1c4571bb0ed33ba | |
parent | 7bc551f6363486b7ea6f004d1404304f7f69a7e0 (diff) | |
download | chromium_src-ae5184d682c302981920f45b580b5a306fc957f9.zip chromium_src-ae5184d682c302981920f45b580b5a306fc957f9.tar.gz chromium_src-ae5184d682c302981920f45b580b5a306fc957f9.tar.bz2 |
Hook into another code path that lets the renderer request a new tab to be created
BUG=96877
TEST=browser_tests:ExtensionApiTest.WebNavigationRequestOpenTab
Review URL: http://codereview.chromium.org/8055011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104346 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 236 insertions, 22 deletions
diff --git a/chrome/browser/extensions/extension_webnavigation_api.cc b/chrome/browser/extensions/extension_webnavigation_api.cc index 66643ee..b675871 100644 --- a/chrome/browser/extensions/extension_webnavigation_api.cc +++ b/chrome/browser/extensions/extension_webnavigation_api.cc @@ -576,6 +576,35 @@ void ExtensionWebNavigationTabObserver::DidFinishLoad( frame_id); } +void ExtensionWebNavigationTabObserver::DidOpenRequestedURL( + TabContents* new_contents, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition, + int64 source_frame_id) { + if (!navigation_state_.CanSendEvents(source_frame_id)) + return; + + // We only send the onCreatedNavigationTarget if we end up creating a new + // window. + if (disposition != SINGLETON_TAB && + disposition != NEW_FOREGROUND_TAB && + disposition != NEW_BACKGROUND_TAB && + disposition != NEW_POPUP && + disposition != NEW_WINDOW && + disposition != OFF_THE_RECORD) + return; + + DispatchOnCreatedNavigationTarget( + tab_contents(), + new_contents->browser_context(), + source_frame_id, + navigation_state_.IsMainFrame(source_frame_id), + new_contents, + url); +} + void ExtensionWebNavigationTabObserver::TabContentsDestroyed( TabContents* tab) { g_tab_observer.Get().erase(tab); diff --git a/chrome/browser/extensions/extension_webnavigation_api.h b/chrome/browser/extensions/extension_webnavigation_api.h index 92d0985..932734f 100644 --- a/chrome/browser/extensions/extension_webnavigation_api.h +++ b/chrome/browser/extensions/extension_webnavigation_api.h @@ -148,6 +148,12 @@ class ExtensionWebNavigationTabObserver : public TabContentsObserver { int error_code) OVERRIDE; virtual void DocumentLoadedInFrame(int64 frame_id) OVERRIDE; virtual void DidFinishLoad(int64 frame_id) OVERRIDE; + virtual void DidOpenRequestedURL(TabContents* new_contents, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition, + int64 source_frame_id) OVERRIDE; virtual void TabContentsDestroyed(TabContents* tab) OVERRIDE; private: diff --git a/chrome/browser/extensions/extension_webnavigation_apitest.cc b/chrome/browser/extensions/extension_webnavigation_apitest.cc index 1996e28..22fb035 100644 --- a/chrome/browser/extensions/extension_webnavigation_apitest.cc +++ b/chrome/browser/extensions/extension_webnavigation_apitest.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" @@ -12,9 +11,11 @@ #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "net/base/mock_host_resolver.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" #include "webkit/glue/context_menu.h" namespace { @@ -147,3 +148,34 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationUserAction) { ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); } + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationRequestOpenTab) { + FrameNavigationState::set_allow_extension_scheme(true); + + // Wait for the extension to set itself up and return control to us. + ASSERT_TRUE(RunExtensionSubtest("webnavigation", "test_requestOpenTab.html")) + << message_; + + ResultCatcher catcher; + + ExtensionService* service = browser()->profile()->GetExtensionService(); + const Extension* extension = + service->GetExtensionById(last_loaded_extension_id_, false); + GURL url = extension->GetResourceURL("requestOpenTab/a.html"); + + ui_test_utils::NavigateToURL(browser(), url); + + // There's a link on a.html. Middle-click on it to open it in a new tab. + WebKit::WebMouseEvent mouse_event; + mouse_event.type = WebKit::WebInputEvent::MouseDown; + mouse_event.button = WebKit::WebMouseEvent::ButtonMiddle; + mouse_event.x = 7; + mouse_event.y = 7; + mouse_event.clickCount = 1; + TabContents* tab = browser()->GetSelectedTabContents(); + tab->render_view_host()->ForwardMouseEvent(mouse_event); + mouse_event.type = WebKit::WebInputEvent::MouseUp; + tab->render_view_host()->ForwardMouseEvent(mouse_event); + + ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); +} diff --git a/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/a.html b/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/a.html new file mode 100644 index 0000000..6473d89 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/a.html @@ -0,0 +1,11 @@ +<html><head> +<style type="text/css"> +body { + margin: 0; +} +</style> +</head> +<body> +<a href="b.html">link</a> +</body> +</html> diff --git a/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/b.html b/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/b.html new file mode 100644 index 0000000..18ecdcb --- /dev/null +++ b/chrome/test/data/extensions/api_test/webnavigation/requestOpenTab/b.html @@ -0,0 +1 @@ +<html></html> diff --git a/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.html b/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.html new file mode 100644 index 0000000..fadbdba --- /dev/null +++ b/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.html @@ -0,0 +1,5 @@ +<script src="test_requestOpenTab.js"></script> +<script src="framework.js"></script> +<script> + runTests(); +</script> diff --git a/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.js b/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.js new file mode 100644 index 0000000..4301571 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webnavigation/test_requestOpenTab.js @@ -0,0 +1,84 @@ +// Copyright (c) 2011 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. + +function runTests() { + var getURL = chrome.extension.getURL; + chrome.tabs.create({"url": "about:blank"}, function(tab) { + var tabId = tab.id; + + chrome.test.runTests([ + // Opens a tab and waits for the user to middle-click on a link in it. + function requestOpenTab() { + expect([ + { label: "a-onBeforeNavigate", + event: "onBeforeNavigate", + details: { frameId: 0, + tabId: 0, + timeStamp: 0, + url: getURL('requestOpenTab/a.html') }}, + { label: "a-onCommitted", + event: "onCommitted", + details: { frameId: 0, + tabId: 0, + timeStamp: 0, + transitionQualifiers: [], + transitionType: "typed", + url: getURL('requestOpenTab/a.html') }}, + { label: "a-onDOMContentLoaded", + event: "onDOMContentLoaded", + details: { frameId: 0, + tabId: 0, + timeStamp: 0, + url: getURL('requestOpenTab/a.html') }}, + { label: "a-onCompleted", + event: "onCompleted", + details: { frameId: 0, + tabId: 0, + timeStamp: 0, + url: getURL('requestOpenTab/a.html') }}, + { label: "b-onCreatedNavigationTarget", + event: "onCreatedNavigationTarget", + details: { sourceFrameId: 0, + sourceTabId: 0, + tabId: 1, + timeStamp: 0, + url: getURL('requestOpenTab/b.html') }}, + { label: "b-onBeforeNavigate", + event: "onBeforeNavigate", + details: { frameId: 0, + tabId: 1, + timeStamp: 0, + url: getURL('requestOpenTab/b.html') }}, + { label: "b-onCommitted", + event: "onCommitted", + details: { frameId: 0, + tabId: 1, + timeStamp: 0, + transitionQualifiers: [], + transitionType: "link", + url: getURL('requestOpenTab/b.html') }}, + { label: "b-onDOMContentLoaded", + event: "onDOMContentLoaded", + details: { frameId: 0, + tabId: 1, + timeStamp: 0, + url: getURL('requestOpenTab/b.html') }}, + { label: "b-onCompleted", + event: "onCompleted", + details: { frameId: 0, + tabId: 1, + timeStamp: 0, + url: getURL('requestOpenTab/b.html') }}], + [ navigationOrder("a-"), + navigationOrder("b-"), + [ "a-onDOMContentLoaded", + "b-onCreatedNavigationTarget", + "b-onBeforeNavigate" ]]); + + // Notify the api test that we're waiting for the user. + chrome.test.notifyPass(); + }, + ]); + }); +} diff --git a/content/browser/renderer_host/render_view_host.cc b/content/browser/renderer_host/render_view_host.cc index c797151..f2b1a76 100644 --- a/content/browser/renderer_host/render_view_host.cc +++ b/content/browser/renderer_host/render_view_host.cc @@ -951,12 +951,14 @@ void RenderViewHost::OnMsgToggleFullscreen(bool enter_fullscreen) { void RenderViewHost::OnMsgOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) { + WindowOpenDisposition disposition, + int64 source_frame_id) { GURL validated_url(url); FilterURL(ChildProcessSecurityPolicy::GetInstance(), process()->id(), &validated_url); - delegate_->RequestOpenURL(validated_url, referrer, disposition); + delegate_->RequestOpenURL( + validated_url, referrer, disposition, source_frame_id); } void RenderViewHost::OnMsgDidContentsPreferredSizeChange( diff --git a/content/browser/renderer_host/render_view_host.h b/content/browser/renderer_host/render_view_host.h index ef541c8..d29b8e4 100644 --- a/content/browser/renderer_host/render_view_host.h +++ b/content/browser/renderer_host/render_view_host.h @@ -490,8 +490,10 @@ class CONTENT_EXPORT RenderViewHost : public RenderWidgetHost { void OnMsgDocumentOnLoadCompletedInMainFrame(int32 page_id); void OnMsgContextMenu(const ContextMenuParams& params); void OnMsgToggleFullscreen(bool enter_fullscreen); - void OnMsgOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition); + void OnMsgOpenURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id); void OnMsgDidContentsPreferredSizeChange(const gfx::Size& new_size); void OnMsgDidChangeScrollbarsForMainFrame(bool has_horizontal_scrollbar, bool has_vertical_scrollbar); diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 65bb4ac..c86dc34 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -283,7 +283,8 @@ class CONTENT_EXPORT RenderViewHostDelegate : public IPC::Channel::Listener { // The page wants to open a URL with the specified disposition. virtual void RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) {} + WindowOpenDisposition disposition, + int64 source_frame_id) {} // A javascript message, confirmation or prompt should be shown. virtual void RunJavaScriptMessage(const RenderViewHost* rvh, diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 2d3cf8d..5d809cc 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -1675,8 +1675,12 @@ void TabContents::DocumentOnLoadCompletedInMainFrame( Details<int>(&page_id)); } -void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) { +void TabContents::RequestOpenURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id) { + TabContents* new_contents = NULL; + PageTransition::Type transition_type = PageTransition::LINK; if (render_manager_.web_ui()) { // When we're a Web UI, it will provide a page transition type for us (this // is so the new tab page can specify AUTO_BOOKMARK for automatically @@ -1686,10 +1690,21 @@ void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer, // want web sites to see a referrer of "chrome://blah" (and some // chrome: URLs might have search terms or other stuff we don't want to // send to the site), so we send no referrer. - OpenURL(url, GURL(), disposition, + new_contents = OpenURL(url, GURL(), disposition, render_manager_.web_ui()->link_transition_type()); + transition_type = render_manager_.web_ui()->link_transition_type(); } else { - OpenURL(url, referrer, disposition, PageTransition::LINK); + new_contents = OpenURL(url, referrer, disposition, PageTransition::LINK); + } + if (new_contents) { + // Notify observers. + FOR_EACH_OBSERVER(TabContentsObserver, observers_, + DidOpenRequestedURL(new_contents, + url, + referrer, + disposition, + transition_type, + source_frame_id)); } } diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index acdefbc..8262c95 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -655,8 +655,10 @@ class CONTENT_EXPORT TabContents : public PageNavigator, virtual void DocumentOnLoadCompletedInMainFrame( RenderViewHost* render_view_host, int32 page_id) OVERRIDE; - virtual void RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) OVERRIDE; + virtual void RequestOpenURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id) OVERRIDE; virtual void RunJavaScriptMessage(const RenderViewHost* rvh, const string16& message, const string16& default_prompt, diff --git a/content/browser/tab_contents/tab_contents_observer.cc b/content/browser/tab_contents/tab_contents_observer.cc index f3b5af5..fa5ff3c 100644 --- a/content/browser/tab_contents/tab_contents_observer.cc +++ b/content/browser/tab_contents/tab_contents_observer.cc @@ -85,6 +85,14 @@ void TabContentsObserver::DidOpenURL(const GURL& url, PageTransition::Type transition) { } +void TabContentsObserver::DidOpenRequestedURL(TabContents* new_contents, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition, + int64 source_frame_id) { +} + void TabContentsObserver::AppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy) { } diff --git a/content/browser/tab_contents/tab_contents_observer.h b/content/browser/tab_contents/tab_contents_observer.h index 3d922c1..fdc157d 100644 --- a/content/browser/tab_contents/tab_contents_observer.h +++ b/content/browser/tab_contents/tab_contents_observer.h @@ -64,6 +64,13 @@ class CONTENT_EXPORT TabContentsObserver : public IPC::Channel::Listener, WindowOpenDisposition disposition, PageTransition::Type transition); + virtual void DidOpenRequestedURL(TabContents* new_contents, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition, + int64 source_frame_id); + virtual void AppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy); #if 0 diff --git a/content/common/view_messages.h b/content/common/view_messages.h index e418265..3d439b7c 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -1556,10 +1556,11 @@ IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_RunJavaScriptMessage, string16 /* out - user_input field */) // Requests that the given URL be opened in the specified manner. -IPC_MESSAGE_ROUTED3(ViewHostMsg_OpenURL, +IPC_MESSAGE_ROUTED4(ViewHostMsg_OpenURL, GURL /* url */, GURL /* referrer */, - WindowOpenDisposition /* disposition */) + WindowOpenDisposition /* disposition */, + int64 /* frame id */) // Notifies that the preferred size of the content changed. IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange, diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 34551fa..c79c567 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -1252,10 +1252,16 @@ void RenderView::UpdateSessionHistory(WebFrame* frame) { routing_id_, page_id_, webkit_glue::HistoryItemToString(item))); } -void RenderView::OpenURL( - const GURL& url, const GURL& referrer, WebNavigationPolicy policy) { +void RenderView::OpenURL(WebFrame* frame, + const GURL& url, + const GURL& referrer, + WebNavigationPolicy policy) { Send(new ViewHostMsg_OpenURL( - routing_id_, url, referrer, NavigationPolicyToDisposition(policy))); + routing_id_, + url, + referrer, + NavigationPolicyToDisposition(policy), + frame->identifier())); } // WebViewDelegate ------------------------------------------------------------ @@ -1972,7 +1978,7 @@ void RenderView::loadURLExternally( Send(new ViewHostMsg_DownloadUrl(routing_id_, request.url(), referrer, suggested_name)); } else { - OpenURL(request.url(), referrer, policy); + OpenURL(frame, request.url(), referrer, policy); } } @@ -2006,7 +2012,7 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( // navigation. page_id_ = -1; last_page_id_sent_to_browser_ = -1; - OpenURL(url, referrer, default_policy); + OpenURL(frame, url, referrer, default_policy); return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. } @@ -2050,7 +2056,7 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( if (should_fork) { GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer"))); - OpenURL(url, send_referrer ? referrer : GURL(), default_policy); + OpenURL(frame, url, send_referrer ? referrer : GURL(), default_policy); return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. } } @@ -2120,7 +2126,7 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( if (is_fork || is_noreferrer_and_blank_target) { // Open the URL via the browser, not via WebKit. - OpenURL(url, GURL(), default_policy); + OpenURL(frame, url, GURL(), default_policy); return WebKit::WebNavigationPolicyIgnore; } diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h index 536f0ff..2c16ac6 100644 --- a/content/renderer/render_view.h +++ b/content/renderer/render_view.h @@ -731,7 +731,9 @@ class RenderView : public RenderWidget, void UpdateEncoding(WebKit::WebFrame* frame, const std::string& encoding_name); - void OpenURL(const GURL& url, const GURL& referrer, + void OpenURL(WebKit::WebFrame* frame, + const GURL& url, + const GURL& referrer, WebKit::WebNavigationPolicy policy); bool RunJavaScriptMessage(int type, |