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" |
| 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/run_loop.h" |
| 10 #include "base/strings/stringprintf.h" |
7 #include "chrome/browser/extensions/browser_action_test_util.h" | 11 #include "chrome/browser/extensions/browser_action_test_util.h" |
8 #include "chrome/browser/extensions/extension_browsertest.h" | 12 #include "chrome/browser/extensions/extension_browsertest.h" |
9 #include "chrome/browser/extensions/extension_service.h" | 13 #include "chrome/browser/extensions/extension_service.h" |
| 14 #include "chrome/browser/extensions/test_extension_dir.h" |
10 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 15 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 16 #include "chrome/common/extensions/extension_process_policy.h" |
11 #include "chrome/test/base/in_process_browser_test.h" | 17 #include "chrome/test/base/in_process_browser_test.h" |
12 #include "chrome/test/base/ui_test_utils.h" | 18 #include "chrome/test/base/ui_test_utils.h" |
13 #include "content/public/browser/notification_service.h" | 19 #include "content/public/browser/notification_service.h" |
| 20 #include "content/public/browser/render_frame_host.h" |
14 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 22 #include "content/public/test/browser_test_utils.h" |
15 #include "content/public/test/test_utils.h" | 23 #include "content/public/test/test_utils.h" |
| 24 #include "extensions/common/value_builder.h" |
| 25 #include "extensions/test/background_page_watcher.h" |
| 26 #include "extensions/test/extension_test_message_listener.h" |
16 #include "net/dns/mock_host_resolver.h" | 27 #include "net/dns/mock_host_resolver.h" |
17 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
18 | 29 |
19 namespace extensions { | 30 namespace extensions { |
20 | 31 |
| 32 namespace { |
| 33 |
| 34 void AddFrameToSet(std::set<content::RenderFrameHost*>* frames, |
| 35 content::RenderFrameHost* rfh) { |
| 36 if (rfh->IsRenderFrameLive()) |
| 37 frames->insert(rfh); |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
| 42 // Takes a snapshot of all frames upon construction. When Wait() is called, a |
| 43 // MessageLoop is created and Quit when all previously recorded frames are |
| 44 // either present in the tab, or deleted. If a navigation happens between the |
| 45 // construction and the Wait() call, then this logic ensures that all obsolete |
| 46 // RenderFrameHosts have been destructed when Wait() returns. |
| 47 // See also the comment at ProcessManagerBrowserTest::NavigateToURL. |
| 48 class NavigationCompletedObserver : public content::WebContentsObserver { |
| 49 public: |
| 50 explicit NavigationCompletedObserver(content::WebContents* web_contents) |
| 51 : content::WebContentsObserver(web_contents), |
| 52 message_loop_runner_(new content::MessageLoopRunner) { |
| 53 web_contents->ForEachFrame( |
| 54 base::Bind(&AddFrameToSet, base::Unretained(&frames_))); |
| 55 } |
| 56 |
| 57 void Wait() { |
| 58 if (!AreAllFramesInTab()) |
| 59 message_loop_runner_->Run(); |
| 60 } |
| 61 |
| 62 void RenderFrameDeleted(content::RenderFrameHost* rfh) override { |
| 63 if (frames_.erase(rfh) != 0 && message_loop_runner_->loop_running() && |
| 64 AreAllFramesInTab()) |
| 65 message_loop_runner_->Quit(); |
| 66 } |
| 67 |
| 68 private: |
| 69 // Check whether all frames that were recorded at the construction of this |
| 70 // class are still part of the tab. |
| 71 bool AreAllFramesInTab() { |
| 72 std::set<content::RenderFrameHost*> current_frames; |
| 73 web_contents()->ForEachFrame( |
| 74 base::Bind(&AddFrameToSet, base::Unretained(¤t_frames))); |
| 75 for (content::RenderFrameHost* frame : frames_) { |
| 76 if (current_frames.find(frame) == current_frames.end()) |
| 77 return false; |
| 78 } |
| 79 return true; |
| 80 } |
| 81 |
| 82 std::set<content::RenderFrameHost*> frames_; |
| 83 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| 84 |
| 85 DISALLOW_COPY_AND_ASSIGN(NavigationCompletedObserver); |
| 86 }; |
| 87 |
21 // Exists as a browser test because ExtensionHosts are hard to create without | 88 // Exists as a browser test because ExtensionHosts are hard to create without |
22 // a real browser. | 89 // a real browser. |
23 typedef ExtensionBrowserTest ProcessManagerBrowserTest; | 90 class ProcessManagerBrowserTest : public ExtensionBrowserTest { |
| 91 public: |
| 92 // Create an extension with web-accessible frames and an optional background |
| 93 // page. |
| 94 const Extension* CreateExtension(const std::string& name, |
| 95 bool has_background_process) { |
| 96 scoped_ptr<TestExtensionDir> dir(new TestExtensionDir()); |
| 97 |
| 98 DictionaryBuilder manifest; |
| 99 manifest.Set("name", name) |
| 100 .Set("version", "1") |
| 101 .Set("manifest_version", 2) |
| 102 // To allow ExecuteScript* to work. |
| 103 .Set("content_security_policy", |
| 104 "script-src 'self' 'unsafe-eval'; object-src 'self'") |
| 105 .Set("sandbox", DictionaryBuilder().Set( |
| 106 "pages", ListBuilder().Append("sandboxed.html"))) |
| 107 .Set("web_accessible_resources", ListBuilder().Append("*")); |
| 108 |
| 109 if (has_background_process) { |
| 110 manifest.Set("background", DictionaryBuilder().Set("page", "bg.html")); |
| 111 dir->WriteFile(FILE_PATH_LITERAL("bg.html"), |
| 112 "<iframe id='bgframe' src='empty.html'></iframe>"); |
| 113 } |
| 114 |
| 115 dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"), |
| 116 "<iframe id='frame0' src='about:blank'></iframe>"); |
| 117 |
| 118 dir->WriteFile(FILE_PATH_LITERAL("srcdoc_iframe.html"), |
| 119 "<iframe id='frame0' srcdoc='Hello world'></iframe>"); |
| 120 |
| 121 dir->WriteFile(FILE_PATH_LITERAL("two_iframes.html"), |
| 122 "<iframe id='frame1' src='empty.html'></iframe>" |
| 123 "<iframe id='frame2' src='empty.html'></iframe>"); |
| 124 |
| 125 dir->WriteFile(FILE_PATH_LITERAL("sandboxed.html"), "Some sandboxed page"); |
| 126 |
| 127 dir->WriteFile(FILE_PATH_LITERAL("empty.html"), ""); |
| 128 |
| 129 dir->WriteManifest(manifest.ToJSON()); |
| 130 |
| 131 const Extension* extension = LoadExtension(dir->unpacked_path()); |
| 132 EXPECT_TRUE(extension); |
| 133 temp_dirs_.push_back(dir.Pass()); |
| 134 return extension; |
| 135 } |
| 136 |
| 137 // ui_test_utils::NavigateToURL sometimes returns too early: It returns as |
| 138 // soon as the StopLoading notification has been triggered. This does not |
| 139 // imply that RenderFrameDeleted was called, so the test may continue too |
| 140 // early and fail when ProcessManager::GetAllFrames() returns too many frames |
| 141 // (namely frames that are in the process of being deleted). To work around |
| 142 // this problem, we also wait until all previous frames have been deleted. |
| 143 void NavigateToURL(const GURL& url) { |
| 144 NavigationCompletedObserver observer( |
| 145 browser()->tab_strip_model()->GetActiveWebContents()); |
| 146 |
| 147 ui_test_utils::NavigateToURL(browser(), url); |
| 148 |
| 149 // Wait until the last RenderFrameHosts are deleted. This wait doesn't take |
| 150 // long. |
| 151 observer.Wait(); |
| 152 } |
| 153 |
| 154 void NavigateIframeToURLAndWait(content::WebContents* web_contents, |
| 155 const std::string iframe_id, |
| 156 const GURL& url) { |
| 157 // This is an improved version of content::NavigateIframeToURL. Unlike the |
| 158 // other method, this does actually wait until the load of all child frames |
| 159 // completes. |
| 160 std::string script = base::StringPrintf( |
| 161 "var frame = document.getElementById('%s');" |
| 162 "frame.onload = frame.onerror = function(event) {" |
| 163 " frame.onload = frame.onerror = null;" |
| 164 " domAutomationController.send(event.type === 'load');" |
| 165 "};" |
| 166 "frame.src = '%s';", |
| 167 iframe_id.c_str(), url.spec().c_str()); |
| 168 bool is_loaded = false; |
| 169 EXPECT_TRUE(ExecuteScriptAndExtractBool(web_contents, script, &is_loaded)); |
| 170 EXPECT_TRUE(is_loaded); |
| 171 } |
| 172 |
| 173 size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) { |
| 174 return content::AreAllSitesIsolatedForTesting() || |
| 175 IsIsolateExtensionsEnabled() |
| 176 ? if_enabled |
| 177 : if_disabled; |
| 178 } |
| 179 |
| 180 private: |
| 181 std::vector<scoped_ptr<TestExtensionDir>> temp_dirs_; |
| 182 }; |
24 | 183 |
25 // Test that basic extension loading creates the appropriate ExtensionHosts | 184 // Test that basic extension loading creates the appropriate ExtensionHosts |
26 // and background pages. | 185 // and background pages. |
27 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, | 186 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
28 ExtensionHostCreation) { | 187 ExtensionHostCreation) { |
29 ProcessManager* pm = ProcessManager::Get(profile()); | 188 ProcessManager* pm = ProcessManager::Get(profile()); |
30 | 189 |
31 // We start with no background hosts. | 190 // We start with no background hosts. |
32 ASSERT_EQ(0u, pm->background_hosts().size()); | 191 ASSERT_EQ(0u, pm->background_hosts().size()); |
33 ASSERT_EQ(0u, pm->GetAllFrames().size()); | 192 ASSERT_EQ(0u, pm->GetAllFrames().size()); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 content::WebContents* extension_web_contents = | 309 content::WebContents* extension_web_contents = |
151 content::WebContents::FromRenderFrameHost( | 310 content::WebContents::FromRenderFrameHost( |
152 *pm->GetRenderFrameHostsForExtension(extension->id()).begin()); | 311 *pm->GetRenderFrameHostsForExtension(extension->id()).begin()); |
153 EXPECT_TRUE(extension_web_contents->GetSiteInstance() != | 312 EXPECT_TRUE(extension_web_contents->GetSiteInstance() != |
154 tab_web_contents->GetSiteInstance()); | 313 tab_web_contents->GetSiteInstance()); |
155 EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url()) != | 314 EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url()) != |
156 tab_web_contents->GetSiteInstance()); | 315 tab_web_contents->GetSiteInstance()); |
157 EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id())); | 316 EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id())); |
158 } | 317 } |
159 | 318 |
| 319 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, NoBackgroundPage) { |
| 320 ASSERT_TRUE(embedded_test_server()->Start()); |
| 321 |
| 322 ProcessManager* pm = ProcessManager::Get(profile()); |
| 323 const Extension* extension = |
| 324 LoadExtension(test_data_dir_.AppendASCII("api_test") |
| 325 .AppendASCII("messaging") |
| 326 .AppendASCII("connect_nobackground")); |
| 327 ASSERT_TRUE(extension); |
| 328 |
| 329 // The extension has no background page. |
| 330 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 331 |
| 332 // Start in a non-extension process, then navigate to an extension process. |
| 333 NavigateToURL(embedded_test_server()->GetURL("/empty.html")); |
| 334 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 335 |
| 336 const GURL extension_url = extension->url().Resolve("manifest.json"); |
| 337 NavigateToURL(extension_url); |
| 338 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 339 |
| 340 NavigateToURL(GURL("about:blank")); |
| 341 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 342 |
| 343 ui_test_utils::NavigateToURLWithDisposition( |
| 344 browser(), extension_url, NEW_FOREGROUND_TAB, |
| 345 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 346 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 347 } |
| 348 |
| 349 // Tests whether frames are correctly classified. Non-extension frames should |
| 350 // never appear in the list. Top-level extension frames should always appear. |
| 351 // Child extension frames should only appear if it is hosted in an extension |
| 352 // process (i.e. if the top-level frame is an extension page, or if OOP frames |
| 353 // are enabled for extensions). |
| 354 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, FrameClassification) { |
| 355 const Extension* extension1 = CreateExtension("Extension 1", false); |
| 356 const Extension* extension2 = CreateExtension("Extension 2", true); |
| 357 embedded_test_server()->ServeFilesFromDirectory(extension1->path()); |
| 358 ASSERT_TRUE(embedded_test_server()->Start()); |
| 359 |
| 360 const GURL kExt1TwoFramesUrl(extension1->url().Resolve("two_iframes.html")); |
| 361 const GURL kExt1EmptyUrl(extension1->url().Resolve("empty.html")); |
| 362 const GURL kExt2TwoFramesUrl(extension2->url().Resolve("two_iframes.html")); |
| 363 const GURL kExt2EmptyUrl(extension2->url().Resolve("empty.html")); |
| 364 |
| 365 ProcessManager* pm = ProcessManager::Get(profile()); |
| 366 |
| 367 // 1 background page + 1 frame in background page from Extension 2. |
| 368 BackgroundPageWatcher(pm, extension2).WaitForOpen(); |
| 369 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
| 370 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 371 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 372 |
| 373 ExecuteScriptInBackgroundPageNoWait(extension2->id(), |
| 374 "setTimeout(window.close, 0)"); |
| 375 BackgroundPageWatcher(pm, extension2).WaitForClose(); |
| 376 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 377 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 378 |
| 379 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); |
| 380 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 381 |
| 382 content::WebContents* tab = |
| 383 browser()->tab_strip_model()->GetActiveWebContents(); |
| 384 |
| 385 // Tests extension frames in non-extension page. |
| 386 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); |
| 387 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 388 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 389 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); |
| 390 |
| 391 NavigateIframeToURLAndWait(tab, "frame2", kExt2EmptyUrl); |
| 392 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 393 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 394 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); |
| 395 |
| 396 // Tests non-extension page in extension frame. |
| 397 NavigateToURL(kExt1TwoFramesUrl); |
| 398 // 1 top-level + 2 child frames from Extension 1. |
| 399 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
| 400 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 401 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 402 |
| 403 NavigateIframeToURLAndWait(tab, "frame1", |
| 404 embedded_test_server()->GetURL("/empty.html")); |
| 405 // 1 top-level + 1 child frame from Extension 1. |
| 406 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 407 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
| 408 |
| 409 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); |
| 410 // 1 top-level + 2 child frames from Extension 1. |
| 411 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
| 412 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 413 |
| 414 // Load a frame from another extension. |
| 415 NavigateIframeToURLAndWait(tab, "frame1", kExt2EmptyUrl); |
| 416 // 1 top-level + 1 child frame from Extension 1, |
| 417 // 1 child frame from Extension 2. |
| 418 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); |
| 419 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 420 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 421 pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 422 |
| 423 // Destroy all existing frames by navigating to another extension. |
| 424 NavigateToURL(extension2->url().Resolve("empty.html")); |
| 425 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 426 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 427 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 428 |
| 429 // Test about:blank and about:srcdoc child frames. |
| 430 NavigateToURL(extension2->url().Resolve("srcdoc_iframe.html")); |
| 431 // 1 top-level frame + 1 child frame from Extension 2. |
| 432 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
| 433 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 434 |
| 435 NavigateToURL(extension2->url().Resolve("blank_iframe.html")); |
| 436 // 1 top-level frame + 1 child frame from Extension 2. |
| 437 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
| 438 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 439 |
| 440 // Sandboxed frames are not viewed as extension frames. |
| 441 NavigateIframeToURLAndWait(tab, "frame0", |
| 442 extension2->url().Resolve("sandboxed.html")); |
| 443 // 1 top-level frame from Extension 2. |
| 444 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 445 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 446 |
| 447 NavigateToURL(extension2->url().Resolve("sandboxed.html")); |
| 448 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 449 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 450 |
| 451 // Test nested frames (same extension). |
| 452 NavigateToURL(kExt2TwoFramesUrl); |
| 453 // 1 top-level + 2 child frames from Extension 2. |
| 454 EXPECT_EQ(3u, pm->GetAllFrames().size()); |
| 455 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 456 |
| 457 NavigateIframeToURLAndWait(tab, "frame1", kExt2TwoFramesUrl); |
| 458 // 1 top-level + 2 child frames from Extension 1, |
| 459 // 2 child frames in frame1 from Extension 2. |
| 460 EXPECT_EQ(5u, pm->GetAllFrames().size()); |
| 461 EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 462 |
| 463 // The extension frame from the other extension should not be classified as an |
| 464 // extension (unless out-of-process frames are enabled). |
| 465 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); |
| 466 // 1 top-level + 1 child frames from Extension 2, |
| 467 // 1 child frame from Extension 1. |
| 468 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); |
| 469 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 470 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 471 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 472 |
| 473 NavigateIframeToURLAndWait(tab, "frame2", kExt1TwoFramesUrl); |
| 474 // 1 top-level + 1 child frames from Extension 2, |
| 475 // 1 child frame + 2 child frames in frame2 from Extension 1. |
| 476 EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size()); |
| 477 EXPECT_EQ(IfExtensionsIsolated(4, 0), |
| 478 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 479 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 480 |
| 481 // Crash tab where the top-level frame is an extension frame. |
| 482 content::CrashTab(tab); |
| 483 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 484 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 485 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); |
| 486 |
| 487 // Now load an extension page and a non-extension page... |
| 488 ui_test_utils::NavigateToURLWithDisposition( |
| 489 browser(), kExt1EmptyUrl, NEW_BACKGROUND_TAB, |
| 490 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 491 NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); |
| 492 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 493 |
| 494 // ... load an extension frame in the non-extension process |
| 495 NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); |
| 496 EXPECT_EQ(IfExtensionsIsolated(2, 1), |
| 497 pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 498 |
| 499 // ... and take down the tab. The extension process is not part of the tab, |
| 500 // so it should be kept alive (minus the frames that died). |
| 501 content::CrashTab(tab); |
| 502 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 503 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); |
| 504 } |
| 505 |
160 // Verify correct keepalive count behavior on network request events. | 506 // Verify correct keepalive count behavior on network request events. |
161 // Regression test for http://crbug.com/535716. | 507 // Regression test for http://crbug.com/535716. |
162 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) { | 508 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) { |
163 // Load an extension with a lazy background page. | 509 // Load an extension with a lazy background page. |
164 scoped_refptr<const Extension> extension = | 510 scoped_refptr<const Extension> extension = |
165 LoadExtension(test_data_dir_.AppendASCII("api_test") | 511 LoadExtension(test_data_dir_.AppendASCII("api_test") |
166 .AppendASCII("lazy_background_page") | 512 .AppendASCII("lazy_background_page") |
167 .AppendASCII("broadcast_event")); | 513 .AppendASCII("broadcast_event")); |
168 ASSERT_TRUE(extension.get()); | 514 ASSERT_TRUE(extension.get()); |
169 | 515 |
(...skipping 17 matching lines...) Expand all Loading... |
187 pm->OnNetworkRequestDone(frame_host, 1); | 533 pm->OnNetworkRequestDone(frame_host, 1); |
188 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 534 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
189 | 535 |
190 // Simulate only a request completion for this ID and ensure it doesn't result | 536 // Simulate only a request completion for this ID and ensure it doesn't result |
191 // in keepalive decrement. | 537 // in keepalive decrement. |
192 pm->OnNetworkRequestDone(frame_host, 2); | 538 pm->OnNetworkRequestDone(frame_host, 2); |
193 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 539 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
194 } | 540 } |
195 | 541 |
196 } // namespace extensions | 542 } // namespace extensions |
OLD | NEW |