Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / render_view_host_unittest.cc
blob2dc55582e691df9c5e0e26830e47aaa4406df0da
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/renderer_host/test_render_view_host.h"
9 #include "content/browser/web_contents/navigation_controller_impl.h"
10 #include "content/common/input_messages.h"
11 #include "content/common/view_messages.h"
12 #include "content/port/browser/render_view_host_delegate_view.h"
13 #include "content/public/browser/navigation_entry.h"
14 #include "content/public/common/bindings_policy.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_web_contents.h"
20 #include "net/base/net_util.h"
21 #include "third_party/WebKit/public/web/WebDragOperation.h"
22 #include "webkit/common/webdropdata.h"
24 namespace content {
26 class RenderViewHostTestBrowserClient : public TestContentBrowserClient {
27 public:
28 RenderViewHostTestBrowserClient() {}
29 virtual ~RenderViewHostTestBrowserClient() {}
31 virtual bool IsHandledURL(const GURL& url) OVERRIDE {
32 return url.scheme() == chrome::kFileScheme;
35 private:
36 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestBrowserClient);
39 class RenderViewHostTest : public RenderViewHostImplTestHarness {
40 public:
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();
54 private:
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().GetActiveEntry());
66 EXPECT_EQ(GURL("about:blank"), controller().GetActiveEntry()->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 RenderViewHost::is_waiting_for_unload_ack_ is false when
76 // reloading a page. If is_waiting_for_unload_ack_ is not false when reloading
77 // the contents may get closed out even though the user pressed the reload
78 // button.
79 TEST_F(RenderViewHostTest, ResetUnloadOnReload) {
80 const GURL url1("http://foo1");
81 const GURL url2("http://foo2");
83 // This test is for a subtle timing bug. Here's the sequence that triggered
84 // the bug:
85 // . go to a page.
86 // . go to a new page, preferably one that takes a while to resolve, such
87 // as one on a site that doesn't exist.
88 // . After this step is_waiting_for_unload_ack_ has been set to true on
89 // the first RVH.
90 // . click stop before the page has been commited.
91 // . click reload.
92 // . is_waiting_for_unload_ack_ is still true, and the if the hang monitor
93 // fires the contents gets closed.
95 NavigateAndCommit(url1);
96 controller().LoadURL(
97 url2, Referrer(), PAGE_TRANSITION_LINK, std::string());
98 // Simulate the ClosePage call which is normally sent by the net::URLRequest.
99 rvh()->ClosePage();
100 // Needed so that navigations are not suspended on the RVH.
101 test_rvh()->SendShouldCloseACK(true);
102 contents()->Stop();
103 controller().Reload(false);
104 EXPECT_FALSE(test_rvh()->is_waiting_for_unload_ack());
107 // Ensure we do not grant bindings to a process shared with unprivileged views.
108 TEST_F(RenderViewHostTest, DontGrantBindingsToSharedProcess) {
109 // Create another view in the same process.
110 scoped_ptr<TestWebContents> new_web_contents(
111 TestWebContents::Create(browser_context(), rvh()->GetSiteInstance()));
113 rvh()->AllowBindings(BINDINGS_POLICY_WEB_UI);
114 EXPECT_FALSE(rvh()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
117 class MockDraggingRenderViewHostDelegateView
118 : public RenderViewHostDelegateView {
119 public:
120 virtual ~MockDraggingRenderViewHostDelegateView() {}
121 virtual void ShowPopupMenu(const gfx::Rect& bounds,
122 int item_height,
123 double item_font_size,
124 int selected_item,
125 const std::vector<WebMenuItem>& items,
126 bool right_aligned,
127 bool allow_multiple_selection) OVERRIDE {}
128 virtual void StartDragging(const WebDropData& drop_data,
129 WebKit::WebDragOperationsMask allowed_ops,
130 const gfx::ImageSkia& image,
131 const gfx::Vector2d& image_offset,
132 const DragEventSourceInfo& event_info) OVERRIDE {
133 drag_url_ = drop_data.url;
134 html_base_url_ = drop_data.html_base_url;
136 virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE {}
137 virtual void GotFocus() OVERRIDE {}
138 virtual void TakeFocus(bool reverse) OVERRIDE {}
139 virtual void UpdatePreferredSize(const gfx::Size& pref_size) {}
141 GURL drag_url() {
142 return drag_url_;
145 GURL html_base_url() {
146 return html_base_url_;
149 private:
150 GURL drag_url_;
151 GURL html_base_url_;
154 TEST_F(RenderViewHostTest, StartDragging) {
155 TestWebContents* web_contents = contents();
156 MockDraggingRenderViewHostDelegateView delegate_view;
157 web_contents->set_delegate_view(&delegate_view);
159 WebDropData drop_data;
160 GURL file_url = GURL("file:///home/user/secrets.txt");
161 drop_data.url = file_url;
162 drop_data.html_base_url = file_url;
163 test_rvh()->TestOnStartDragging(drop_data);
164 EXPECT_EQ(GURL("about:blank"), delegate_view.drag_url());
165 EXPECT_EQ(GURL("about:blank"), delegate_view.html_base_url());
167 GURL http_url = GURL("http://www.domain.com/index.html");
168 drop_data.url = http_url;
169 drop_data.html_base_url = http_url;
170 test_rvh()->TestOnStartDragging(drop_data);
171 EXPECT_EQ(http_url, delegate_view.drag_url());
172 EXPECT_EQ(http_url, delegate_view.html_base_url());
174 GURL https_url = GURL("https://www.domain.com/index.html");
175 drop_data.url = https_url;
176 drop_data.html_base_url = https_url;
177 test_rvh()->TestOnStartDragging(drop_data);
178 EXPECT_EQ(https_url, delegate_view.drag_url());
179 EXPECT_EQ(https_url, delegate_view.html_base_url());
181 GURL javascript_url = GURL("javascript:alert('I am a bookmarklet')");
182 drop_data.url = javascript_url;
183 drop_data.html_base_url = http_url;
184 test_rvh()->TestOnStartDragging(drop_data);
185 EXPECT_EQ(javascript_url, delegate_view.drag_url());
186 EXPECT_EQ(http_url, delegate_view.html_base_url());
189 TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
190 WebDropData dropped_data;
191 gfx::Point client_point;
192 gfx::Point screen_point;
193 // We use "//foo/bar" path (rather than "/foo/bar") since dragged paths are
194 // expected to be absolute on any platforms.
195 base::FilePath highlighted_file_path(FILE_PATH_LITERAL("//tmp/foo.html"));
196 base::FilePath dragged_file_path(FILE_PATH_LITERAL("//tmp/image.jpg"));
197 base::FilePath sensitive_file_path(FILE_PATH_LITERAL("//etc/passwd"));
198 GURL highlighted_file_url = net::FilePathToFileURL(highlighted_file_path);
199 GURL dragged_file_url = net::FilePathToFileURL(dragged_file_path);
200 GURL sensitive_file_url = net::FilePathToFileURL(sensitive_file_path);
201 dropped_data.url = highlighted_file_url;
202 dropped_data.filenames.push_back(WebDropData::FileInfo(
203 UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), string16()));
205 rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point,
206 WebKit::WebDragOperationNone, 0);
208 int id = process()->GetID();
209 ChildProcessSecurityPolicyImpl* policy =
210 ChildProcessSecurityPolicyImpl::GetInstance();
212 EXPECT_FALSE(policy->CanRequestURL(id, highlighted_file_url));
213 EXPECT_FALSE(policy->CanReadFile(id, highlighted_file_path));
214 EXPECT_TRUE(policy->CanRequestURL(id, dragged_file_url));
215 EXPECT_TRUE(policy->CanReadFile(id, dragged_file_path));
216 EXPECT_FALSE(policy->CanRequestURL(id, sensitive_file_url));
217 EXPECT_FALSE(policy->CanReadFile(id, sensitive_file_path));
220 // The test that follow trigger DCHECKS in debug build.
221 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
223 // Test that when we fail to de-serialize a message, RenderViewHost calls the
224 // ReceivedBadMessage() handler.
225 TEST_F(RenderViewHostTest, BadMessageHandlerRenderViewHost) {
226 EXPECT_EQ(0, process()->bad_msg_count());
227 // craft an incorrect ViewHostMsg_UpdateTargetURL message. The real one has
228 // two payload items but the one we construct has none.
229 IPC::Message message(0, ViewHostMsg_UpdateTargetURL::ID,
230 IPC::Message::PRIORITY_NORMAL);
231 test_rvh()->OnMessageReceived(message);
232 EXPECT_EQ(1, process()->bad_msg_count());
235 // Test that when we fail to de-serialize a message, RenderWidgetHost calls the
236 // ReceivedBadMessage() handler.
237 TEST_F(RenderViewHostTest, BadMessageHandlerRenderWidgetHost) {
238 EXPECT_EQ(0, process()->bad_msg_count());
239 // craft an incorrect ViewHostMsg_UpdateRect message. The real one has
240 // one payload item but the one we construct has none.
241 IPC::Message message(0, ViewHostMsg_UpdateRect::ID,
242 IPC::Message::PRIORITY_NORMAL);
243 test_rvh()->OnMessageReceived(message);
244 EXPECT_EQ(1, process()->bad_msg_count());
247 // Test that OnInputEventAck() detects bad messages.
248 TEST_F(RenderViewHostTest, BadMessageHandlerInputEventAck) {
249 EXPECT_EQ(0, process()->bad_msg_count());
250 // InputHostMsg_HandleInputEvent_ACK is defined taking 0 params but
251 // the code actually expects it to have at least one int para, this this
252 // bogus message will not fail at de-serialization but should fail in
253 // OnInputEventAck() processing.
254 IPC::Message message(0, InputHostMsg_HandleInputEvent_ACK::ID,
255 IPC::Message::PRIORITY_NORMAL);
256 test_rvh()->OnMessageReceived(message);
257 EXPECT_EQ(1, process()->bad_msg_count());
260 #endif
262 TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
263 base::FilePath file_path;
264 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
265 file_path = file_path.AppendASCII("foo");
266 EXPECT_EQ(0, process()->bad_msg_count());
267 test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
268 EXPECT_EQ(1, process()->bad_msg_count());
270 ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile(
271 process()->GetID(), file_path,
272 base::PLATFORM_FILE_OPEN |
273 base::PLATFORM_FILE_READ |
274 base::PLATFORM_FILE_EXCLUSIVE_READ |
275 base::PLATFORM_FILE_ASYNC);
276 test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
277 EXPECT_EQ(1, process()->bad_msg_count());
280 TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
281 GURL url("http://www.google.com");
282 base::FilePath file_path;
283 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
284 file_path = file_path.AppendASCII("bar");
285 EXPECT_EQ(0, process()->bad_msg_count());
286 test_rvh()->SendNavigateWithFile(1, url, file_path);
287 EXPECT_EQ(1, process()->bad_msg_count());
289 ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile(
290 process()->GetID(), file_path,
291 base::PLATFORM_FILE_OPEN |
292 base::PLATFORM_FILE_READ |
293 base::PLATFORM_FILE_EXCLUSIVE_READ |
294 base::PLATFORM_FILE_ASYNC);
295 test_rvh()->SendNavigateWithFile(process()->GetID(), url, file_path);
296 EXPECT_EQ(1, process()->bad_msg_count());
299 } // namespace content