- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / process_management_browsertest.cc
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/strings/utf_string_conversions.h"
6 #include "chrome/browser/extensions/extension_apitest.h"
7 #include "chrome/browser/extensions/extension_host.h"
8 #include "chrome/browser/extensions/extension_process_manager.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/url_constants.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/site_instance.h"
20 #include "content/public/browser/web_contents.h"
21 #include "extensions/common/switches.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/test/embedded_test_server/embedded_test_server.h"
24
25 using content::NavigationController;
26 using content::WebContents;
27
28 namespace {
29
30 class ProcessManagementTest : public ExtensionBrowserTest {
31  private:
32   // This is needed for testing isolated apps, which are still experimental.
33   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
34     ExtensionBrowserTest::SetUpCommandLine(command_line);
35     command_line->AppendSwitch(
36         extensions::switches::kEnableExperimentalExtensionApis);
37   }
38 };
39
40 }  // namespace
41
42
43 // TODO(nasko): crbug.com/173137
44 #if defined(OS_WIN)
45 #define MAYBE_ProcessOverflow DISABLED_ProcessOverflow
46 #else
47 #define MAYBE_ProcessOverflow ProcessOverflow
48 #endif
49
50 // Ensure that an isolated app never shares a process with WebUIs, non-isolated
51 // extensions, and normal webpages.  None of these should ever comingle
52 // RenderProcessHosts even if we hit the process limit.
53 IN_PROC_BROWSER_TEST_F(ProcessManagementTest, MAYBE_ProcessOverflow) {
54   // Set max renderers to 1 to force running out of processes.
55   content::RenderProcessHost::SetMaxRendererProcessCount(1);
56
57   host_resolver()->AddRule("*", "127.0.0.1");
58   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
59
60   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
61   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
62   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("hosted_app")));
63   ASSERT_TRUE(
64       LoadExtension(test_data_dir_.AppendASCII("api_test/app_process")));
65
66   // The app under test acts on URLs whose host is "localhost",
67   // so the URLs we navigate to must have host "localhost".
68   GURL base_url = embedded_test_server()->GetURL(
69       "/extensions/");
70   GURL::Replacements replace_host;
71   std::string host_str("localhost");  // Must stay in scope with replace_host.
72   replace_host.SetHostStr(host_str);
73   base_url = base_url.ReplaceComponents(replace_host);
74
75   // Load an extension before adding tabs.
76   const extensions::Extension* extension1 = LoadExtension(
77       test_data_dir_.AppendASCII("api_test/browser_action/basics"));
78   ASSERT_TRUE(extension1);
79   GURL extension1_url = extension1->url();
80
81   // Create multiple tabs for each type of renderer that might exist.
82   ui_test_utils::NavigateToURLWithDisposition(
83       browser(), base_url.Resolve("isolated_apps/app1/main.html"),
84       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
85   ui_test_utils::NavigateToURLWithDisposition(
86       browser(), GURL(chrome::kChromeUINewTabURL),
87       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
88   ui_test_utils::NavigateToURLWithDisposition(
89       browser(), base_url.Resolve("hosted_app/main.html"),
90       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
91   ui_test_utils::NavigateToURLWithDisposition(
92       browser(), base_url.Resolve("test_file.html"),
93       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
94
95   ui_test_utils::NavigateToURLWithDisposition(
96       browser(), base_url.Resolve("isolated_apps/app2/main.html"),
97       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
98   ui_test_utils::NavigateToURLWithDisposition(
99       browser(), GURL(chrome::kChromeUINewTabURL),
100       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
101   ui_test_utils::NavigateToURLWithDisposition(
102       browser(), base_url.Resolve("api_test/app_process/path1/empty.html"),
103       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
104   ui_test_utils::NavigateToURLWithDisposition(
105       browser(), base_url.Resolve("test_file_with_body.html"),
106       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
107
108   // Load another copy of isolated app 1.
109   ui_test_utils::NavigateToURLWithDisposition(
110       browser(), base_url.Resolve("isolated_apps/app1/main.html"),
111       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
112
113   // Load another extension.
114   const extensions::Extension* extension2 = LoadExtension(
115       test_data_dir_.AppendASCII("api_test/browser_action/close_background"));
116   ASSERT_TRUE(extension2);
117   GURL extension2_url = extension2->url();
118
119   // Get tab processes.
120   ASSERT_EQ(9, browser()->tab_strip_model()->count());
121   content::RenderProcessHost* isolated1_host =
122       browser()->tab_strip_model()->GetWebContentsAt(0)->GetRenderProcessHost();
123   content::RenderProcessHost* ntp1_host =
124       browser()->tab_strip_model()->GetWebContentsAt(1)->GetRenderProcessHost();
125   content::RenderProcessHost* hosted1_host =
126       browser()->tab_strip_model()->GetWebContentsAt(2)->GetRenderProcessHost();
127   content::RenderProcessHost* web1_host =
128       browser()->tab_strip_model()->GetWebContentsAt(3)->GetRenderProcessHost();
129
130   content::RenderProcessHost* isolated2_host =
131       browser()->tab_strip_model()->GetWebContentsAt(4)->GetRenderProcessHost();
132   content::RenderProcessHost* ntp2_host =
133       browser()->tab_strip_model()->GetWebContentsAt(5)->GetRenderProcessHost();
134   content::RenderProcessHost* hosted2_host =
135       browser()->tab_strip_model()->GetWebContentsAt(6)->GetRenderProcessHost();
136   content::RenderProcessHost* web2_host =
137       browser()->tab_strip_model()->GetWebContentsAt(7)->GetRenderProcessHost();
138
139   content::RenderProcessHost* second_isolated1_host =
140       browser()->tab_strip_model()->GetWebContentsAt(8)->GetRenderProcessHost();
141
142   // Get extension processes.
143   ExtensionProcessManager* process_manager =
144       extensions::ExtensionSystem::Get(browser()->profile())->
145           process_manager();
146   content::RenderProcessHost* extension1_host =
147       process_manager->GetSiteInstanceForURL(extension1_url)->GetProcess();
148   content::RenderProcessHost* extension2_host =
149       process_manager->GetSiteInstanceForURL(extension2_url)->GetProcess();
150
151   // An isolated app only shares with other instances of itself, not other
152   // isolated apps or anything else.
153   EXPECT_EQ(isolated1_host, second_isolated1_host);
154   EXPECT_NE(isolated1_host, isolated2_host);
155   EXPECT_NE(isolated1_host, ntp1_host);
156   EXPECT_NE(isolated1_host, hosted1_host);
157   EXPECT_NE(isolated1_host, web1_host);
158   EXPECT_NE(isolated1_host, extension1_host);
159   EXPECT_NE(isolated2_host, ntp1_host);
160   EXPECT_NE(isolated2_host, hosted1_host);
161   EXPECT_NE(isolated2_host, web1_host);
162   EXPECT_NE(isolated2_host, extension1_host);
163
164   // Everything else is clannish.  WebUI only shares with other WebUI.
165   EXPECT_EQ(ntp1_host, ntp2_host);
166   EXPECT_NE(ntp1_host, hosted1_host);
167   EXPECT_NE(ntp1_host, web1_host);
168   EXPECT_NE(ntp1_host, extension1_host);
169
170   // Hosted apps only share with each other.
171   // Note that hosted2_host's app has the background permission and will use
172   // process-per-site mode, but it should still share with hosted1_host's app.
173   EXPECT_EQ(hosted1_host, hosted2_host);
174   EXPECT_NE(hosted1_host, web1_host);
175   EXPECT_NE(hosted1_host, extension1_host);
176
177   // Web pages only share with each other.
178   EXPECT_EQ(web1_host, web2_host);
179   EXPECT_NE(web1_host, extension1_host);
180
181   // Extensions only share with each other.
182   EXPECT_EQ(extension1_host, extension2_host);
183 }
184
185 // See
186 #if defined(OS_WIN)
187 #define MAYBE_ExtensionProcessBalancing DISABLED_ExtensionProcessBalancing
188 #else
189 #define MAYBE_ExtensionProcessBalancing ExtensionProcessBalancing
190 #endif
191 // Test to verify that the policy of maximum share of extension processes is
192 // properly enforced.
193 IN_PROC_BROWSER_TEST_F(ProcessManagementTest, MAYBE_ExtensionProcessBalancing) {
194   // Set max renderers to 6 so we can expect 2 extension processes to be
195   // allocated.
196   content::RenderProcessHost::SetMaxRendererProcessCount(6);
197
198   host_resolver()->AddRule("*", "127.0.0.1");
199   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
200
201   // The app under test acts on URLs whose host is "localhost",
202   // so the URLs we navigate to must have host "localhost".
203   GURL base_url = embedded_test_server()->GetURL(
204       "/extensions/");
205   GURL::Replacements replace_host;
206   std::string host_str("localhost");  // Must stay in scope with replace_host.
207   replace_host.SetHostStr(host_str);
208   base_url = base_url.ReplaceComponents(replace_host);
209
210   ASSERT_TRUE(LoadExtension(
211       test_data_dir_.AppendASCII("api_test/browser_action/none")));
212   ASSERT_TRUE(LoadExtension(
213       test_data_dir_.AppendASCII("api_test/browser_action/basics")));
214   ASSERT_TRUE(LoadExtension(
215       test_data_dir_.AppendASCII("api_test/browser_action/remove_popup")));
216   ASSERT_TRUE(LoadExtension(
217       test_data_dir_.AppendASCII("api_test/browser_action/add_popup")));
218   ASSERT_TRUE(LoadExtension(
219       test_data_dir_.AppendASCII("api_test/browser_action/no_icon")));
220   ASSERT_TRUE(LoadExtension(
221       test_data_dir_.AppendASCII("isolated_apps/app1")));
222   ASSERT_TRUE(LoadExtension(
223       test_data_dir_.AppendASCII("api_test/management/test")));
224
225   ui_test_utils::NavigateToURLWithDisposition(
226       browser(), base_url.Resolve("isolated_apps/app1/main.html"),
227       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
228
229   ui_test_utils::NavigateToURLWithDisposition(
230       browser(), base_url.Resolve("api_test/management/test/basics.html"),
231       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
232
233   std::set<int> process_ids;
234   Profile* profile = browser()->profile();
235   ExtensionProcessManager* epm = extensions::ExtensionSystem::Get(profile)->
236       process_manager();
237   for (ExtensionProcessManager::const_iterator iter =
238            epm->background_hosts().begin();
239        iter != epm->background_hosts().end(); ++iter) {
240     process_ids.insert((*iter)->render_process_host()->GetID());
241   }
242
243   // We've loaded 5 extensions with background pages, 1 extension without
244   // background page, and one isolated app. We expect only 2 unique processes
245   // hosting those extensions.
246   ExtensionService* service =
247       extensions::ExtensionSystem::Get(profile)->extension_service();
248
249   EXPECT_GE((size_t) 6, service->process_map()->size());
250   EXPECT_EQ((size_t) 2, process_ids.size());
251 }