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_message_filter.h"
10 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
11 #include "content/browser/renderer_host/render_widget_helper.h"
12 #include "content/common/input_messages.h"
13 #include "content/common/view_messages.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/common/bindings_policy.h"
17 #include "content/public/common/drop_data.h"
18 #include "content/public/common/url_constants.h"
19 #include "content/public/test/mock_render_process_host.h"
20 #include "content/test/test_content_browser_client.h"
21 #include "content/test/test_render_view_host.h"
22 #include "content/test/test_web_contents.h"
23 #include "net/base/filename_util.h"
24 #include "third_party/WebKit/public/web/WebDragOperation.h"
25 #include "ui/base/page_transition_types.h"
29 class RenderViewHostTestBrowserClient
: public TestContentBrowserClient
{
31 RenderViewHostTestBrowserClient() {}
32 ~RenderViewHostTestBrowserClient() override
{}
34 bool IsHandledURL(const GURL
& url
) override
{
35 return url
.scheme() == url::kFileScheme
;
39 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestBrowserClient
);
42 class RenderViewHostTest
: public RenderViewHostImplTestHarness
{
44 RenderViewHostTest() : old_browser_client_(NULL
) {}
45 ~RenderViewHostTest() override
{}
47 void SetUp() override
{
48 RenderViewHostImplTestHarness::SetUp();
49 old_browser_client_
= SetBrowserClientForTesting(&test_browser_client_
);
52 void TearDown() override
{
53 SetBrowserClientForTesting(old_browser_client_
);
54 RenderViewHostImplTestHarness::TearDown();
58 RenderViewHostTestBrowserClient test_browser_client_
;
59 ContentBrowserClient
* old_browser_client_
;
61 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTest
);
64 // All about URLs reported by the renderer should get rewritten to about:blank.
65 // See RenderViewHost::OnNavigate for a discussion.
66 TEST_F(RenderViewHostTest
, FilterAbout
) {
67 contents()->GetMainFrame()->SendNavigate(1, GURL("about:cache"));
68 ASSERT_TRUE(controller().GetVisibleEntry());
69 EXPECT_EQ(GURL(url::kAboutBlankURL
),
70 controller().GetVisibleEntry()->GetURL());
73 // Create a full screen popup RenderWidgetHost and View.
74 TEST_F(RenderViewHostTest
, CreateFullscreenWidget
) {
75 int routing_id
= process()->GetNextRoutingID();
76 test_rvh()->CreateNewFullscreenWidget(routing_id
);
79 // Makes sure that the RenderViewHost is not waiting for an unload ack when
80 // reloading a page. If this is not the case, when reloading, the contents may
81 // get closed out even though the user pressed the reload button.
82 TEST_F(RenderViewHostTest
, ResetUnloadOnReload
) {
83 const GURL
url1("http://foo1");
84 const GURL
url2("http://foo2");
86 // This test is for a subtle timing bug. Here's the sequence that triggered
89 // . go to a new page, preferably one that takes a while to resolve, such
90 // as one on a site that doesn't exist.
91 // . After this step IsWaitingForUnloadACK returns true on the first RVH.
92 // . click stop before the page has been commited.
94 // . IsWaitingForUnloadACK still returns true, and if the hang monitor fires
95 // the contents gets closed.
97 NavigateAndCommit(url1
);
99 url2
, Referrer(), ui::PAGE_TRANSITION_LINK
, std::string());
100 // Simulate the ClosePage call which is normally sent by the net::URLRequest.
102 // Needed so that navigations are not suspended on the RFH.
103 main_test_rfh()->SendBeforeUnloadACK(true);
105 controller().Reload(false);
106 EXPECT_FALSE(main_test_rfh()->IsWaitingForUnloadACK());
109 // Ensure we do not grant bindings to a process shared with unprivileged views.
110 TEST_F(RenderViewHostTest
, DontGrantBindingsToSharedProcess
) {
111 // Create another view in the same process.
112 scoped_ptr
<TestWebContents
> new_web_contents(
113 TestWebContents::Create(browser_context(), rvh()->GetSiteInstance()));
115 rvh()->AllowBindings(BINDINGS_POLICY_WEB_UI
);
116 EXPECT_FALSE(rvh()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI
);
119 class MockDraggingRenderViewHostDelegateView
120 : public RenderViewHostDelegateView
{
122 ~MockDraggingRenderViewHostDelegateView() override
{}
123 void StartDragging(const DropData
& drop_data
,
124 blink::WebDragOperationsMask allowed_ops
,
125 const gfx::ImageSkia
& image
,
126 const gfx::Vector2d
& image_offset
,
127 const DragEventSourceInfo
& event_info
) override
{
128 drag_url_
= drop_data
.url
;
129 html_base_url_
= drop_data
.html_base_url
;
131 void UpdateDragCursor(blink::WebDragOperation operation
) override
{}
132 void GotFocus() override
{}
133 void TakeFocus(bool reverse
) override
{}
134 virtual void UpdatePreferredSize(const gfx::Size
& pref_size
) {}
140 GURL
html_base_url() {
141 return html_base_url_
;
149 TEST_F(RenderViewHostTest
, StartDragging
) {
150 TestWebContents
* web_contents
= contents();
151 MockDraggingRenderViewHostDelegateView delegate_view
;
152 web_contents
->set_delegate_view(&delegate_view
);
155 GURL file_url
= GURL("file:///home/user/secrets.txt");
156 drop_data
.url
= file_url
;
157 drop_data
.html_base_url
= file_url
;
158 test_rvh()->TestOnStartDragging(drop_data
);
159 EXPECT_EQ(GURL(url::kAboutBlankURL
), delegate_view
.drag_url());
160 EXPECT_EQ(GURL(url::kAboutBlankURL
), delegate_view
.html_base_url());
162 GURL http_url
= GURL("http://www.domain.com/index.html");
163 drop_data
.url
= http_url
;
164 drop_data
.html_base_url
= http_url
;
165 test_rvh()->TestOnStartDragging(drop_data
);
166 EXPECT_EQ(http_url
, delegate_view
.drag_url());
167 EXPECT_EQ(http_url
, delegate_view
.html_base_url());
169 GURL https_url
= GURL("https://www.domain.com/index.html");
170 drop_data
.url
= https_url
;
171 drop_data
.html_base_url
= https_url
;
172 test_rvh()->TestOnStartDragging(drop_data
);
173 EXPECT_EQ(https_url
, delegate_view
.drag_url());
174 EXPECT_EQ(https_url
, delegate_view
.html_base_url());
176 GURL javascript_url
= GURL("javascript:alert('I am a bookmarklet')");
177 drop_data
.url
= javascript_url
;
178 drop_data
.html_base_url
= http_url
;
179 test_rvh()->TestOnStartDragging(drop_data
);
180 EXPECT_EQ(javascript_url
, delegate_view
.drag_url());
181 EXPECT_EQ(http_url
, delegate_view
.html_base_url());
184 TEST_F(RenderViewHostTest
, DragEnteredFileURLsStillBlocked
) {
185 DropData dropped_data
;
186 gfx::Point client_point
;
187 gfx::Point screen_point
;
188 // We use "//foo/bar" path (rather than "/foo/bar") since dragged paths are
189 // expected to be absolute on any platforms.
190 base::FilePath
highlighted_file_path(FILE_PATH_LITERAL("//tmp/foo.html"));
191 base::FilePath
dragged_file_path(FILE_PATH_LITERAL("//tmp/image.jpg"));
192 base::FilePath
sensitive_file_path(FILE_PATH_LITERAL("//etc/passwd"));
193 GURL highlighted_file_url
= net::FilePathToFileURL(highlighted_file_path
);
194 GURL dragged_file_url
= net::FilePathToFileURL(dragged_file_path
);
195 GURL sensitive_file_url
= net::FilePathToFileURL(sensitive_file_path
);
196 dropped_data
.url
= highlighted_file_url
;
197 dropped_data
.filenames
.push_back(
198 ui::FileInfo(dragged_file_path
, base::FilePath()));
200 rvh()->DragTargetDragEnter(dropped_data
, client_point
, screen_point
,
201 blink::WebDragOperationNone
, 0);
203 int id
= process()->GetID();
204 ChildProcessSecurityPolicyImpl
* policy
=
205 ChildProcessSecurityPolicyImpl::GetInstance();
207 EXPECT_FALSE(policy
->CanRequestURL(id
, highlighted_file_url
));
208 EXPECT_FALSE(policy
->CanReadFile(id
, highlighted_file_path
));
209 EXPECT_TRUE(policy
->CanRequestURL(id
, dragged_file_url
));
210 EXPECT_TRUE(policy
->CanReadFile(id
, dragged_file_path
));
211 EXPECT_FALSE(policy
->CanRequestURL(id
, sensitive_file_url
));
212 EXPECT_FALSE(policy
->CanReadFile(id
, sensitive_file_path
));
215 TEST_F(RenderViewHostTest
, MessageWithBadHistoryItemFiles
) {
216 base::FilePath file_path
;
217 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file_path
));
218 file_path
= file_path
.AppendASCII("foo");
219 EXPECT_EQ(0, process()->bad_msg_count());
220 test_rvh()->TestOnUpdateStateWithFile(-1, file_path
);
221 EXPECT_EQ(1, process()->bad_msg_count());
223 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
224 process()->GetID(), file_path
);
225 test_rvh()->TestOnUpdateStateWithFile(-1, file_path
);
226 EXPECT_EQ(1, process()->bad_msg_count());
229 TEST_F(RenderViewHostTest
, NavigationWithBadHistoryItemFiles
) {
230 GURL
url("http://www.google.com");
231 base::FilePath file_path
;
232 EXPECT_TRUE(PathService::Get(base::DIR_TEMP
, &file_path
));
233 file_path
= file_path
.AppendASCII("bar");
234 EXPECT_EQ(0, process()->bad_msg_count());
235 contents()->GetMainFrame()->SendNavigateWithFile(1, url
, file_path
);
236 EXPECT_EQ(1, process()->bad_msg_count());
238 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
239 process()->GetID(), file_path
);
240 contents()->GetMainFrame()->SendNavigateWithFile(process()->GetID(), url
,
242 EXPECT_EQ(1, process()->bad_msg_count());
245 TEST_F(RenderViewHostTest
, RoutingIdSane
) {
246 RenderFrameHostImpl
* root_rfh
=
247 contents()->GetFrameTree()->root()->current_frame_host();
248 EXPECT_EQ(contents()->GetMainFrame(), root_rfh
);
249 EXPECT_EQ(test_rvh()->GetProcess(), root_rfh
->GetProcess());
250 EXPECT_NE(test_rvh()->GetRoutingID(), root_rfh
->routing_id());
253 class TestSaveImageFromDataURL
: public RenderMessageFilter
{
255 TestSaveImageFromDataURL(
256 BrowserContext
* context
)
257 : RenderMessageFilter(
261 context
->GetRequestContext(),
270 url_string_
= std::string();
271 is_downloaded_
= false;
274 std::string
& UrlString() const {
278 bool IsDownloaded() const {
279 return is_downloaded_
;
282 void Test(const std::string
& url
) {
283 OnMessageReceived(ViewHostMsg_SaveImageFromDataURL(0, url
));
287 ~TestSaveImageFromDataURL() override
{}
288 void DownloadUrl(int render_view_id
,
290 const Referrer
& referrer
,
291 const base::string16
& suggested_name
,
292 const bool use_prompt
) const override
{
293 url_string_
= url
.spec();
294 is_downloaded_
= true;
298 mutable std::string url_string_
;
299 mutable bool is_downloaded_
;
302 TEST_F(RenderViewHostTest
, SaveImageFromDataURL
) {
303 scoped_refptr
<TestSaveImageFromDataURL
> tester(
304 new TestSaveImageFromDataURL(browser_context()));
307 tester
->Test("http://non-data-url.com");
308 EXPECT_EQ(tester
->UrlString(), "");
309 EXPECT_FALSE(tester
->IsDownloaded());
311 const std::string data_url
= "data:image/gif;base64,"
312 "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
315 tester
->Test(data_url
);
316 EXPECT_EQ(tester
->UrlString(), data_url
);
317 EXPECT_TRUE(tester
->IsDownloaded());
320 } // namespace content