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

Side by Side Diff: chrome/browser/extensions/process_manager_browsertest.cc

Issue 1413853005: Track all extension frames in ProcessManager, inspect extensionoptions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: include extension_process_policy.h Created 5 years, 1 month 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
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/strings/stringprintf.h"
7 #include "chrome/browser/extensions/browser_action_test_util.h" 8 #include "chrome/browser/extensions/browser_action_test_util.h"
8 #include "chrome/browser/extensions/extension_browsertest.h" 9 #include "chrome/browser/extensions/extension_browsertest.h"
9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/test_extension_dir.h"
10 #include "chrome/browser/ui/tabs/tab_strip_model.h" 12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/common/extensions/extension_process_policy.h"
11 #include "chrome/test/base/in_process_browser_test.h" 14 #include "chrome/test/base/in_process_browser_test.h"
12 #include "chrome/test/base/ui_test_utils.h" 15 #include "chrome/test/base/ui_test_utils.h"
13 #include "content/public/browser/notification_service.h" 16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_frame_host.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"
22 #include "extensions/test/background_page_watcher.h"
23 #include "extensions/test/extension_test_message_listener.h"
16 #include "net/dns/mock_host_resolver.h" 24 #include "net/dns/mock_host_resolver.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h" 25 #include "net/test/embedded_test_server/embedded_test_server.h"
18 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 // Create an extension with web-accessible frames and an optional background
34 // page.
35 const Extension* CreateExtension(const std::string& name,
36 bool has_background_process) {
37 scoped_ptr<TestExtensionDir> dir(new TestExtensionDir);
38
39 DictionaryBuilder manifest;
40 manifest.Set("name", name)
41 .Set("version", "1")
42 .Set("manifest_version", 2)
43 // To allow ExecuteScript* to work.
44 .Set("content_security_policy",
45 "script-src 'self' 'unsafe-eval'; object-src 'self'")
46 .Set("web_accessible_resources", ListBuilder().Append("*"));
47
48 if (has_background_process) {
49 manifest.Set("background", DictionaryBuilder().Set("page", "bg.html"));
50 dir->WriteFile(FILE_PATH_LITERAL("bg.html"),
51 "<iframe id=bgframe src=empty.html></iframe>");
52 }
53
54 dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"),
55 "<iframe id=frame0 src='about:blank'></iframe>");
56
57 dir->WriteFile(FILE_PATH_LITERAL("srcdoc_iframe.html"),
58 "<iframe id=frame0 srcdoc='Hello world'></iframe>");
59
60 dir->WriteFile(FILE_PATH_LITERAL("two_iframes.html"),
61 "<iframe id=frame1 src=empty.html></iframe>"
62 "<iframe id=frame2 src=empty.html></iframe>");
63
64 dir->WriteFile(FILE_PATH_LITERAL("empty.html"), "");
65
66 dir->WriteManifest(manifest.ToJSON());
67
68 const Extension* extension = LoadExtension(dir->unpacked_path());
69 EXPECT_TRUE(extension);
70 temp_dirs_.push_back(dir.release());
71 return extension;
72 }
73
74 void NavigateIframeToURLAndWait(content::WebContents* web_contents,
75 const std::string iframe_id,
76 const GURL& url) {
77 // This is an improved version of content::NavigateIframeToURL. Unlike the
78 // other method, this does actually wait until the load of all child frames
79 // completes.
80 std::string script = base::StringPrintf(
81 "var frame = document.getElementById('%s');"
82 "frame.onload = frame.onerror = function(event) {"
83 " frame.onload = frame.onerror = null;"
84 " domAutomationController.send(event.type === 'load');"
85 "};"
86 "frame.src = '%s';",
87 iframe_id.c_str(), url.spec().c_str());
88 bool is_loaded = false;
89 EXPECT_TRUE(ExecuteScriptAndExtractBool(web_contents, script, &is_loaded));
90 EXPECT_TRUE(is_loaded);
ncarter (slow) 2015/11/24 05:22:13 I had a chat with creis, and we'd probably be fine
robwu 2015/11/25 00:44:16 I'll do that in a separate CL to make sure that bi
91 }
92
93 size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) {
94 return content::AreAllSitesIsolatedForTesting() ||
95 IsIsolateExtensionsEnabled() ? if_enabled : if_disabled;
96 }
97
98 private:
99 ScopedVector<TestExtensionDir> temp_dirs_;
ncarter (slow) 2015/11/24 05:22:13 std::vector<scoped_ptr<TestExtensionDir>> Since w
robwu 2015/11/25 00:44:17 Done.
100
ncarter (slow) 2015/11/24 05:22:13 nit: no blank line
robwu 2015/11/25 00:44:16 Done.
101 };
24 102
25 // Test that basic extension loading creates the appropriate ExtensionHosts 103 // Test that basic extension loading creates the appropriate ExtensionHosts
26 // and background pages. 104 // and background pages.
27 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, 105 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
28 ExtensionHostCreation) { 106 ExtensionHostCreation) {
29 ProcessManager* pm = ProcessManager::Get(profile()); 107 ProcessManager* pm = ProcessManager::Get(profile());
30 108
31 // We start with no background hosts. 109 // We start with no background hosts.
32 ASSERT_EQ(0u, pm->background_hosts().size()); 110 ASSERT_EQ(0u, pm->background_hosts().size());
33 ASSERT_EQ(0u, pm->GetAllFrames().size()); 111 ASSERT_EQ(0u, pm->GetAllFrames().size());
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 content::WebContents* extension_web_contents = 228 content::WebContents* extension_web_contents =
151 content::WebContents::FromRenderFrameHost( 229 content::WebContents::FromRenderFrameHost(
152 *pm->GetRenderFrameHostsForExtension(extension->id()).begin()); 230 *pm->GetRenderFrameHostsForExtension(extension->id()).begin());
153 EXPECT_TRUE(extension_web_contents->GetSiteInstance() != 231 EXPECT_TRUE(extension_web_contents->GetSiteInstance() !=
154 tab_web_contents->GetSiteInstance()); 232 tab_web_contents->GetSiteInstance());
155 EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url()) != 233 EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url()) !=
156 tab_web_contents->GetSiteInstance()); 234 tab_web_contents->GetSiteInstance());
157 EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id())); 235 EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id()));
158 } 236 }
159 237
238 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, NoBackgroundPage) {
239 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
240
241 ProcessManager* pm = ProcessManager::Get(profile());
242 const Extension* extension =
243 LoadExtension(test_data_dir_.AppendASCII("api_test")
244 .AppendASCII("messaging")
245 .AppendASCII("connect_nobackground"));
246 ASSERT_TRUE(extension);
247
248 // The extension has no background page.
249 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
250
251 // Start in a non-extension process, then navigate to an extension process.
252 ui_test_utils::NavigateToURL(browser(),
253 embedded_test_server()->GetURL("/empty.html"));
254 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
255
256 const GURL extension_url = extension->url().Resolve("manifest.json");
257 ui_test_utils::NavigateToURL(browser(), extension_url);
258 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
259
260 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
261 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
262
263 ui_test_utils::NavigateToURLWithDisposition(
264 browser(), extension_url, NEW_FOREGROUND_TAB,
265 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
266 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
267 }
268
269 // Tests whether frames are correctly classified. Non-extension frames should
270 // never appear in the list. Top-level extension frames should always appear.
271 // Child extension frames should only appear if it is hosted in an extension
272 // process (i.e. if the top-level frame is an extension page, or if OOP frames
273 // are enabled for extensions).
274 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, FrameClassification) {
275 const Extension* extension1 = CreateExtension("Extension 1", false);
276 const Extension* extension2 = CreateExtension("Extension 2", true);
277 embedded_test_server()->ServeFilesFromDirectory(extension1->path());
278 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
279
280 const GURL ext1_parent_url(extension1->url().Resolve("two_iframes.html"));
281 const GURL ext1_empty_url(extension1->url().Resolve("empty.html"));
282 const GURL ext2_parent_url(extension2->url().Resolve("two_iframes.html"));
283 const GURL ext2_empty_url(extension2->url().Resolve("empty.html"));
284
285 ProcessManager* pm = ProcessManager::Get(profile());
286 BackgroundPageWatcher(pm, extension2).WaitForOpen();
287
288 EXPECT_EQ(2u, pm->GetAllFrames().size());
289 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
290 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
291
292 ExecuteScriptInBackgroundPageNoWait(extension2->id(),
293 "setTimeout(window.close, 0)");
294 BackgroundPageWatcher(pm, extension2).WaitForClose();
295 EXPECT_EQ(0u, pm->GetAllFrames().size());
296 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
297
298 ui_test_utils::NavigateToURL(
299 browser(), embedded_test_server()->GetURL("/two_iframes.html"));
300 EXPECT_EQ(0u, pm->GetAllFrames().size());
301
302 content::WebContents* tab =
303 browser()->tab_strip_model()->GetActiveWebContents();
304
305 // Tests extension frames in non-extension page.
306 NavigateIframeToURLAndWait(tab, "frame1", ext1_empty_url);
307 EXPECT_EQ(IfExtensionsIsolated(1, 0),
308 pm->GetRenderFrameHostsForExtension(extension1->id()).size());
309 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size());
310
311 NavigateIframeToURLAndWait(tab, "frame2", ext2_empty_url);
312 EXPECT_EQ(IfExtensionsIsolated(1, 0),
313 pm->GetRenderFrameHostsForExtension(extension2->id()).size());
314 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size());
315
316 // Tests non-extension page in extension frame
317 ui_test_utils::NavigateToURL(browser(), ext1_parent_url);
318 EXPECT_EQ(3u, pm->GetAllFrames().size());
319 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
320 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
321
322 NavigateIframeToURLAndWait(tab, "frame1",
323 embedded_test_server()->GetURL("/empty.html"));
324 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
325 EXPECT_EQ(2u, pm->GetAllFrames().size());
326
327 NavigateIframeToURLAndWait(tab, "frame1", ext1_empty_url);
328 EXPECT_EQ(3u, pm->GetAllFrames().size());
329 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
330
331 // Load a frame from another extension.
332 NavigateIframeToURLAndWait(tab, "frame1", ext2_empty_url);
333 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size());
334 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
335 EXPECT_EQ(IfExtensionsIsolated(1, 0),
336 pm->GetRenderFrameHostsForExtension(extension2->id()).size());
337
338 // Destroy all existing frames by navigating to another extension.
339 ui_test_utils::NavigateToURL(browser(),
340 extension2->url().Resolve("empty.html"));
341 EXPECT_EQ(1u, pm->GetAllFrames().size());
342 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
343 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
344
345 // Test about:blank and about:srcdoc child frames.
346 ui_test_utils::NavigateToURL(browser(),
347 extension2->url().Resolve("srcdoc_iframe.html"));
348 EXPECT_EQ(2u, pm->GetAllFrames().size());
349 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
350
351 ui_test_utils::NavigateToURL(browser(),
352 extension2->url().Resolve("blank_iframe.html"));
353 EXPECT_EQ(2u, pm->GetAllFrames().size());
354 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
355
356 // Test nested frames (same extension).
357 ui_test_utils::NavigateToURL(browser(), ext2_parent_url);
358 EXPECT_EQ(3u, pm->GetAllFrames().size());
359 EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
360
361 NavigateIframeToURLAndWait(tab, "frame1", ext2_parent_url);
362 EXPECT_EQ(5u, pm->GetAllFrames().size());
363 EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
364
365 // The extension frame from the other extension should not be classified as an
366 // extension (unless out-of-process frames are enabled).
367 NavigateIframeToURLAndWait(tab, "frame1", ext1_empty_url);
368 EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size());
369 EXPECT_EQ(IfExtensionsIsolated(1, 0),
370 pm->GetRenderFrameHostsForExtension(extension1->id()).size());
371 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
372
373 NavigateIframeToURLAndWait(tab, "frame2", ext1_parent_url);
374 EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size());
375 EXPECT_EQ(IfExtensionsIsolated(4, 0),
376 pm->GetRenderFrameHostsForExtension(extension1->id()).size());
377 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
378
379 // Crash tab where the top-level frame is an extension frame.
380 content::CrashTab(tab);
381 EXPECT_EQ(0u, pm->GetAllFrames().size());
382 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
383 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size());
384
385 // Now load an extension page and a non-extension page...
386 ui_test_utils::NavigateToURLWithDisposition(
387 browser(), ext1_empty_url, NEW_BACKGROUND_TAB,
388 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
389 ui_test_utils::NavigateToURL(
390 browser(), embedded_test_server()->GetURL("/two_iframes.html"));
391 EXPECT_EQ(1u, pm->GetAllFrames().size());
392
393 // ... load an extension frame in the non-extension process
394 NavigateIframeToURLAndWait(tab, "frame1", ext1_empty_url);
395 EXPECT_EQ(IfExtensionsIsolated(2, 1),
396 pm->GetRenderFrameHostsForExtension(extension1->id()).size());
397
398 // ... and take down the tab. The extension process is not part of the tab,
399 // so it should be kept alive (minus the frames that died).
400 content::CrashTab(tab);
401 EXPECT_EQ(1u, pm->GetAllFrames().size());
402 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size());
ncarter (slow) 2015/11/24 05:22:13 This test is awesome.
robwu 2015/11/25 00:44:16 Thanks. It was flaky, and I locally ran the test f
ncarter (slow) 2015/11/30 22:56:45 Good find; I like how you handled it. This makes m
403 }
404
160 // Verify correct keepalive count behavior on network request events. 405 // Verify correct keepalive count behavior on network request events.
161 // Regression test for http://crbug.com/535716. 406 // Regression test for http://crbug.com/535716.
162 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) { 407 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) {
163 // Load an extension with a lazy background page. 408 // Load an extension with a lazy background page.
164 scoped_refptr<const Extension> extension = 409 scoped_refptr<const Extension> extension =
165 LoadExtension(test_data_dir_.AppendASCII("api_test") 410 LoadExtension(test_data_dir_.AppendASCII("api_test")
166 .AppendASCII("lazy_background_page") 411 .AppendASCII("lazy_background_page")
167 .AppendASCII("broadcast_event")); 412 .AppendASCII("broadcast_event"));
168 ASSERT_TRUE(extension.get()); 413 ASSERT_TRUE(extension.get());
169 414
(...skipping 17 matching lines...) Expand all
187 pm->OnNetworkRequestDone(frame_host, 1); 432 pm->OnNetworkRequestDone(frame_host, 1);
188 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); 433 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get()));
189 434
190 // Simulate only a request completion for this ID and ensure it doesn't result 435 // Simulate only a request completion for this ID and ensure it doesn't result
191 // in keepalive decrement. 436 // in keepalive decrement.
192 pm->OnNetworkRequestDone(frame_host, 2); 437 pm->OnNetworkRequestDone(frame_host, 2);
193 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get())); 438 EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get()));
194 } 439 }
195 440
196 } // namespace extensions 441 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698