OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/process_manager.h" | 5 #include "extensions/browser/process_manager.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/strings/stringprintf.h" | |
11 #include "chrome/browser/extensions/browser_action_test_util.h" | 10 #include "chrome/browser/extensions/browser_action_test_util.h" |
12 #include "chrome/browser/extensions/extension_browsertest.h" | 11 #include "chrome/browser/extensions/extension_browsertest.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 12 #include "chrome/browser/extensions/extension_service.h" |
14 #include "chrome/browser/extensions/test_extension_dir.h" | 13 #include "chrome/browser/extensions/test_extension_dir.h" |
15 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 14 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
16 #include "chrome/common/extensions/extension_process_policy.h" | 15 #include "chrome/common/extensions/extension_process_policy.h" |
17 #include "chrome/test/base/in_process_browser_test.h" | 16 #include "chrome/test/base/in_process_browser_test.h" |
18 #include "chrome/test/base/ui_test_utils.h" | 17 #include "chrome/test/base/ui_test_utils.h" |
19 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
20 #include "content/public/browser/render_frame_host.h" | 19 #include "content/public/browser/render_frame_host.h" |
21 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
22 #include "content/public/test/browser_test_utils.h" | 21 #include "content/public/test/browser_test_utils.h" |
23 #include "content/public/test/test_utils.h" | 22 #include "content/public/test/test_utils.h" |
24 #include "extensions/common/value_builder.h" | 23 #include "extensions/common/value_builder.h" |
25 #include "extensions/test/background_page_watcher.h" | 24 #include "extensions/test/background_page_watcher.h" |
26 #include "extensions/test/extension_test_message_listener.h" | |
27 #include "net/dns/mock_host_resolver.h" | 25 #include "net/dns/mock_host_resolver.h" |
28 #include "net/test/embedded_test_server/embedded_test_server.h" | 26 #include "net/test/embedded_test_server/embedded_test_server.h" |
29 | 27 |
30 namespace extensions { | 28 namespace extensions { |
31 | 29 |
32 namespace { | 30 namespace { |
33 | 31 |
34 void AddFrameToSet(std::set<content::RenderFrameHost*>* frames, | 32 void AddFrameToSet(std::set<content::RenderFrameHost*>* frames, |
35 content::RenderFrameHost* rfh) { | 33 content::RenderFrameHost* rfh) { |
36 if (rfh->IsRenderFrameLive()) | 34 if (rfh->IsRenderFrameLive()) |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 NavigationCompletedObserver observer( | 143 NavigationCompletedObserver observer( |
146 browser()->tab_strip_model()->GetActiveWebContents()); | 144 browser()->tab_strip_model()->GetActiveWebContents()); |
147 | 145 |
148 ui_test_utils::NavigateToURL(browser(), url); | 146 ui_test_utils::NavigateToURL(browser(), url); |
149 | 147 |
150 // Wait until the last RenderFrameHosts are deleted. This wait doesn't take | 148 // Wait until the last RenderFrameHosts are deleted. This wait doesn't take |
151 // long. | 149 // long. |
152 observer.Wait(); | 150 observer.Wait(); |
153 } | 151 } |
154 | 152 |
155 void NavigateIframeToURLAndWait(content::WebContents* web_contents, | |
156 const std::string iframe_id, | |
157 const GURL& url) { | |
158 // This is an improved version of content::NavigateIframeToURL. Unlike the | |
159 // other method, this does actually wait until the load of all child frames | |
160 // completes. | |
161 std::string script = base::StringPrintf( | |
162 "var frame = document.getElementById('%s');" | |
163 "frame.onload = frame.onerror = function(event) {" | |
164 " frame.onload = frame.onerror = null;" | |
165 " domAutomationController.send(event.type === 'load');" | |
166 "};" | |
167 "frame.src = '%s';", | |
168 iframe_id.c_str(), url.spec().c_str()); | |
169 bool is_loaded = false; | |
170 EXPECT_TRUE(ExecuteScriptAndExtractBool(web_contents, script, &is_loaded)); | |
171 EXPECT_TRUE(is_loaded); | |
172 } | |
173 | |
174 size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) { | 153 size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) { |
175 return content::AreAllSitesIsolatedForTesting() || | 154 return content::AreAllSitesIsolatedForTesting() || |
176 IsIsolateExtensionsEnabled() | 155 IsIsolateExtensionsEnabled() |
177 ? if_enabled | 156 ? if_enabled |
178 : if_disabled; | 157 : if_disabled; |
179 } | 158 } |
180 | 159 |
181 private: | 160 private: |
182 std::vector<scoped_ptr<TestExtensionDir>> temp_dirs_; | 161 std::vector<scoped_ptr<TestExtensionDir>> temp_dirs_; |
183 }; | 162 }; |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 EXPECT_EQ(0u, pm->GetAllFrames().size()); | 356 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
378 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 357 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
379 | 358 |
380 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); | 359 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); |
381 EXPECT_EQ(0u, pm->GetAllFrames().size()); | 360 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
382 | 361 |
383 content::WebContents* tab = | 362 content::WebContents* tab = |
384 browser()->tab_strip_model()->GetActiveWebContents(); | 363 browser()->tab_strip_model()->GetActiveWebContents(); |
385 | 364 |
386 // Tests extension frames in non-extension page. | 365 // Tests extension frames in non-extension page. |
387 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); | 366 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt1EmptyUrl)); |
388 EXPECT_EQ(IfExtensionsIsolated(1, 0), | 367 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
389 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 368 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
390 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); | 369 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); |
391 | 370 |
392 NavigateIframeToURLAndWait(tab, "frame2", kExt2EmptyUrl); | 371 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame2", kExt2EmptyUrl)); |
393 EXPECT_EQ(IfExtensionsIsolated(1, 0), | 372 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
394 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 373 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
395 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); | 374 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); |
396 | 375 |
397 // Tests non-extension page in extension frame. | 376 // Tests non-extension page in extension frame. |
398 NavigateToURL(kExt1TwoFramesUrl); | 377 NavigateToURL(kExt1TwoFramesUrl); |
399 // 1 top-level + 2 child frames from Extension 1. | 378 // 1 top-level + 2 child frames from Extension 1. |
400 EXPECT_EQ(3u, pm->GetAllFrames().size()); | 379 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
401 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 380 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
402 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 381 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
403 | 382 |
404 NavigateIframeToURLAndWait(tab, "frame1", | 383 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", |
405 embedded_test_server()->GetURL("/empty.html")); | 384 embedded_test_server() |
| 385 ->GetURL("/empty.html"))); |
406 // 1 top-level + 1 child frame from Extension 1. | 386 // 1 top-level + 1 child frame from Extension 1. |
407 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 387 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
408 EXPECT_EQ(2u, pm->GetAllFrames().size()); | 388 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
409 | 389 |
410 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); | 390 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt1EmptyUrl)); |
411 // 1 top-level + 2 child frames from Extension 1. | 391 // 1 top-level + 2 child frames from Extension 1. |
412 EXPECT_EQ(3u, pm->GetAllFrames().size()); | 392 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
413 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 393 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
414 | 394 |
415 // Load a frame from another extension. | 395 // Load a frame from another extension. |
416 NavigateIframeToURLAndWait(tab, "frame1", kExt2EmptyUrl); | 396 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt2EmptyUrl)); |
417 // 1 top-level + 1 child frame from Extension 1, | 397 // 1 top-level + 1 child frame from Extension 1, |
418 // 1 child frame from Extension 2. | 398 // 1 child frame from Extension 2. |
419 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); | 399 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); |
420 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 400 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
421 EXPECT_EQ(IfExtensionsIsolated(1, 0), | 401 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
422 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 402 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
423 | 403 |
424 // Destroy all existing frames by navigating to another extension. | 404 // Destroy all existing frames by navigating to another extension. |
425 NavigateToURL(extension2->url().Resolve("empty.html")); | 405 NavigateToURL(extension2->url().Resolve("empty.html")); |
426 EXPECT_EQ(1u, pm->GetAllFrames().size()); | 406 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
427 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 407 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
428 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 408 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
429 | 409 |
430 // Test about:blank and about:srcdoc child frames. | 410 // Test about:blank and about:srcdoc child frames. |
431 NavigateToURL(extension2->url().Resolve("srcdoc_iframe.html")); | 411 NavigateToURL(extension2->url().Resolve("srcdoc_iframe.html")); |
432 // 1 top-level frame + 1 child frame from Extension 2. | 412 // 1 top-level frame + 1 child frame from Extension 2. |
433 EXPECT_EQ(2u, pm->GetAllFrames().size()); | 413 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
434 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 414 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
435 | 415 |
436 NavigateToURL(extension2->url().Resolve("blank_iframe.html")); | 416 NavigateToURL(extension2->url().Resolve("blank_iframe.html")); |
437 // 1 top-level frame + 1 child frame from Extension 2. | 417 // 1 top-level frame + 1 child frame from Extension 2. |
438 EXPECT_EQ(2u, pm->GetAllFrames().size()); | 418 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
439 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 419 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
440 | 420 |
441 // Sandboxed frames are not viewed as extension frames. | 421 // Sandboxed frames are not viewed as extension frames. |
442 NavigateIframeToURLAndWait(tab, "frame0", | 422 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame0", |
443 extension2->url().Resolve("sandboxed.html")); | 423 extension2->url() |
| 424 .Resolve("sandboxed.html"))); |
444 // 1 top-level frame from Extension 2. | 425 // 1 top-level frame from Extension 2. |
445 EXPECT_EQ(1u, pm->GetAllFrames().size()); | 426 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
446 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 427 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
447 | 428 |
448 NavigateToURL(extension2->url().Resolve("sandboxed.html")); | 429 NavigateToURL(extension2->url().Resolve("sandboxed.html")); |
449 EXPECT_EQ(0u, pm->GetAllFrames().size()); | 430 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
450 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 431 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
451 | 432 |
452 // Test nested frames (same extension). | 433 // Test nested frames (same extension). |
453 NavigateToURL(kExt2TwoFramesUrl); | 434 NavigateToURL(kExt2TwoFramesUrl); |
454 // 1 top-level + 2 child frames from Extension 2. | 435 // 1 top-level + 2 child frames from Extension 2. |
455 EXPECT_EQ(3u, pm->GetAllFrames().size()); | 436 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
456 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 437 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
457 | 438 |
458 NavigateIframeToURLAndWait(tab, "frame1", kExt2TwoFramesUrl); | 439 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt2TwoFramesUrl)); |
459 // 1 top-level + 2 child frames from Extension 1, | 440 // 1 top-level + 2 child frames from Extension 1, |
460 // 2 child frames in frame1 from Extension 2. | 441 // 2 child frames in frame1 from Extension 2. |
461 EXPECT_EQ(5u, pm->GetAllFrames().size()); | 442 EXPECT_EQ(5u, pm->GetAllFrames().size()); |
462 EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 443 EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
463 | 444 |
464 // The extension frame from the other extension should not be classified as an | 445 // The extension frame from the other extension should not be classified as an |
465 // extension (unless out-of-process frames are enabled). | 446 // extension (unless out-of-process frames are enabled). |
466 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); | 447 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt1EmptyUrl)); |
467 // 1 top-level + 1 child frames from Extension 2, | 448 // 1 top-level + 1 child frames from Extension 2, |
468 // 1 child frame from Extension 1. | 449 // 1 child frame from Extension 1. |
469 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); | 450 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); |
470 EXPECT_EQ(IfExtensionsIsolated(1, 0), | 451 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
471 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 452 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
472 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 453 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
473 | 454 |
474 NavigateIframeToURLAndWait(tab, "frame2", kExt1TwoFramesUrl); | 455 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame2", kExt1TwoFramesUrl)); |
475 // 1 top-level + 1 child frames from Extension 2, | 456 // 1 top-level + 1 child frames from Extension 2, |
476 // 1 child frame + 2 child frames in frame2 from Extension 1. | 457 // 1 child frame + 2 child frames in frame2 from Extension 1. |
477 EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size()); | 458 EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size()); |
478 EXPECT_EQ(IfExtensionsIsolated(4, 0), | 459 EXPECT_EQ(IfExtensionsIsolated(4, 0), |
479 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 460 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
480 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 461 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
481 | 462 |
482 // Crash tab where the top-level frame is an extension frame. | 463 // Crash tab where the top-level frame is an extension frame. |
483 content::CrashTab(tab); | 464 content::CrashTab(tab); |
484 EXPECT_EQ(0u, pm->GetAllFrames().size()); | 465 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
485 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 466 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
486 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); | 467 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
487 | 468 |
488 // Now load an extension page and a non-extension page... | 469 // Now load an extension page and a non-extension page... |
489 ui_test_utils::NavigateToURLWithDisposition( | 470 ui_test_utils::NavigateToURLWithDisposition( |
490 browser(), kExt1EmptyUrl, NEW_BACKGROUND_TAB, | 471 browser(), kExt1EmptyUrl, NEW_BACKGROUND_TAB, |
491 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | 472 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
492 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); | 473 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); |
493 EXPECT_EQ(1u, pm->GetAllFrames().size()); | 474 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
494 | 475 |
495 // ... load an extension frame in the non-extension process | 476 // ... load an extension frame in the non-extension process |
496 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); | 477 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", kExt1EmptyUrl)); |
497 EXPECT_EQ(IfExtensionsIsolated(2, 1), | 478 EXPECT_EQ(IfExtensionsIsolated(2, 1), |
498 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 479 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
499 | 480 |
500 // ... and take down the tab. The extension process is not part of the tab, | 481 // ... and take down the tab. The extension process is not part of the tab, |
501 // so it should be kept alive (minus the frames that died). | 482 // so it should be kept alive (minus the frames that died). |
502 content::CrashTab(tab); | 483 content::CrashTab(tab); |
503 EXPECT_EQ(1u, pm->GetAllFrames().size()); | 484 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
504 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); | 485 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
505 } | 486 } |
506 | 487 |
(...skipping 27 matching lines...) Expand all Loading... |
534 pm->OnNetworkRequestDone(frame_host, 1); | 515 pm->OnNetworkRequestDone(frame_host, 1); |
535 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 516 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
536 | 517 |
537 // Simulate only a request completion for this ID and ensure it doesn't result | 518 // Simulate only a request completion for this ID and ensure it doesn't result |
538 // in keepalive decrement. | 519 // in keepalive decrement. |
539 pm->OnNetworkRequestDone(frame_host, 2); | 520 pm->OnNetworkRequestDone(frame_host, 2); |
540 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 521 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
541 } | 522 } |
542 | 523 |
543 } // namespace extensions | 524 } // namespace extensions |
OLD | NEW |