Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_view_host_unittest.cc
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.
4
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/common/input_messages.h"
10 #include "content/common/view_messages.h"
11 #include "content/port/browser/render_view_host_delegate_view.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/net_util.h"
22 #include "third_party/WebKit/public/web/WebDragOperation.h"
23
24 namespace content {
25
26 class RenderViewHostTestBrowserClient : public TestContentBrowserClient {
27  public:
28   RenderViewHostTestBrowserClient() {}
29   virtual ~RenderViewHostTestBrowserClient() {}
30
31   virtual bool IsHandledURL(const GURL& url) OVERRIDE {
32     return url.scheme() == kFileScheme;
33   }
34
35  private:
36   DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestBrowserClient);
37 };
38
39 class RenderViewHostTest : public RenderViewHostImplTestHarness {
40  public:
41   RenderViewHostTest() : old_browser_client_(NULL) {}
42   virtual ~RenderViewHostTest() {}
43
44   virtual void SetUp() OVERRIDE {
45     RenderViewHostImplTestHarness::SetUp();
46     old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
47   }
48
49   virtual void TearDown() OVERRIDE {
50     SetBrowserClientForTesting(old_browser_client_);
51     RenderViewHostImplTestHarness::TearDown();
52   }
53
54  private:
55   RenderViewHostTestBrowserClient test_browser_client_;
56   ContentBrowserClient* old_browser_client_;
57
58   DISALLOW_COPY_AND_ASSIGN(RenderViewHostTest);
59 };
60
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());
67 }
68
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);
73 }
74
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");
81
82   // This test is for a subtle timing bug. Here's the sequence that triggered
83   // the bug:
84   // . go to a page.
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.
89   // . click reload.
90   //   . IsWaitingForUnloadACK still returns true, and if the hang monitor fires
91   //     the contents gets closed.
92
93   NavigateAndCommit(url1);
94   controller().LoadURL(
95       url2, Referrer(), PAGE_TRANSITION_LINK, std::string());
96   // Simulate the ClosePage call which is normally sent by the net::URLRequest.
97   rvh()->ClosePage();
98   // Needed so that navigations are not suspended on the RVH.
99   test_rvh()->SendShouldCloseACK(true);
100   contents()->Stop();
101   controller().Reload(false);
102   EXPECT_FALSE(test_rvh()->IsWaitingForUnloadACK());
103 }
104
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()));
110
111   rvh()->AllowBindings(BINDINGS_POLICY_WEB_UI);
112   EXPECT_FALSE(rvh()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
113 }
114
115 class MockDraggingRenderViewHostDelegateView
116     : public RenderViewHostDelegateView {
117  public:
118   virtual ~MockDraggingRenderViewHostDelegateView() {}
119   virtual void ShowPopupMenu(const gfx::Rect& bounds,
120                              int item_height,
121                              double item_font_size,
122                              int selected_item,
123                              const std::vector<MenuItem>& items,
124                              bool right_aligned,
125                              bool allow_multiple_selection) OVERRIDE {}
126   virtual void StartDragging(const DropData& drop_data,
127                              blink::WebDragOperationsMask allowed_ops,
128                              const gfx::ImageSkia& image,
129                              const gfx::Vector2d& image_offset,
130                              const DragEventSourceInfo& event_info) OVERRIDE {
131     drag_url_ = drop_data.url;
132     html_base_url_ = drop_data.html_base_url;
133   }
134   virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE {}
135   virtual void GotFocus() OVERRIDE {}
136   virtual void TakeFocus(bool reverse) OVERRIDE {}
137   virtual void UpdatePreferredSize(const gfx::Size& pref_size) {}
138
139   GURL drag_url() {
140     return drag_url_;
141   }
142
143   GURL html_base_url() {
144     return html_base_url_;
145   }
146
147  private:
148   GURL drag_url_;
149   GURL html_base_url_;
150 };
151
152 TEST_F(RenderViewHostTest, StartDragging) {
153   TestWebContents* web_contents = contents();
154   MockDraggingRenderViewHostDelegateView delegate_view;
155   web_contents->set_delegate_view(&delegate_view);
156
157   DropData drop_data;
158   GURL file_url = GURL("file:///home/user/secrets.txt");
159   drop_data.url = file_url;
160   drop_data.html_base_url = file_url;
161   test_rvh()->TestOnStartDragging(drop_data);
162   EXPECT_EQ(GURL(kAboutBlankURL), delegate_view.drag_url());
163   EXPECT_EQ(GURL(kAboutBlankURL), delegate_view.html_base_url());
164
165   GURL http_url = GURL("http://www.domain.com/index.html");
166   drop_data.url = http_url;
167   drop_data.html_base_url = http_url;
168   test_rvh()->TestOnStartDragging(drop_data);
169   EXPECT_EQ(http_url, delegate_view.drag_url());
170   EXPECT_EQ(http_url, delegate_view.html_base_url());
171
172   GURL https_url = GURL("https://www.domain.com/index.html");
173   drop_data.url = https_url;
174   drop_data.html_base_url = https_url;
175   test_rvh()->TestOnStartDragging(drop_data);
176   EXPECT_EQ(https_url, delegate_view.drag_url());
177   EXPECT_EQ(https_url, delegate_view.html_base_url());
178
179   GURL javascript_url = GURL("javascript:alert('I am a bookmarklet')");
180   drop_data.url = javascript_url;
181   drop_data.html_base_url = http_url;
182   test_rvh()->TestOnStartDragging(drop_data);
183   EXPECT_EQ(javascript_url, delegate_view.drag_url());
184   EXPECT_EQ(http_url, delegate_view.html_base_url());
185 }
186
187 TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
188   DropData dropped_data;
189   gfx::Point client_point;
190   gfx::Point screen_point;
191   // We use "//foo/bar" path (rather than "/foo/bar") since dragged paths are
192   // expected to be absolute on any platforms.
193   base::FilePath highlighted_file_path(FILE_PATH_LITERAL("//tmp/foo.html"));
194   base::FilePath dragged_file_path(FILE_PATH_LITERAL("//tmp/image.jpg"));
195   base::FilePath sensitive_file_path(FILE_PATH_LITERAL("//etc/passwd"));
196   GURL highlighted_file_url = net::FilePathToFileURL(highlighted_file_path);
197   GURL dragged_file_url = net::FilePathToFileURL(dragged_file_path);
198   GURL sensitive_file_url = net::FilePathToFileURL(sensitive_file_path);
199   dropped_data.url = highlighted_file_url;
200   dropped_data.filenames.push_back(DropData::FileInfo(
201       base::UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), base::string16()));
202
203   rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point,
204                               blink::WebDragOperationNone, 0);
205
206   int id = process()->GetID();
207   ChildProcessSecurityPolicyImpl* policy =
208       ChildProcessSecurityPolicyImpl::GetInstance();
209
210   EXPECT_FALSE(policy->CanRequestURL(id, highlighted_file_url));
211   EXPECT_FALSE(policy->CanReadFile(id, highlighted_file_path));
212   EXPECT_TRUE(policy->CanRequestURL(id, dragged_file_url));
213   EXPECT_TRUE(policy->CanReadFile(id, dragged_file_path));
214   EXPECT_FALSE(policy->CanRequestURL(id, sensitive_file_url));
215   EXPECT_FALSE(policy->CanReadFile(id, sensitive_file_path));
216 }
217
218 // The test that follow trigger DCHECKS in debug build.
219 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
220
221 // Test that when we fail to de-serialize a message, RenderViewHost calls the
222 // ReceivedBadMessage() handler.
223 TEST_F(RenderViewHostTest, BadMessageHandlerRenderViewHost) {
224   EXPECT_EQ(0, process()->bad_msg_count());
225   // craft an incorrect ViewHostMsg_UpdateTargetURL message. The real one has
226   // two payload items but the one we construct has none.
227   IPC::Message message(0, ViewHostMsg_UpdateTargetURL::ID,
228                        IPC::Message::PRIORITY_NORMAL);
229   test_rvh()->OnMessageReceived(message);
230   EXPECT_EQ(1, process()->bad_msg_count());
231 }
232
233 // Test that when we fail to de-serialize a message, RenderWidgetHost calls the
234 // ReceivedBadMessage() handler.
235 TEST_F(RenderViewHostTest, BadMessageHandlerRenderWidgetHost) {
236   EXPECT_EQ(0, process()->bad_msg_count());
237   // craft an incorrect ViewHostMsg_UpdateRect message. The real one has
238   // one payload item but the one we construct has none.
239   IPC::Message message(0, ViewHostMsg_UpdateRect::ID,
240                        IPC::Message::PRIORITY_NORMAL);
241   test_rvh()->OnMessageReceived(message);
242   EXPECT_EQ(1, process()->bad_msg_count());
243 }
244
245 // Test that OnInputEventAck() detects bad messages.
246 TEST_F(RenderViewHostTest, BadMessageHandlerInputEventAck) {
247   EXPECT_EQ(0, process()->bad_msg_count());
248   // InputHostMsg_HandleInputEvent_ACK is defined taking 0 params but
249   // the code actually expects it to have at least one int para, this this
250   // bogus message will not fail at de-serialization but should fail in
251   // OnInputEventAck() processing.
252   IPC::Message message(0, InputHostMsg_HandleInputEvent_ACK::ID,
253                        IPC::Message::PRIORITY_NORMAL);
254   test_rvh()->OnMessageReceived(message);
255   EXPECT_EQ(1, process()->bad_msg_count());
256 }
257
258 #endif
259
260 TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
261   base::FilePath file_path;
262   EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
263   file_path = file_path.AppendASCII("foo");
264   EXPECT_EQ(0, process()->bad_msg_count());
265   test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
266   EXPECT_EQ(1, process()->bad_msg_count());
267
268   ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
269       process()->GetID(), file_path);
270   test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
271   EXPECT_EQ(1, process()->bad_msg_count());
272 }
273
274 TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
275   GURL url("http://www.google.com");
276   base::FilePath file_path;
277   EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
278   file_path = file_path.AppendASCII("bar");
279   EXPECT_EQ(0, process()->bad_msg_count());
280   test_rvh()->SendNavigateWithFile(1, url, file_path);
281   EXPECT_EQ(1, process()->bad_msg_count());
282
283   ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
284       process()->GetID(), file_path);
285   test_rvh()->SendNavigateWithFile(process()->GetID(), url, file_path);
286   EXPECT_EQ(1, process()->bad_msg_count());
287 }
288
289 TEST_F(RenderViewHostTest, RoutingIdSane) {
290   RenderFrameHostImpl* root_rfh =
291       contents()->GetFrameTree()->root()->current_frame_host();
292   EXPECT_EQ(test_rvh()->GetProcess(), root_rfh->GetProcess());
293   EXPECT_NE(test_rvh()->GetRoutingID(), root_rfh->routing_id());
294 }
295
296 }  // namespace content