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