Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(616)

Side by Side Diff: content/browser/browser_plugin/browser_plugin_host_browsertest.cc

Issue 10868012: Browser Plugin: New Implementation (Browser Side) (Closed) Base URL: http://git.chromium.org/chromium/src.git@master-trial-obrowser
Patch Set: Address nits. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 const char* kHTMLForGuestInfiniteLoop =
39 "data:text/html,<html><head><script type=\"text/javascript\">"
40 "function StartInfiniteLoop() {"
41 " setTimeout(function () {while (true) {} }, 0);"
42 "}"
43 "</script></head><body></body></html>";
44
45 // Test factory for creating test instances of BrowserPluginEmbedder and
46 // BrowserPluginGuest.
47 class TestBrowserPluginHostFactory : public BrowserPluginHostFactory {
48 public:
49 virtual BrowserPluginGuest* CreateBrowserPluginGuest(
50 int instance_id,
51 WebContentsImpl* web_contents,
52 RenderViewHost* render_view_host) OVERRIDE {
53 return new TestBrowserPluginGuest(instance_id,
54 web_contents,
55 render_view_host);
56 }
57
58 // Also keeps track of number of instances created.
59 virtual BrowserPluginEmbedder* CreateBrowserPluginEmbedder(
60 WebContentsImpl* web_contents,
61 RenderViewHost* render_view_host) OVERRIDE {
62 embedder_instance_count_++;
63 if (message_loop_runner_)
64 message_loop_runner_->Quit();
65
66 return new TestBrowserPluginEmbedder(web_contents, render_view_host);
67 }
68
69 // Singleton getter.
70 static TestBrowserPluginHostFactory* GetInstance() {
71 return Singleton<TestBrowserPluginHostFactory>::get();
72 }
73
74 // Waits for at least one embedder to be created in the test. Returns true if
75 // we have a guest, false if waiting times out.
76 bool WaitForEmbedderCreation() {
77 // Check if already have created instance.
78 if (embedder_instance_count_ > 0)
79 return true;
80 // Wait otherwise.
81 message_loop_runner_ = new MessageLoopRunner();
82 return TestTimeoutTracker::RunInActionTimeout(
83 message_loop_runner_.get());
84 }
85
86 protected:
87 TestBrowserPluginHostFactory() : embedder_instance_count_(0) {}
88 virtual ~TestBrowserPluginHostFactory() {}
89
90 private:
91 // For Singleton.
92 friend struct DefaultSingletonTraits<TestBrowserPluginHostFactory>;
93
94 scoped_refptr<MessageLoopRunner> message_loop_runner_;
95 int embedder_instance_count_;
96
97 DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginHostFactory);
98 };
99
100 // Test factory class for browser plugin that creates guests with short hang
101 // timeout.
102 class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory {
103 public:
104 virtual BrowserPluginGuest* CreateBrowserPluginGuest(
105 int instance_id,
106 WebContentsImpl* web_contents,
107 RenderViewHost* render_view_host) OVERRIDE {
108 BrowserPluginGuest* guest = new TestBrowserPluginGuest(instance_id,
109 web_contents,
110 render_view_host);
111 guest->SetGuestHangTimeoutForTesting(TestTimeouts::tiny_timeout());
112 return guest;
113 }
114
115 // Singleton getter.
116 static TestShortHangTimeoutGuestFactory* GetInstance() {
117 return Singleton<TestShortHangTimeoutGuestFactory>::get();
118 }
119
120 protected:
121 TestShortHangTimeoutGuestFactory() {}
122 virtual ~TestShortHangTimeoutGuestFactory() {}
123
124 private:
125 // For Singleton.
126 friend struct DefaultSingletonTraits<TestShortHangTimeoutGuestFactory>;
127
128 DISALLOW_COPY_AND_ASSIGN(TestShortHangTimeoutGuestFactory);
129 };
130
131 class BrowserPluginHostTest : public ContentBrowserTest {
132 public:
133 BrowserPluginHostTest() {}
134
135 virtual void SetUp() OVERRIDE {
136 // Override factory to create tests instances of BrowserPlugin*.
137 content::BrowserPluginEmbedder::set_factory_for_testing(
138 TestBrowserPluginHostFactory::GetInstance());
139 content::BrowserPluginGuest::set_factory_for_testing(
140 TestBrowserPluginHostFactory::GetInstance());
141
142 ContentBrowserTest::SetUp();
143 }
144 virtual void TearDown() OVERRIDE {
145 content::BrowserPluginEmbedder::set_factory_for_testing(NULL);
146 content::BrowserPluginGuest::set_factory_for_testing(NULL);
147
148 ContentBrowserTest::TearDown();
149 }
150
151 static void SimulateTabKeyPress(WebContents* web_contents) {
152 SimulateKeyPress(web_contents,
153 ui::VKEY_TAB,
154 false, // control.
155 false, // shift.
156 false, // alt.
157 false); // command.
158 }
159
160 private:
161 DISALLOW_COPY_AND_ASSIGN(BrowserPluginHostTest);
162 };
163
164 // This test loads a guest that has infinite loop, therefore it hangs the guest
165 // and eventually gets killed.
166 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateGuest) {
167 // Override the hang timeout for guest to be very small.
168 content::BrowserPluginGuest::set_factory_for_testing(
169 TestShortHangTimeoutGuestFactory::GetInstance());
170 ASSERT_TRUE(test_server()->Start());
171 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html"));
172 NavigateToURL(shell(), test_url);
173
174 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
175 shell()->web_contents());
176 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
177 embedder_web_contents->GetRenderViewHost());
178
179 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
180 StringPrintf("SetSrc('%s');", kHTMLForGuestInfiniteLoop)));
181
182 // Wait to make sure embedder is created/attached to WebContents.
183 ASSERT_TRUE(
184 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
185
186 TestBrowserPluginEmbedder* test_embedder =
187 static_cast<TestBrowserPluginEmbedder*>(
188 embedder_web_contents->GetBrowserPluginEmbedder());
189 ASSERT_TRUE(test_embedder);
190 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
191
192 // Verify that we have exactly one guest.
193 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
194 test_embedder->guest_web_contents_for_testing();
195 EXPECT_EQ(1u, instance_map.size());
196
197 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
198 instance_map.begin()->second);
199 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
200 test_guest_web_contents->GetBrowserPluginGuest());
201
202 // Wait for the guest to send an UpdateRectMsg, meaning it is ready.
203 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
204
205 test_guest_web_contents->GetRenderViewHost()->ExecuteJavascriptAndGetValue(
206 string16(), ASCIIToUTF16("StartInfiniteLoop();"));
207
208 // Send a mouse event to the guest.
jam 2012/09/13 16:07:56 can you make the plugin take 100% and use content:
lazyboy 2012/09/14 19:17:30 Done.
209 WebKit::WebMouseEvent mouse_event;
210 mouse_event.type = WebInputEvent::MouseDown;
211 mouse_event.button = WebMouseEvent::ButtonMiddle;
212 mouse_event.x = 35;
213 mouse_event.y = 35;
214 mouse_event.globalX = 35;
215 mouse_event.globalY = 35;
216
217 IPC::Message* input_message = new ViewMsg_HandleInputEvent(
218 embedder_web_contents->GetRenderViewHost()->GetRoutingID());
219 input_message->WriteData(reinterpret_cast<const char*>(&mouse_event),
220 sizeof(WebKit::WebMouseEvent));
221 embedder_web_contents->GetRenderViewHost()->Send(input_message);
222
223 // Expect the guest to crash.
224 ASSERT_TRUE(test_guest->WaitForCrashed());
225 }
226
227 // This test ensures that if guest isn't there and we resize the guest (from
228 // js), it remembers the size correctly.
229 //
230 // Initially we load an embedder with a guest without a src attribute (which has
231 // dimension 640x480), resize it to 100x200, and then we set the source to a
232 // sample guest. In the end we verify that the correct size has been set.
233 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateAfterResize) {
234 ASSERT_TRUE(test_server()->Start());
235 GURL test_url(test_server()->GetURL(
236 "files/browser_plugin_embedder.html"));
237 NavigateToURL(shell(), test_url);
238
239 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
240 shell()->web_contents());
241 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
242 embedder_web_contents->GetRenderViewHost());
243
244 int nxt_width = 100;
245 int nxt_height = 200;
246 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
247 StringPrintf("SetSize(%d, %d);", nxt_width, nxt_height)));
248
249 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
250 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
251
252 // Wait to make sure embedder is created/attached to WebContents.
253 ASSERT_TRUE(
254 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
255
256 TestBrowserPluginEmbedder* test_embedder =
257 static_cast<TestBrowserPluginEmbedder*>(
258 embedder_web_contents->GetBrowserPluginEmbedder());
259 ASSERT_TRUE(test_embedder);
260 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
261
262 // Verify that we have exactly one guest.
263 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
264 test_embedder->guest_web_contents_for_testing();
265 EXPECT_EQ(1u, instance_map.size());
266
267 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
268 instance_map.begin()->second);
269 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
270 test_guest_web_contents->GetBrowserPluginGuest());
271
272
273 // Wait for the guest to send an UpdateRectMsg, the dimensions should be
274 // 100 x 200.
275 ASSERT_TRUE(test_guest->WaitForUpdateRectMsgWithSize(nxt_width, nxt_height));
276 }
277
278 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) {
279 ASSERT_TRUE(test_server()->Start());
280 GURL test_url(test_server()->GetURL(
281 "files/browser_plugin_focus.html"));
282 NavigateToURL(shell(), test_url);
283
284 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
285 shell()->web_contents());
286 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
287 embedder_web_contents->GetRenderViewHost());
288
289 test_url = test_server()->GetURL(
290 "files/browser_plugin_focus_child.html");
291 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
292 StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
293
294 // Wait to make sure embedder is created/attached to WebContents.
295 ASSERT_TRUE(
296 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
297
298 TestBrowserPluginEmbedder* test_embedder =
299 static_cast<TestBrowserPluginEmbedder*>(
300 embedder_web_contents->GetBrowserPluginEmbedder());
301 ASSERT_TRUE(test_embedder);
302 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
303
304 // Verify that we have exactly one guest.
305 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
306 test_embedder->guest_web_contents_for_testing();
307 EXPECT_EQ(1u, instance_map.size());
308
309 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
310 instance_map.begin()->second);
311 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
312 test_guest_web_contents->GetBrowserPluginGuest());
313 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
314
315 SimulateMouseClick(embedder_web_contents);
316 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
317 // Wait until we focus into the guest.
318 ASSERT_TRUE(test_guest->WaitForFocus());
319
320 // TODO(fsamuel): A third Tab key press should not be necessary.
321 // The browser plugin will take keyboard focus but it will not
322 // focus an initial element. The initial element is dependent
323 // upon tab direction which WebKit does not propagate to the plugin.
324 // See http://crbug.com/147644.
325 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
326 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
327 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
328 ASSERT_TRUE(test_guest->WaitForAdvanceFocus());
329 }
330
331 // This test opens a page in http and then opens another page in https, forcing
332 // a RenderViewHost swap in the web_contents. We verify that the embedder in the
333 // web_contents gets cleared properly.
334 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
335 ASSERT_TRUE(test_server()->Start());
336 net::TestServer https_server(
337 net::TestServer::TYPE_HTTPS,
338 net::TestServer::kLocalhost,
339 FilePath(FILE_PATH_LITERAL("content/test/data")));
340 ASSERT_TRUE(https_server.Start());
341
342 // 1. Load an embedder page with one guest in it.
343 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html"));
344 NavigateToURL(shell(), test_url);
345
346 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
347 shell()->web_contents());
348 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
349 embedder_web_contents->GetRenderViewHost());
350 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
351 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
352
353 // Wait to make sure embedder is created/attached to WebContents.
354 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation();
355
356 TestBrowserPluginEmbedder* test_embedder_before_swap =
357 static_cast<TestBrowserPluginEmbedder*>(
358 embedder_web_contents->GetBrowserPluginEmbedder());
359 ASSERT_TRUE(test_embedder_before_swap);
360 test_embedder_before_swap->WaitForGuestAdded();
361
362 // Verify that we have exactly one guest.
363 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
364 test_embedder_before_swap->guest_web_contents_for_testing();
365 EXPECT_EQ(1u, instance_map.size());
366
367 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
368 instance_map.begin()->second);
369 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
370 test_guest_web_contents->GetBrowserPluginGuest());
371
372 // Wait for the guest to send an UpdateRectMsg, which means the guest is
373 // ready.
374 test_guest->WaitForUpdateRectMsg();
375
376 // 2. Navigate to a URL in https, so we trigger a RenderViewHost swap.
377 GURL test_https_url(https_server.GetURL(
378 "files/browser_plugin_title_change.html"));
379 content::WindowedNotificationObserver swap_observer(
380 content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
381 content::Source<WebContents>(embedder_web_contents));
382 NavigateToURL(shell(), test_https_url);
383 swap_observer.Wait();
384
385 TestBrowserPluginEmbedder* test_embedder_after_swap =
386 static_cast<TestBrowserPluginEmbedder*>(
387 static_cast<WebContentsImpl*>(shell()->web_contents())->
388 GetBrowserPluginEmbedder());
389 // Verify we have a no embedder in web_contents (since the new page doesn't
390 // have any browser plugin).
391 ASSERT_TRUE(!test_embedder_after_swap);
392 ASSERT_NE(test_embedder_before_swap, test_embedder_after_swap);
393 }
394
395 // This test opens two pages in http and there is no RenderViewHost swap,
396 // therefore the embedder created on first page navigation stays the same in
397 // web_contents.
398 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
399 ASSERT_TRUE(test_server()->Start());
400
401 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html"));
402 NavigateToURL(shell(), test_url);
403
404 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
405 shell()->web_contents());
406 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
407 embedder_web_contents->GetRenderViewHost());
408
409 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
410 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
411
412 // Wait to make sure embedder is created/attached to WebContents.
413 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation();
414
415 TestBrowserPluginEmbedder* test_embedder =
416 static_cast<TestBrowserPluginEmbedder*>(
417 embedder_web_contents->GetBrowserPluginEmbedder());
418 ASSERT_TRUE(test_embedder);
419 test_embedder->WaitForGuestAdded();
420
421 // Verify that we have exactly one guest.
422 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
423 test_embedder->guest_web_contents_for_testing();
424 EXPECT_EQ(1u, instance_map.size());
425
426 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
427 instance_map.begin()->second);
428 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
429 test_guest_web_contents->GetBrowserPluginGuest());
430
431 // Wait for the guest to send an UpdateRectMsg, which means the guest is
432 // ready.
433 test_guest->WaitForUpdateRectMsg();
434
435 // Navigate to another page in same host and port, so RenderViewHost swap
436 // does not happen and existing embedder doesn't change in web_contents.
437 GURL test_url_new(test_server()->GetURL(
438 "files/browser_plugin_title_change.html"));
439 const string16 expected_title = ASCIIToUTF16("done");
440 content::TitleWatcher title_watcher(shell()->web_contents(), expected_title);
441 NavigateToURL(shell(), test_url_new);
442 LOG(INFO) << "Start waiting for title";
443 string16 actual_title = title_watcher.WaitAndGetTitle();
444 EXPECT_EQ(expected_title, actual_title);
445 LOG(INFO) << "Done navigating to second page";
446
447 TestBrowserPluginEmbedder* test_embedder_after_nav =
448 static_cast<TestBrowserPluginEmbedder*>(
449 embedder_web_contents->GetBrowserPluginEmbedder());
450 // Embedder must not change in web_contents.
451 ASSERT_EQ(test_embedder_after_nav, test_embedder);
452 }
453
454 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, VisibilityChanged) {
455 ASSERT_TRUE(test_server()->Start());
456 GURL test_url(test_server()->GetURL(
457 "files/browser_plugin_focus.html"));
458 NavigateToURL(shell(), test_url);
459
460 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
461 shell()->web_contents());
462 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
463 embedder_web_contents->GetRenderViewHost());
464
465 test_url = test_server()->GetURL(
466 "files/browser_plugin_focus_child.html");
467 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
468 StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
469
470 // Wait to make sure embedder is created/attached to WebContents.
471 ASSERT_TRUE(
472 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
473
474 TestBrowserPluginEmbedder* test_embedder =
475 static_cast<TestBrowserPluginEmbedder*>(
476 embedder_web_contents->GetBrowserPluginEmbedder());
477 ASSERT_TRUE(test_embedder);
478 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
479
480 // Verify that we have exactly one guest.
481 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
482 test_embedder->guest_web_contents_for_testing();
483 EXPECT_EQ(1u, instance_map.size());
484
485 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
486 instance_map.begin()->second);
487 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
488 test_guest_web_contents->GetBrowserPluginGuest());
489
490 // Wait for the guest to send an UpdateRectMsg, meaning it is ready.
491 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
492
493 // Hide the embedder.
494 embedder_web_contents->WasHidden();
Fady Samuel 2012/09/13 16:35:26 I forgot to add an ASSERT_TRUE here.
Fady Samuel 2012/09/13 16:47:47 Wow, nevermind. I misread what I wrote :P
495
496 // Make sure that hiding the embedder also hides the guest.
497 ASSERT_TRUE(test_guest->WaitUntilHidden());
498 }
499
500 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698