1 // Copyright (c) 2012 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.
5 #include "base/path_service.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "content/browser/child_process_security_policy_impl.h"
8 #include "content/browser/frame_host/render_frame_host_impl.h"
9 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
10 #include "content/common/input_messages.h"
11 #include "content/common/view_messages.h"
12 #include "content/public/browser/navigation_entry.h"
13 #include "content/public/common/bindings_policy.h"
14 #include "content/public/common/drop_data.h"
15 #include "content/public/common/page_transition_types.h"
16 #include "content/public/common/url_constants.h"
17 #include "content/public/test/mock_render_process_host.h"
18 #include "content/test/test_content_browser_client.h"
19 #include "content/test/test_render_view_host.h"
20 #include "content/test/test_web_contents.h"
21 #include "net/base/filename_util.h"
22 #include "third_party/WebKit/public/web/WebDragOperation.h"
26 class RenderViewHostTestBrowserClient
: public TestContentBrowserClient
{
28 RenderViewHostTestBrowserClient() {}
29 virtual ~RenderViewHostTestBrowserClient() {}
31 virtual bool IsHandledURL(const GURL
& url
) OVERRIDE
{
32 return url
.scheme() == kFileScheme
;
36 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestBrowserClient
);
39 class RenderViewHostTest
: public RenderViewHostImplTestHarness
{
41 RenderViewHostTest() : old_browser_client_(NULL
) {}
42 virtual ~RenderViewHostTest() {}
44 virtual void SetUp() OVERRIDE
{
45 RenderViewHostImplTestHarness::SetUp();
46 old_browser_client_
= SetBrowserClientForTesting(&test_browser_client_
);
49 virtual void TearDown() OVERRIDE
{
50 SetBrowserClientForTesting(old_browser_client_
);
51 RenderViewHostImplTestHarness::TearDown();
55 RenderViewHostTestBrowserClient test_browser_client_
;
56 ContentBrowserClient
* old_browser_client_
;
58 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTest
);
61 // All about URLs reported by the renderer should get rewritten to about:blank.
62 // See RenderViewHost::OnNavigate for a discussion.
63 TEST_F(RenderViewHostTest
, FilterAbout
) {
64 test_rvh()->SendNavigate(1, GURL("about:cache"));
65 ASSERT_TRUE(controller().GetVisibleEntry());
66 EXPECT_EQ(GURL(kAboutBlankURL
), controller().GetVisibleEntry()->GetURL());
69 // Create a full screen popup RenderWidgetHost and View.
70 TEST_F(RenderViewHostTest
, CreateFullscreenWidget
) {
71 int routing_id
= process()->GetNextRoutingID();
72 test_rvh()->CreateNewFullscreenWidget(routing_id
);
75 // Makes sure that the RenderViewHost is not waiting for an unload ack when
76 // reloading a page. If this is not the case, when reloading, the contents may
77 // get closed out even though the user pressed the reload button.
78 TEST_F(RenderViewHostTest
, ResetUnloadOnReload
) {
79 const GURL
url1("http://foo1");
80 const GURL
url2("http://foo2");
82 // This test is for a subtle timing bug. Here's the sequence that triggered
85 // . go to a new page, preferably one that takes a while to resolve, such
86 // as one on a site that doesn't exist.
87 // . After this step IsWaitingForUnloadACK returns true on the first RVH.
88 // . click stop before the page has been commited.
90 // . IsWaitingForUnloadACK still returns true, and if the hang monitor fires
91 // the contents gets closed.
93 NavigateAndCommit(url1
);
95 url2
, Referrer(), PAGE_TRANSITION_LINK
, std::string());
96 // Simulate the ClosePage call which is normally sent by the net::URLRequest.
98 // Needed so that navigations are not suspended on the RVH.
99 test_rvh()->SendBeforeUnloadACK(true);
101 controller().Reload(false);
102 EXPECT_FALSE(test_rvh()->IsWaitingForUnloadACK());
105 // Ensure we do not grant bindings to a process shared with unprivileged views.
106 TEST_F(RenderViewHostTest
, DontGrantBindingsToSharedProcess
) {
107 // Create another view in the same process.
108 scoped_ptr
<TestWebContents
> new_web_contents(
109 TestWebContents::Create(browser_context(), rvh()->GetSiteInstance()));
111 rvh()->AllowBindings(BINDINGS_POLICY_WEB_UI
);
112 EXPECT_FALSE(rvh()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI
);
115 class MockDraggingRenderViewHostDelegateView
116 : public RenderViewHostDelegateView
{
118 virtual ~MockDraggingRenderViewHostDelegateView() {}
119 virtual void StartDragging(const DropData
& drop_data
,
120 blink::WebDragOperationsMask allowed_ops
,
121 const gfx::ImageSkia
& image
,
122 const gfx::Vector2d
& image_offset
,
123 const DragEventSourceInfo
& event_info
) OVERRIDE
{
124 drag_url_
= drop_data
.url
;
125 html_base_url_
= drop_data
.html_base_url
;
127 virtual void UpdateDragCursor(blink::WebDragOperation operation
) OVERRIDE
{}
128 virtual void GotFocus() OVERRIDE
{}
129 virtual void TakeFocus(bool reverse
) OVERRIDE
{}
130 virtual void UpdatePreferredSize(const gfx::Size
& pref_size
) {}
136 GURL
html_base_url() {
137 return html_base_url_
;
145 TEST_F(RenderViewHostTest
, StartDragging
) {
146 TestWebContents
* web_contents
= contents();
147 MockDraggingRenderViewHostDelegateView delegate_view
;
148 web_contents
->set_delegate_view(&delegate_view
);
151 GURL file_url
= GURL("file:///home/user/secrets.txt");
152 drop_data
.url
= file_url
;
153 drop_data
.html_base_url
= file_url
;
154 test_rvh()->TestOnStartDragging(drop_data
);
155 EXPECT_EQ(GURL(kAboutBlankURL
), delegate_view
.drag_url());
156 EXPECT_EQ(GURL(kAboutBlankURL
), delegate_view
.html_base_url());
158 GURL http_url
= GURL("http://www.domain.com/index.html");
159 drop_data
.url
= http_url
;
160 drop_data
.html_base_url
= http_url
;
161 test_rvh()->TestOnStartDragging(drop_data
);
162 EXPECT_EQ(http_url
, delegate_view
.drag_url());
163 EXPECT_EQ(http_url
, delegate_view
.html_base_url());
165 GURL https_url
= GURL("https://www.domain.com/index.html");
166 drop_data
.url
= https_url
;
167 drop_data
.html_base_url
= https_url
;
168 test_rvh()->TestOnStartDragging(drop_data
);
169 EXPECT_EQ(https_url
, delegate_view
.drag_url());
170 EXPECT_EQ(https_url
, delegate_view
.html_base_url());
172 GURL javascript_url
= GURL("javascript:alert('I am a bookmarklet')");
173 drop_data
.url
= javascript_url
;
174 drop_data
.html_base_url
= http_url
;
175 test_rvh()->TestOnStartDragging(drop_data
);
176 EXPECT_EQ(javascript_url
, delegate_view
.drag_url());
177 EXPECT_EQ(http_url
, delegate_view
.html_base_url());
180 TEST_F(RenderViewHostTest
, DragEnteredFileURLsStillBlocked
) {
181 DropData dropped_data
;
182 gfx::Point client_point
;
183 gfx::Point screen_point
;
184 // We use "//foo/bar" path (rather than "/foo/bar") since dragged paths are
185 // expected to be absolute on any platforms.
186 base::FilePath
highlighted_file_path(FILE_PATH_LITERAL("//tmp/foo.html"));
187 base::FilePath
dragged_file_path(FILE_PATH_LITERAL("//tmp/image.jpg"));
188 base::FilePath
sensitive_file_path(FILE_PATH_LITERAL("//etc/passwd"));
189 GURL highlighted_file_url
= net::FilePathToFileURL(highlighted_file_path
);
190 GURL dragged_file_url
= net::FilePathToFileURL(dragged_file_path
);
191 GURL sensitive_file_url
= net::FilePathToFileURL(sensitive_file_path
);
192 dropped_data
.url
= highlighted_file_url
;
193 dropped_data
.filenames
.push_back(
194 ui::FileInfo(dragged_file_path
, base::FilePath()));
196 rvh()->DragTargetDragEnter(dropped_data
, client_point
, screen_point
,
197 blink::WebDragOperationNone
, 0);
199 int id
= process()->GetID();
200 ChildProcessSecurityPolicyImpl
* policy
=
201 ChildProcessSecurityPolicyImpl::GetInstance();
203 EXPECT_FALSE(policy
->CanRequestURL(id
, highlighted_file_url
));
204 EXPECT_FALSE(policy
->CanReadFile(id
, highlighted_file_path
));
205 EXPECT_TRUE(policy
->CanRequestURL(id
, dragged_file_url
));
206 EXPECT_TRUE(policy
->CanReadFile(id
, dragged_file_path
));
207 EXPECT_FALSE(policy
->CanRequestURL(id
, sensitive_file_url
));
208 EXPECT_FALSE(policy
->CanReadFile(id
, sensitive_file_path
));
211 // The test that follow trigger DCHECKS in debug build.
212 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
214 // Test that when we fail to de-serialize a message, RenderViewHost calls the
215 // ReceivedBadMessage() handler.
216 TEST_F(RenderViewHostTest
, BadMessageHandlerRenderViewHost
) {
217 EXPECT_EQ(0, process()->bad_msg_count());
218 // craft an incorrect ViewHostMsg_UpdateTargetURL message. The real one has
219 // two payload items but the one we construct has none.
220 IPC::Message
message(0, ViewHostMsg_UpdateTargetURL::ID
,
221 IPC::Message::PRIORITY_NORMAL
);
222 test_rvh()->OnMessageReceived(message
);
223 EXPECT_EQ(1, process()->bad_msg_count());
226 // Test that when we fail to de-serialize a message, RenderWidgetHost calls the
227 // ReceivedBadMessage() handler.
228 TEST_F(RenderViewHostTest
, BadMessageHandlerRenderWidgetHost
) {
229 EXPECT_EQ(0, process()->bad_msg_count());
230 // craft an incorrect ViewHostMsg_UpdateRect message. The real one has
231 // one payload item but the one we construct has none.
232 IPC::Message
message(0, ViewHostMsg_UpdateRect::ID
,
233 IPC::Message::PRIORITY_NORMAL
);
234 test_rvh()->OnMessageReceived(message
);
235 EXPECT_EQ(1, process()->bad_msg_count());
238 // Test that OnInputEventAck() detects bad messages.
239 TEST_F(RenderViewHostTest
, BadMessageHandlerInputEventAck
) {
240 EXPECT_EQ(0, process()->bad_msg_count());
241 // InputHostMsg_HandleInputEvent_ACK is defined taking 0 params but
242 // the code actually expects it to have at least one int para, this this
243 // bogus message will not fail at de-serialization but should fail in
244 // OnInputEventAck() processing.
245 IPC::Message
message(0, InputHostMsg_HandleInputEvent_ACK::ID
,
246 IPC::Message::PRIORITY_NORMAL
);
247 test_rvh()->OnMessageReceived(message
);
248 EXPECT_EQ(1, process()->bad_msg_count());
253 TEST_F(RenderViewHostTest
, MessageWithBadHistoryItemFiles
) {
254 base::FilePath file_path
;
255 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file_path
));
256 file_path
= file_path
.AppendASCII("foo");
257 EXPECT_EQ(0, process()->bad_msg_count());
258 test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path
);
259 EXPECT_EQ(1, process()->bad_msg_count());
261 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
262 process()->GetID(), file_path
);
263 test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path
);
264 EXPECT_EQ(1, process()->bad_msg_count());
267 TEST_F(RenderViewHostTest
, NavigationWithBadHistoryItemFiles
) {
268 GURL
url("http://www.google.com");
269 base::FilePath file_path
;
270 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file_path
));
271 file_path
= file_path
.AppendASCII("bar");
272 EXPECT_EQ(0, process()->bad_msg_count());
273 test_rvh()->SendNavigateWithFile(1, url
, file_path
);
274 EXPECT_EQ(1, process()->bad_msg_count());
276 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
277 process()->GetID(), file_path
);
278 test_rvh()->SendNavigateWithFile(process()->GetID(), url
, file_path
);
279 EXPECT_EQ(1, process()->bad_msg_count());
282 TEST_F(RenderViewHostTest
, RoutingIdSane
) {
283 RenderFrameHostImpl
* root_rfh
=
284 contents()->GetFrameTree()->root()->current_frame_host();
285 EXPECT_EQ(test_rvh()->GetProcess(), root_rfh
->GetProcess());
286 EXPECT_NE(test_rvh()->GetRoutingID(), root_rfh
->routing_id());
289 } // namespace content