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/path_service.h" |
| 8 #include "base/strings/stringprintf.h" |
7 #include "chrome/browser/extensions/browser_action_test_util.h" | 9 #include "chrome/browser/extensions/browser_action_test_util.h" |
8 #include "chrome/browser/extensions/extension_browsertest.h" | 10 #include "chrome/browser/extensions/extension_browsertest.h" |
9 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
| 12 #include "chrome/browser/extensions/test_extension_dir.h" |
10 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 13 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 14 #include "chrome/common/extensions/extension_process_policy.h" |
11 #include "chrome/test/base/in_process_browser_test.h" | 15 #include "chrome/test/base/in_process_browser_test.h" |
12 #include "chrome/test/base/ui_test_utils.h" | 16 #include "chrome/test/base/ui_test_utils.h" |
13 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
14 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
| 19 #include "content/public/test/browser_test_utils.h" |
15 #include "content/public/test/test_utils.h" | 20 #include "content/public/test/test_utils.h" |
| 21 #include "extensions/common/value_builder.h" |
16 #include "net/dns/mock_host_resolver.h" | 22 #include "net/dns/mock_host_resolver.h" |
17 #include "net/test/embedded_test_server/embedded_test_server.h" | 23 #include "net/test/embedded_test_server/embedded_test_server.h" |
18 | 24 |
| 25 using content::WebContents; |
| 26 |
19 namespace extensions { | 27 namespace extensions { |
20 | 28 |
21 // Exists as a browser test because ExtensionHosts are hard to create without | 29 // Exists as a browser test because ExtensionHosts are hard to create without |
22 // a real browser. | 30 // a real browser. |
23 typedef ExtensionBrowserTest ProcessManagerBrowserTest; | 31 class ProcessManagerBrowserTest : public ExtensionBrowserTest { |
| 32 public: |
| 33 void SetUpOnMainThread() override { |
| 34 host_resolver()->AddRule("*", "127.0.0.1"); |
| 35 |
| 36 // Add content/test/data so we can use cross_site_iframe_factory.html |
| 37 base::FilePath test_data_dir; |
| 38 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir)); |
| 39 embedded_test_server()->ServeFilesFromDirectory( |
| 40 test_data_dir.AppendASCII("content/test/data/")); |
| 41 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| 42 } |
| 43 |
| 44 // Create and install an extension that has a couple of web-accessible |
| 45 // resources and, optionally, a background process. |
| 46 const Extension* CreateExtension(const std::string& name, |
| 47 bool has_background_process) { |
| 48 scoped_ptr<TestExtensionDir> dir(new TestExtensionDir); |
| 49 |
| 50 DictionaryBuilder manifest; |
| 51 manifest.Set("name", name) |
| 52 .Set("version", "1.0") |
| 53 .Set("manifest_version", 2) |
| 54 .Set("web_accessible_resources", ListBuilder() |
| 55 .Append("blank_iframe.html") |
| 56 .Append("http_iframe.html") |
| 57 .Append("two_http_iframes.html")); |
| 58 |
| 59 if (has_background_process) { |
| 60 manifest.Set("background", |
| 61 DictionaryBuilder().Set("scripts", |
| 62 ListBuilder().Append("script.js"))); |
| 63 dir->WriteFile(FILE_PATH_LITERAL("script.js"), |
| 64 "console.log('" + name + " running');"); |
| 65 } |
| 66 |
| 67 dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"), |
| 68 base::StringPrintf("<html><body>%s, blank iframe:" |
| 69 " <iframe width=80 height=80></iframe>" |
| 70 "</body></html>", |
| 71 name.c_str())); |
| 72 std::string iframe_url = |
| 73 embedded_test_server() |
| 74 ->GetURL("w.com", "/cross_site_iframe_factory.html?w") |
| 75 .spec(); |
| 76 std::string iframe_url2 = |
| 77 embedded_test_server() |
| 78 ->GetURL("x.com", "/cross_site_iframe_factory.html?x") |
| 79 .spec(); |
| 80 dir->WriteFile( |
| 81 FILE_PATH_LITERAL("http_iframe.html"), |
| 82 base::StringPrintf("<html><body>%s, http:// iframe:" |
| 83 " <iframe width=80 height=80 src='%s'></iframe>" |
| 84 "</body></html>", |
| 85 name.c_str(), iframe_url.c_str())); |
| 86 dir->WriteFile(FILE_PATH_LITERAL("two_http_iframes.html"), |
| 87 base::StringPrintf( |
| 88 "<html><body>%s, two http:// iframes:" |
| 89 " <iframe width=80 height=80 src='%s'></iframe>" |
| 90 " <iframe width=80 height=80 src='%s'></iframe>" |
| 91 "</body></html>", |
| 92 name.c_str(), iframe_url.c_str(), iframe_url2.c_str())); |
| 93 dir->WriteManifest(manifest.ToJSON()); |
| 94 |
| 95 const Extension* extension = LoadExtension(dir->unpacked_path()); |
| 96 EXPECT_TRUE(extension); |
| 97 temp_dirs_.push_back(dir.release()); |
| 98 return extension; |
| 99 } |
| 100 |
| 101 int IfExtensionsIsolated(int value) { |
| 102 if (content::AreAllSitesIsolatedForTesting() || |
| 103 IsIsolateExtensionsEnabled()) { |
| 104 return value; |
| 105 } |
| 106 return 0; |
| 107 } |
| 108 |
| 109 private: |
| 110 ScopedVector<TestExtensionDir> temp_dirs_; |
| 111 }; |
24 | 112 |
25 // Test that basic extension loading creates the appropriate ExtensionHosts | 113 // Test that basic extension loading creates the appropriate ExtensionHosts |
26 // and background pages. | 114 // and background pages. |
27 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, | 115 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
28 ExtensionHostCreation) { | 116 ExtensionHostCreation) { |
29 ProcessManager* pm = ProcessManager::Get(profile()); | 117 ProcessManager* pm = ProcessManager::Get(profile()); |
30 | 118 |
31 // We start with no background hosts. | 119 // We start with no background hosts. |
32 ASSERT_EQ(0u, pm->background_hosts().size()); | 120 ASSERT_EQ(0u, pm->background_hosts().size()); |
33 ASSERT_EQ(0u, pm->GetAllFrames().size()); | 121 ASSERT_EQ(0u, pm->GetAllFrames().size()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 EXPECT_EQ(baseline_keepalive + 1, pm->GetLazyKeepaliveCount(extension.get())); | 274 EXPECT_EQ(baseline_keepalive + 1, pm->GetLazyKeepaliveCount(extension.get())); |
187 pm->OnNetworkRequestDone(frame_host, 1); | 275 pm->OnNetworkRequestDone(frame_host, 1); |
188 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 276 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
189 | 277 |
190 // Simulate only a request completion for this ID and ensure it doesn't result | 278 // Simulate only a request completion for this ID and ensure it doesn't result |
191 // in keepalive decrement. | 279 // in keepalive decrement. |
192 pm->OnNetworkRequestDone(frame_host, 2); | 280 pm->OnNetworkRequestDone(frame_host, 2); |
193 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); | 281 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); |
194 } | 282 } |
195 | 283 |
| 284 // Tests which RenderFrameHosts are tracked by ProcessManager, including: |
| 285 // http iframes inside of extension pages, extension iframes inside of extension |
| 286 // pages, and about:blank iframes inside of extension content. |
| 287 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, FrameClassification) { |
| 288 // The expections here assume that we wish to have the ProcessManager |
| 289 // distinguish between extension vs. non-extension frames in extension |
| 290 // processes. This test exercises about:blank cases that will be hard for |
| 291 // the ProcessManager to get right, until |
| 292 // https://code.google.com/p/chromium/issues/detail?id=498580 is fixed, and |
| 293 // the ProcessManager is made to query the effective origin. |
| 294 ProcessManager* pm = ProcessManager::Get(profile()); |
| 295 |
| 296 size_t expected_extension_frames = 0; |
| 297 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 298 |
| 299 // Install one script-injecting extension with background page, and an |
| 300 // extension with web accessible resources. |
| 301 const Extension* extension1 = CreateExtension("Extension One", true); |
| 302 |
| 303 expected_extension_frames += 1; // extension 1 background page |
| 304 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 305 |
| 306 const Extension* extension2 = CreateExtension("Extension Two", false); |
| 307 expected_extension_frames += 0; // extension 2 / no background page |
| 308 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 309 |
| 310 // Open two a.com tabs (with cross site http iframes). IsolateExtensions mode |
| 311 // should have no effect so far, since there are no frames straddling the |
| 312 // extension/web boundary. |
| 313 GURL tab1_url = embedded_test_server()->GetURL( |
| 314 "a.com", "/cross_site_iframe_factory.html?a(b,c)"); |
| 315 ui_test_utils::NavigateToURL(browser(), tab1_url); |
| 316 |
| 317 expected_extension_frames += 0; // only http frames added to tab1 |
| 318 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 319 |
| 320 WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(0); |
| 321 GURL tab2_url = embedded_test_server()->GetURL( |
| 322 "a.com", "/cross_site_iframe_factory.html?a(d,e)"); |
| 323 AddTabAtIndex(1, tab2_url, ui::PAGE_TRANSITION_TYPED); |
| 324 WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(1); |
| 325 |
| 326 expected_extension_frames += 0; // only http frames added to tab2 |
| 327 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 328 |
| 329 // Tab1 navigates its first iframe to a resource of extension1. |
| 330 content::NavigateIframeToURL( |
| 331 tab1, "child-0", extension1->GetResourceURL("/blank_iframe.html")); |
| 332 |
| 333 expected_extension_frames += IfExtensionsIsolated(2); // A frame and its blan
k child. |
| 334 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 335 |
| 336 // Tab2 navigates its first iframe to a resource of extension1. |
| 337 content::NavigateIframeToURL( |
| 338 tab2, "child-0", extension1->GetResourceURL("/blank_iframe.html")); |
| 339 |
| 340 expected_extension_frames += IfExtensionsIsolated(2); // A frame and its blan
k child. |
| 341 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 342 |
| 343 // Tab1 navigates its second iframe to a resource of extension2. |
| 344 content::NavigateIframeToURL( |
| 345 tab1, "child-1", extension2->GetResourceURL("/blank_iframe.html")); |
| 346 |
| 347 expected_extension_frames += IfExtensionsIsolated(2); // A frame and its blan
k child. |
| 348 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 349 |
| 350 // Tab2 navigates its second iframe to a resource of extension2. |
| 351 content::NavigateIframeToURL( |
| 352 tab2, "child-1", extension2->GetResourceURL("/blank_iframe.html")); |
| 353 |
| 354 expected_extension_frames += IfExtensionsIsolated(2); // A frame and its blan
k child. |
| 355 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 356 |
| 357 // Install extension3 (identical config to extension2) |
| 358 const Extension* extension3 = CreateExtension("Extension Three", false); |
| 359 |
| 360 expected_extension_frames += 0; // No background page. |
| 361 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 362 |
| 363 // Navigate Tab2 to a top-level page from extension3. |
| 364 ui_test_utils::NavigateToURL(browser(), |
| 365 extension3->GetResourceURL("blank_iframe.html")); |
| 366 |
| 367 expected_extension_frames -= IfExtensionsIsolated(4); // Old children. |
| 368 expected_extension_frames += 2; // New page and its child, always in extensio
n process. |
| 369 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 370 |
| 371 // Navigate tab2 to a different extension3 page containing a web iframe. |
| 372 ui_test_utils::NavigateToURL(browser(), |
| 373 extension3->GetResourceURL("http_iframe.html")); |
| 374 |
| 375 expected_extension_frames -= 1; // http iframe is not an extension frame. |
| 376 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 377 |
| 378 browser()->tab_strip_model()->ActivateTabAt(0, true); |
| 379 ui_test_utils::NavigateToURL(browser(), |
| 380 GURL("about:blank")); |
| 381 |
| 382 expected_extension_frames -= IfExtensionsIsolated(4); |
| 383 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 384 |
| 385 ui_test_utils::NavigateToURL(browser(), |
| 386 extension2->GetResourceURL("/two_http_iframes.htm
l")); |
| 387 expected_extension_frames += 1; |
| 388 EXPECT_EQ(expected_extension_frames, pm->GetAllFrames().size()); |
| 389 } |
| 390 |
196 } // namespace extensions | 391 } // namespace extensions |
OLD | NEW |