OLD | NEW |
---|---|
(Empty) | |
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/memory/singleton.h" | |
6 #include "base/run_loop.h" | |
7 #include "base/utf_string_conversions.h" | |
8 #include "content/browser/browser_plugin/browser_plugin_guest.h" | |
9 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" | |
10 #include "content/browser/browser_plugin/test_browser_plugin_embedder.h" | |
11 #include "content/browser/browser_plugin/test_browser_plugin_guest.h" | |
12 #include "content/browser/browser_plugin/test_timeout_tracker.h" | |
13 #include "content/browser/renderer_host/render_view_host_impl.h" | |
14 #include "content/browser/web_contents/web_contents_impl.h" | |
15 #include "content/common/view_messages.h" | |
16 #include "content/public/browser/notification_service.h" | |
17 #include "content/public/browser/notification_types.h" | |
18 #include "content/public/test/browser_test_utils.h" | |
19 #include "content/public/test/test_utils.h" | |
20 #include "content/shell/shell.h" | |
21 #include "content/test/content_browser_test_utils.h" | |
22 #include "content/test/content_browser_test.h" | |
23 #include "ipc/ipc_message.h" | |
24 #include "net/base/net_util.h" | |
25 #include "net/test/test_server.h" | |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | |
27 | |
28 using WebKit::WebInputEvent; | |
29 using WebKit::WebMouseEvent; | |
30 using content::BrowserPluginEmbedder; | |
31 using content::BrowserPluginGuest; | |
32 using content::BrowserPluginHostFactory; | |
33 | |
34 namespace content { | |
35 | |
36 const char* kHTMLForGuest = | |
37 "data:text/html,<html><body>hello world</body></html>"; | |
38 | |
39 // Test factory for creating test instances of BrowserPluginEmbedder and | |
40 // BrowserPluginGuest. | |
41 class TestBrowserPluginHostFactory : public BrowserPluginHostFactory { | |
42 public: | |
43 virtual BrowserPluginGuest* CreateBrowserPluginGuest( | |
44 int instance_id, | |
45 WebContentsImpl* web_contents, | |
46 RenderViewHost* render_view_host) OVERRIDE { | |
47 return new TestBrowserPluginGuest(instance_id, | |
48 web_contents, | |
49 render_view_host); | |
50 } | |
51 | |
52 // Also keeps track of number of instances created. | |
53 virtual BrowserPluginEmbedder* CreateBrowserPluginEmbedder( | |
54 WebContentsImpl* web_contents, | |
55 RenderViewHost* render_view_host) OVERRIDE { | |
56 embedder_instance_count_++; | |
57 if (message_loop_runner_) | |
58 message_loop_runner_->Quit(); | |
59 | |
60 return new TestBrowserPluginEmbedder(web_contents, render_view_host); | |
61 } | |
62 | |
63 // Singleton getter. | |
64 static TestBrowserPluginHostFactory* GetInstance() { | |
65 return Singleton<TestBrowserPluginHostFactory>::get(); | |
66 } | |
67 | |
68 // Waits for at least one embedder to be created in the test. Returns true if | |
69 // we have a guest, false if waiting times out. | |
70 bool WaitForEmbedderCreation() { | |
71 // Check if already have created instance. | |
72 if (embedder_instance_count_ > 0) | |
73 return true; | |
74 // Wait otherwise. | |
75 message_loop_runner_ = new MessageLoopRunner(); | |
76 return TestTimeoutTracker::RunInActionTimeout( | |
77 message_loop_runner_.get()); | |
78 } | |
79 | |
80 protected: | |
81 TestBrowserPluginHostFactory() : embedder_instance_count_(0) {} | |
82 virtual ~TestBrowserPluginHostFactory() {} | |
83 | |
84 private: | |
85 // For Singleton. | |
86 friend struct DefaultSingletonTraits<TestBrowserPluginHostFactory>; | |
87 | |
88 scoped_refptr<MessageLoopRunner> message_loop_runner_; | |
89 int embedder_instance_count_; | |
90 | |
91 DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginHostFactory); | |
92 }; | |
93 | |
94 // Test factory class for browser plugin that creates guests with short hang | |
95 // timeout. | |
96 class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory { | |
97 public: | |
98 virtual BrowserPluginGuest* CreateBrowserPluginGuest( | |
99 int instance_id, | |
100 WebContentsImpl* web_contents, | |
101 RenderViewHost* render_view_host) OVERRIDE { | |
102 BrowserPluginGuest* ret = new TestBrowserPluginGuest(instance_id, | |
Charlie Reis
2012/09/13 00:51:44
nit: ret -> guest
(ret is not a useful variable na
lazyboy
2012/09/13 15:56:24
Done.
| |
103 web_contents, | |
104 render_view_host); | |
105 ret->SetGuestHangTimeoutForTesting(TestTimeouts::tiny_timeout()); | |
106 return ret; | |
107 } | |
108 | |
109 // Singleton getter. | |
110 static TestShortHangTimeoutGuestFactory* GetInstance() { | |
111 return Singleton<TestShortHangTimeoutGuestFactory>::get(); | |
112 } | |
113 | |
114 protected: | |
115 TestShortHangTimeoutGuestFactory() {} | |
116 virtual ~TestShortHangTimeoutGuestFactory() {} | |
117 | |
118 private: | |
119 // For Singleton. | |
120 friend struct DefaultSingletonTraits<TestShortHangTimeoutGuestFactory>; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(TestShortHangTimeoutGuestFactory); | |
123 }; | |
124 | |
125 class BrowserPluginHostTest : public ContentBrowserTest { | |
126 public: | |
127 BrowserPluginHostTest() {} | |
128 | |
129 virtual void SetUp() OVERRIDE { | |
130 // Override factory to create tests instances of BrowserPlugin*. | |
131 content::BrowserPluginEmbedder::set_factory_for_testing( | |
132 TestBrowserPluginHostFactory::GetInstance()); | |
133 content::BrowserPluginGuest::set_factory_for_testing( | |
134 TestBrowserPluginHostFactory::GetInstance()); | |
135 | |
136 ContentBrowserTest::SetUp(); | |
137 } | |
138 virtual void TearDown() OVERRIDE { | |
139 content::BrowserPluginEmbedder::set_factory_for_testing(NULL); | |
140 content::BrowserPluginGuest::set_factory_for_testing(NULL); | |
141 | |
142 ContentBrowserTest::TearDown(); | |
143 } | |
144 | |
145 static void SimulateTabKeyPress(WebContents* web_contents) { | |
146 SimulateKeyPress(web_contents, | |
147 ui::VKEY_TAB, | |
148 false, // control. | |
149 false, // shift. | |
150 false, // alt. | |
151 false); // command. | |
152 } | |
153 | |
154 private: | |
155 DISALLOW_COPY_AND_ASSIGN(BrowserPluginHostTest); | |
156 }; | |
157 | |
158 // This test loads a guest that has infinite loop, therefore it hangs the guest | |
159 // and eventually gets killed. | |
160 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateGuest) { | |
161 // Override the hang timeout for guest to be very small. | |
162 content::BrowserPluginGuest::set_factory_for_testing( | |
163 TestShortHangTimeoutGuestFactory::GetInstance()); | |
164 ASSERT_TRUE(test_server()->Start()); | |
165 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html")); | |
166 NavigateToURL(shell(), test_url); | |
167 | |
168 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>( | |
169 shell()->web_contents()); | |
170 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( | |
171 embedder_web_contents->GetRenderViewHost()); | |
172 | |
173 test_url = test_server()->GetURL( | |
174 "files/browser_plugin_infinite_loop_child.html"); | |
175 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
176 StringPrintf("SetSrc('%s');", test_url.spec().c_str()))); | |
177 | |
178 // Wait to make sure embedder is created/attached to WebContents. | |
179 ASSERT_TRUE( | |
180 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation()); | |
181 | |
182 TestBrowserPluginEmbedder* test_embedder = | |
183 static_cast<TestBrowserPluginEmbedder*>( | |
184 embedder_web_contents->GetBrowserPluginEmbedder()); | |
185 ASSERT_TRUE(test_embedder); | |
186 ASSERT_TRUE(test_embedder->WaitForGuestAdded()); | |
187 | |
188 // Verify that we have exactly one guest. | |
189 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = | |
190 test_embedder->guest_web_contents_for_testing(); | |
191 EXPECT_EQ(1u, instance_map.size()); | |
192 | |
193 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( | |
194 instance_map.begin()->second); | |
195 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>( | |
196 test_guest_web_contents->GetBrowserPluginGuest()); | |
197 | |
198 // Wait for the guest to send an UpdateRectMsg, meaning it is ready. | |
199 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg()); | |
200 | |
201 // Send a mouse event to the guest. | |
202 WebKit::WebMouseEvent mouse_event; | |
203 mouse_event.type = WebInputEvent::MouseDown; | |
204 mouse_event.button = WebMouseEvent::ButtonMiddle; | |
205 mouse_event.x = 35; | |
206 mouse_event.y = 35; | |
207 mouse_event.globalX = 35; | |
208 mouse_event.globalY = 35; | |
209 | |
210 IPC::Message* input_message = new ViewMsg_HandleInputEvent( | |
211 embedder_web_contents->GetRenderViewHost()->GetRoutingID()); | |
212 input_message->WriteData(reinterpret_cast<const char*>(&mouse_event), | |
213 sizeof(WebKit::WebMouseEvent)); | |
214 embedder_web_contents->GetRenderViewHost()->Send(input_message); | |
215 | |
216 // Expect the guest to crash. | |
217 ASSERT_TRUE(test_guest->WaitForCrashed()); | |
218 } | |
219 | |
220 // This test ensures that if guest isn't there and we resize the guest (from | |
221 // js), it remembers the size correctly. | |
222 // | |
223 // Initially we load an embedder with a guest without a src attribute (which has | |
224 // dimension 640x480), then resize it to 100x200, then we set the source to a | |
225 // sample guest. In the end we verify that the correct size has been set. | |
226 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateAfterResize) { | |
227 ASSERT_TRUE(test_server()->Start()); | |
228 GURL test_url(test_server()->GetURL( | |
229 "files/browser_plugin_embedder.html")); | |
230 NavigateToURL(shell(), test_url); | |
231 | |
232 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>( | |
233 shell()->web_contents()); | |
234 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( | |
235 embedder_web_contents->GetRenderViewHost()); | |
236 | |
237 int nxt_width = 100; | |
238 int nxt_height = 200; | |
239 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
240 StringPrintf("SetSize(%d, %d);", nxt_width, nxt_height))); | |
241 | |
242 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
243 StringPrintf("SetSrc('%s');", kHTMLForGuest))); | |
244 | |
245 // Wait to make sure embedder is created/attached to WebContents. | |
246 ASSERT_TRUE( | |
247 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation()); | |
248 | |
249 TestBrowserPluginEmbedder* test_embedder = | |
250 static_cast<TestBrowserPluginEmbedder*>( | |
251 embedder_web_contents->GetBrowserPluginEmbedder()); | |
252 ASSERT_TRUE(test_embedder); | |
253 ASSERT_TRUE(test_embedder->WaitForGuestAdded()); | |
254 | |
255 // Verify that we have exactly one guest. | |
256 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = | |
257 test_embedder->guest_web_contents_for_testing(); | |
258 EXPECT_EQ(1u, instance_map.size()); | |
259 | |
260 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( | |
261 instance_map.begin()->second); | |
262 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>( | |
263 test_guest_web_contents->GetBrowserPluginGuest()); | |
264 | |
265 | |
266 // Wait for the guest to send an UpdateRectMsg, the dimensions should be | |
267 // 100 x 200. | |
268 ASSERT_TRUE(test_guest->WaitForUpdateRectMsgWithSize(nxt_width, nxt_height)); | |
269 } | |
270 | |
271 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) { | |
272 ASSERT_TRUE(test_server()->Start()); | |
273 GURL test_url(test_server()->GetURL( | |
274 "files/browser_plugin_focus.html")); | |
275 NavigateToURL(shell(), test_url); | |
276 | |
277 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>( | |
278 shell()->web_contents()); | |
279 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( | |
280 embedder_web_contents->GetRenderViewHost()); | |
281 | |
282 test_url = test_server()->GetURL( | |
283 "files/browser_plugin_focus_child.html"); | |
284 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
285 StringPrintf("SetSrc('%s');", test_url.spec().c_str()))); | |
286 | |
287 // Wait to make sure embedder is created/attached to WebContents. | |
288 ASSERT_TRUE( | |
289 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation()); | |
290 | |
291 TestBrowserPluginEmbedder* test_embedder = | |
292 static_cast<TestBrowserPluginEmbedder*>( | |
293 embedder_web_contents->GetBrowserPluginEmbedder()); | |
294 ASSERT_TRUE(test_embedder); | |
295 ASSERT_TRUE(test_embedder->WaitForGuestAdded()); | |
296 | |
297 // Verify that we have exactly one guest. | |
298 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = | |
299 test_embedder->guest_web_contents_for_testing(); | |
300 EXPECT_EQ(1u, instance_map.size()); | |
301 | |
302 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( | |
303 instance_map.begin()->second); | |
304 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>( | |
305 test_guest_web_contents->GetBrowserPluginGuest()); | |
306 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg()); | |
307 | |
308 SimulateMouseClick(embedder_web_contents); | |
309 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents); | |
310 // Wait until we focus into the guest. | |
311 ASSERT_TRUE(test_guest->WaitForFocus()); | |
312 | |
313 // TODO(fsamuel): A third Tab key press should not be necessary. | |
314 // The browser plugin will take keyboard focus but it will not | |
315 // focus an initial element. The initial element is dependent | |
316 // upon tab direction which WebKit does not propagate to the plugin. | |
317 // See http://crbug.com/147644. | |
318 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents); | |
319 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents); | |
320 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents); | |
321 ASSERT_TRUE(test_guest->WaitForAdvanceFocus()); | |
322 } | |
323 | |
324 // This test opens a page in http and then opens another page in https, forcing | |
325 // a RenderViewHost swap in the web_contents. We verify if the embedder in the | |
Charlie Reis
2012/09/13 00:51:44
nit: verify if -> verify that
lazyboy
2012/09/13 15:56:24
Done.
| |
326 // web_contents gets cleared properly. | |
327 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) { | |
328 ASSERT_TRUE(test_server()->Start()); | |
329 net::TestServer https_server( | |
330 net::TestServer::TYPE_HTTPS, | |
331 net::TestServer::kLocalhost, | |
332 FilePath(FILE_PATH_LITERAL("content/test/data"))); | |
333 ASSERT_TRUE(https_server.Start()); | |
334 | |
335 // 1. Load an embedder page with one guest in it. | |
336 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html")); | |
337 NavigateToURL(shell(), test_url); | |
338 | |
339 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>( | |
340 shell()->web_contents()); | |
341 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( | |
342 embedder_web_contents->GetRenderViewHost()); | |
343 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
344 StringPrintf("SetSrc('%s');", kHTMLForGuest))); | |
345 | |
346 // Wait to make sure embedder is created/attached to WebContents. | |
347 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation(); | |
348 | |
349 TestBrowserPluginEmbedder* test_embedder_before_swap = | |
350 static_cast<TestBrowserPluginEmbedder*>( | |
351 embedder_web_contents->GetBrowserPluginEmbedder()); | |
352 ASSERT_TRUE(test_embedder_before_swap); | |
353 test_embedder_before_swap->WaitForGuestAdded(); | |
354 | |
355 // Verify that we have exactly one guest. | |
356 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = | |
357 test_embedder_before_swap->guest_web_contents_for_testing(); | |
358 EXPECT_EQ(1u, instance_map.size()); | |
359 | |
360 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( | |
361 instance_map.begin()->second); | |
362 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>( | |
363 test_guest_web_contents->GetBrowserPluginGuest()); | |
364 | |
365 // Wait for the guest to send an UpdateRectMsg, which means the guest is | |
366 // ready. | |
367 test_guest->WaitForUpdateRectMsg(); | |
368 | |
369 // This URL is loaded in https, forcing a RenderViewHost swap. | |
370 GURL test_https_url(https_server.GetURL( | |
371 "files/browser_plugin_title_change.html")); | |
372 | |
373 // 2. Navigate to a URL in https, so we trigger a RenderViewHost swap. | |
Charlie Reis
2012/09/13 00:51:44
nit: Move the test_https_url lines below this line
lazyboy
2012/09/13 15:56:24
Done.
| |
374 content::WindowedNotificationObserver swap_observer( | |
375 content::NOTIFICATION_WEB_CONTENTS_SWAPPED, | |
376 content::Source<WebContents>(embedder_web_contents)); | |
377 NavigateToURL(shell(), test_https_url); | |
378 swap_observer.Wait(); | |
379 | |
380 TestBrowserPluginEmbedder* test_embedder_after_swap = | |
381 static_cast<TestBrowserPluginEmbedder*>( | |
382 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
383 GetBrowserPluginEmbedder()); | |
384 // Verify we have a no embedder in web_contents (since the new page doesn't | |
385 // have any browser plugin). | |
386 ASSERT_TRUE(!test_embedder_after_swap); | |
387 ASSERT_NE(test_embedder_before_swap, test_embedder_after_swap); | |
388 } | |
389 | |
390 // This test opens two pages in http and there is no RenderViewHost swap, | |
391 // therefore the embedder created on first page navigation stays the same in | |
392 // web_contents. | |
393 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) { | |
394 ASSERT_TRUE(test_server()->Start()); | |
395 | |
396 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html")); | |
397 NavigateToURL(shell(), test_url); | |
398 | |
399 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>( | |
400 shell()->web_contents()); | |
401 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( | |
402 embedder_web_contents->GetRenderViewHost()); | |
403 | |
404 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16( | |
405 StringPrintf("SetSrc('%s');", kHTMLForGuest))); | |
406 | |
407 // Wait to make sure embedder is created/attached to WebContents. | |
408 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation(); | |
409 | |
410 TestBrowserPluginEmbedder* test_embedder_ = | |
411 static_cast<TestBrowserPluginEmbedder*>( | |
412 embedder_web_contents->GetBrowserPluginEmbedder()); | |
413 ASSERT_TRUE(test_embedder_); | |
414 test_embedder_->WaitForGuestAdded(); | |
415 | |
416 // Verify that we have exactly one guest. | |
417 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = | |
418 test_embedder_->guest_web_contents_for_testing(); | |
419 EXPECT_EQ(1u, instance_map.size()); | |
420 | |
421 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( | |
422 instance_map.begin()->second); | |
423 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>( | |
424 test_guest_web_contents->GetBrowserPluginGuest()); | |
425 | |
426 // Wait for the guest to send an UpdateRectMsg, which means the guest is | |
427 // ready. | |
428 test_guest->WaitForUpdateRectMsg(); | |
429 | |
430 // Navigate to another page in same host and port, so RenderViewHost swap | |
431 // does not happen and existing embedder doesn't change in web_contents. | |
432 GURL test_url_new(test_server()->GetURL( | |
433 "files/browser_plugin_title_change.html")); | |
434 const string16 expected_title = ASCIIToUTF16("done"); | |
435 content::TitleWatcher title_watcher(shell()->web_contents(), expected_title); | |
436 NavigateToURL(shell(), test_url_new); | |
437 LOG(INFO) << "Start waiting for title"; | |
438 string16 actual_title = title_watcher.WaitAndGetTitle(); | |
439 EXPECT_EQ(expected_title, actual_title); | |
440 LOG(INFO) << "Done navigating to second page"; | |
441 | |
442 TestBrowserPluginEmbedder* test_embedder_after_nav = | |
443 static_cast<TestBrowserPluginEmbedder*>( | |
444 embedder_web_contents->GetBrowserPluginEmbedder()); | |
445 // Embedder must not change in web_contents. | |
446 ASSERT_EQ(test_embedder_after_nav, test_embedder_); | |
447 } | |
448 | |
449 } // namespace content | |
OLD | NEW |