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

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

Powered by Google App Engine
This is Rietveld 408576698