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