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

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: @tott + Address comments + fix win_rel trybot flakiness 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(
172 "files/browser_plugin_embedder_crash.html"));
173 NavigateToURL(shell(), test_url);
174
175 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
176 shell()->web_contents());
177 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
178 embedder_web_contents->GetRenderViewHost());
179
180 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
181 StringPrintf("SetSrc('%s');", kHTMLForGuestInfiniteLoop)));
182
183 // Wait to make sure embedder is created/attached to WebContents.
184 ASSERT_TRUE(
185 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
186
187 TestBrowserPluginEmbedder* test_embedder =
188 static_cast<TestBrowserPluginEmbedder*>(
189 embedder_web_contents->GetBrowserPluginEmbedder());
190 ASSERT_TRUE(test_embedder);
191 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
192
193 // Verify that we have exactly one guest.
194 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
195 test_embedder->guest_web_contents_for_testing();
196 EXPECT_EQ(1u, instance_map.size());
197
198 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
199 instance_map.begin()->second);
200 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
201 test_guest_web_contents->GetBrowserPluginGuest());
202
203 // Wait for the guest to send an UpdateRectMsg, meaning it is ready.
204 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
205
206 test_guest_web_contents->GetRenderViewHost()->ExecuteJavascriptAndGetValue(
207 string16(), ASCIIToUTF16("StartInfiniteLoop();"));
208
209 // Send a mouse event to the guest.
210 SimulateMouseClick(embedder_web_contents);
211
212 // Expect the guest to crash.
213 test_guest->WaitForCrashed();
214 }
215
216 // This test ensures that if guest isn't there and we resize the guest (from
217 // js), it remembers the size correctly.
218 //
219 // Initially we load an embedder with a guest without a src attribute (which has
220 // dimension 640x480), resize it to 100x200, and then we set the source to a
221 // sample guest. In the end we verify that the correct size has been set.
222 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, NavigateAfterResize) {
223 ASSERT_TRUE(test_server()->Start());
224 GURL test_url(test_server()->GetURL(
225 "files/browser_plugin_embedder.html"));
226 NavigateToURL(shell(), test_url);
227
228 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
229 shell()->web_contents());
230 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
231 embedder_web_contents->GetRenderViewHost());
232
233 int nxt_width = 100;
234 int nxt_height = 200;
235 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
236 StringPrintf("SetSize(%d, %d);", nxt_width, nxt_height)));
237
238 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
239 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
240
241 // Wait to make sure embedder is created/attached to WebContents.
242 ASSERT_TRUE(
243 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
244
245 TestBrowserPluginEmbedder* test_embedder =
246 static_cast<TestBrowserPluginEmbedder*>(
247 embedder_web_contents->GetBrowserPluginEmbedder());
248 ASSERT_TRUE(test_embedder);
249 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
250
251 // Verify that we have exactly one guest.
252 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
253 test_embedder->guest_web_contents_for_testing();
254 EXPECT_EQ(1u, instance_map.size());
255
256 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
257 instance_map.begin()->second);
258 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
259 test_guest_web_contents->GetBrowserPluginGuest());
260
261
262 // Wait for the guest to send an UpdateRectMsg, the dimensions should be
263 // 100 x 200.
264 ASSERT_TRUE(test_guest->WaitForUpdateRectMsgWithSize(nxt_width, nxt_height));
265 }
266
267 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) {
268 ASSERT_TRUE(test_server()->Start());
269 GURL test_url(test_server()->GetURL(
270 "files/browser_plugin_focus.html"));
271 NavigateToURL(shell(), test_url);
272
273 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
274 shell()->web_contents());
275 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
276 embedder_web_contents->GetRenderViewHost());
277
278 test_url = test_server()->GetURL(
279 "files/browser_plugin_focus_child.html");
280 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
281 StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
282
283 // Wait to make sure embedder is created/attached to WebContents.
284 ASSERT_TRUE(
285 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
286
287 TestBrowserPluginEmbedder* test_embedder =
288 static_cast<TestBrowserPluginEmbedder*>(
289 embedder_web_contents->GetBrowserPluginEmbedder());
290 ASSERT_TRUE(test_embedder);
291 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
292
293 // Verify that we have exactly one guest.
294 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
295 test_embedder->guest_web_contents_for_testing();
296 EXPECT_EQ(1u, instance_map.size());
297
298 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
299 instance_map.begin()->second);
300 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
301 test_guest_web_contents->GetBrowserPluginGuest());
302 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
303
304 SimulateMouseClick(embedder_web_contents);
305 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
306 // Wait until we focus into the guest.
307 ASSERT_TRUE(test_guest->WaitForFocus());
308
309 // TODO(fsamuel): A third Tab key press should not be necessary.
310 // The browser plugin will take keyboard focus but it will not
311 // focus an initial element. The initial element is dependent
312 // upon tab direction which WebKit does not propagate to the plugin.
313 // See http://crbug.com/147644.
314 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
315 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
316 BrowserPluginHostTest::SimulateTabKeyPress(embedder_web_contents);
317 ASSERT_TRUE(test_guest->WaitForAdvanceFocus());
318 }
319
320 // This test opens a page in http and then opens another page in https, forcing
321 // a RenderViewHost swap in the web_contents. We verify that the embedder in the
322 // web_contents gets cleared properly.
323 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
324 ASSERT_TRUE(test_server()->Start());
325 net::TestServer https_server(
326 net::TestServer::TYPE_HTTPS,
327 net::TestServer::kLocalhost,
328 FilePath(FILE_PATH_LITERAL("content/test/data")));
329 ASSERT_TRUE(https_server.Start());
330
331 // 1. Load an embedder page with one guest in it.
332 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html"));
333 NavigateToURL(shell(), test_url);
334
335 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
336 shell()->web_contents());
337 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
338 embedder_web_contents->GetRenderViewHost());
339 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
340 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
341
342 // Wait to make sure embedder is created/attached to WebContents.
343 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation();
344
345 TestBrowserPluginEmbedder* test_embedder_before_swap =
346 static_cast<TestBrowserPluginEmbedder*>(
347 embedder_web_contents->GetBrowserPluginEmbedder());
348 ASSERT_TRUE(test_embedder_before_swap);
349 test_embedder_before_swap->WaitForGuestAdded();
350
351 // Verify that we have exactly one guest.
352 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
353 test_embedder_before_swap->guest_web_contents_for_testing();
354 EXPECT_EQ(1u, instance_map.size());
355
356 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
357 instance_map.begin()->second);
358 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
359 test_guest_web_contents->GetBrowserPluginGuest());
360
361 // Wait for the guest to send an UpdateRectMsg, which means the guest is
362 // ready.
363 test_guest->WaitForUpdateRectMsg();
364
365 // 2. Navigate to a URL in https, so we trigger a RenderViewHost swap.
366 GURL test_https_url(https_server.GetURL(
367 "files/browser_plugin_title_change.html"));
368 content::WindowedNotificationObserver swap_observer(
369 content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
370 content::Source<WebContents>(embedder_web_contents));
371 NavigateToURL(shell(), test_https_url);
372 swap_observer.Wait();
373
374 TestBrowserPluginEmbedder* test_embedder_after_swap =
375 static_cast<TestBrowserPluginEmbedder*>(
376 static_cast<WebContentsImpl*>(shell()->web_contents())->
377 GetBrowserPluginEmbedder());
378 // Verify we have a no embedder in web_contents (since the new page doesn't
379 // have any browser plugin).
380 ASSERT_TRUE(!test_embedder_after_swap);
381 ASSERT_NE(test_embedder_before_swap, test_embedder_after_swap);
382 }
383
384 // This test opens two pages in http and there is no RenderViewHost swap,
385 // therefore the embedder created on first page navigation stays the same in
386 // web_contents.
387 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
388 ASSERT_TRUE(test_server()->Start());
389
390 GURL test_url(test_server()->GetURL("files/browser_plugin_embedder.html"));
391 NavigateToURL(shell(), test_url);
392
393 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
394 shell()->web_contents());
395 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
396 embedder_web_contents->GetRenderViewHost());
397
398 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
399 StringPrintf("SetSrc('%s');", kHTMLForGuest)));
400
401 // Wait to make sure embedder is created/attached to WebContents.
402 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation();
403
404 TestBrowserPluginEmbedder* test_embedder =
405 static_cast<TestBrowserPluginEmbedder*>(
406 embedder_web_contents->GetBrowserPluginEmbedder());
407 ASSERT_TRUE(test_embedder);
408 test_embedder->WaitForGuestAdded();
409
410 // Verify that we have exactly one guest.
411 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
412 test_embedder->guest_web_contents_for_testing();
413 EXPECT_EQ(1u, instance_map.size());
414
415 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
416 instance_map.begin()->second);
417 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
418 test_guest_web_contents->GetBrowserPluginGuest());
419
420 // Wait for the guest to send an UpdateRectMsg, which means the guest is
421 // ready.
422 test_guest->WaitForUpdateRectMsg();
423
424 // Navigate to another page in same host and port, so RenderViewHost swap
425 // does not happen and existing embedder doesn't change in web_contents.
426 GURL test_url_new(test_server()->GetURL(
427 "files/browser_plugin_title_change.html"));
428 const string16 expected_title = ASCIIToUTF16("done");
429 content::TitleWatcher title_watcher(shell()->web_contents(), expected_title);
430 NavigateToURL(shell(), test_url_new);
431 LOG(INFO) << "Start waiting for title";
432 string16 actual_title = title_watcher.WaitAndGetTitle();
433 EXPECT_EQ(expected_title, actual_title);
434 LOG(INFO) << "Done navigating to second page";
435
436 TestBrowserPluginEmbedder* test_embedder_after_nav =
437 static_cast<TestBrowserPluginEmbedder*>(
438 embedder_web_contents->GetBrowserPluginEmbedder());
439 // Embedder must not change in web_contents.
440 ASSERT_EQ(test_embedder_after_nav, test_embedder);
441 }
442
443 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, VisibilityChanged) {
444 ASSERT_TRUE(test_server()->Start());
445 GURL test_url(test_server()->GetURL(
446 "files/browser_plugin_focus.html"));
447 NavigateToURL(shell(), test_url);
448
449 WebContentsImpl* embedder_web_contents = static_cast<WebContentsImpl*>(
450 shell()->web_contents());
451 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
452 embedder_web_contents->GetRenderViewHost());
453
454 test_url = test_server()->GetURL(
455 "files/browser_plugin_focus_child.html");
456 rvh->ExecuteJavascriptAndGetValue(string16(), ASCIIToUTF16(
457 StringPrintf("SetSrc('%s');", test_url.spec().c_str())));
458
459 // Wait to make sure embedder is created/attached to WebContents.
460 ASSERT_TRUE(
461 TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation());
462
463 TestBrowserPluginEmbedder* test_embedder =
464 static_cast<TestBrowserPluginEmbedder*>(
465 embedder_web_contents->GetBrowserPluginEmbedder());
466 ASSERT_TRUE(test_embedder);
467 ASSERT_TRUE(test_embedder->WaitForGuestAdded());
468
469 // Verify that we have exactly one guest.
470 const BrowserPluginEmbedder::ContainerInstanceMap& instance_map =
471 test_embedder->guest_web_contents_for_testing();
472 EXPECT_EQ(1u, instance_map.size());
473
474 WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>(
475 instance_map.begin()->second);
476 TestBrowserPluginGuest* test_guest = static_cast<TestBrowserPluginGuest*>(
477 test_guest_web_contents->GetBrowserPluginGuest());
478
479 // Wait for the guest to send an UpdateRectMsg, meaning it is ready.
480 ASSERT_TRUE(test_guest->WaitForUpdateRectMsg());
481
482 // Hide the embedder.
483 embedder_web_contents->WasHidden();
484
485 // Make sure that hiding the embedder also hides the guest.
486 ASSERT_TRUE(test_guest->WaitUntilHidden());
487 }
488
489 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698